// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The time package provides functionality for measuring and // displaying time. package time import ( "os"; ) // Seconds reports the number of seconds since the Unix epoch, // January 1, 1970 00:00:00 UTC. func Seconds() int64 { sec, _, err := os.Time(); if err != nil { panic("time: os.Time: ", err.String()) } return sec; } // Nanoseconds reports the number of nanoseconds since the Unix epoch, // January 1, 1970 00:00:00 UTC. func Nanoseconds() int64 { sec, nsec, err := os.Time(); if err != nil { panic("time: os.Time: ", err.String()) } return sec*1e9 + nsec; } // Days of the week. const ( Sunday = iota; Monday; Tuesday; Wednesday; Thursday; Friday; Saturday; ) // Time is the struct representing a parsed time value. type Time struct { Year int64; // 2008 is 2008 Month, Day int; // Sep-17 is 9, 17 Hour, Minute, Second int; // 10:43:12 is 10, 43, 12 Weekday int; // Sunday, Monday, ... ZoneOffset int; // seconds east of UTC Zone string; } var nonleapyear = []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} var leapyear = []int{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} func months(year int64) []int { if year%4 == 0 && (year%100 != 0 || year%400 == 0) { return leapyear } return nonleapyear; } const ( secondsPerDay = 24 * 60 * 60; daysPer400Years = 365*400 + 97; daysPer100Years = 365*100 + 24; daysPer4Years = 365*4 + 1; days1970To2001 = 31*365 + 8; ) // SecondsToUTC converts sec, in number of seconds since the Unix epoch, // into a parsed Time value in the UTC time zone. func SecondsToUTC(sec int64) *Time { t := new(Time); // Split into time and day. day := sec / secondsPerDay; sec -= day * secondsPerDay; if sec < 0 { day--; sec += secondsPerDay; } // Time t.Hour = int(sec / 3600); t.Minute = int((sec / 60) % 60); t.Second = int(sec % 60); // Day 0 = January 1, 1970 was a Thursday t.Weekday = int((day + Thursday) % 7); if t.Weekday < 0 { t.Weekday += 7 } // Change day from 0 = 1970 to 0 = 2001, // to make leap year calculations easier // (2001 begins 4-, 100-, and 400-year cycles ending in a leap year.) day -= days1970To2001; year := int64(2001); if day < 0 { // Go back enough 400 year cycles to make day positive. n := -day/daysPer400Years + 1; year -= 400 * n; day += daysPer400Years * n; } // Cut off 400 year cycles. n := day / daysPer400Years; year += 400 * n; day -= daysPer400Years * n; // Cut off 100-year cycles n = day / daysPer100Years; if n > 3 { // happens on last day of 400th year n = 3 } year += 100 * n; day -= daysPer100Years * n; // Cut off 4-year cycles n = day / daysPer4Years; if n > 24 { // happens on last day of 100th year n = 24 } year += 4 * n; day -= daysPer4Years * n; // Cut off non-leap years. n = day / 365; if n > 3 { // happens on last day of 4th year n = 3 } year += n; day -= 365 * n; t.Year = year; // If someone ever needs yearday, // tyearday = day (+1?) months := months(year); var m int; yday := int(day); for m = 0; m < 12 && yday >= months[m]; m++ { yday -= months[m] } t.Month = m + 1; t.Day = yday + 1; t.Zone = "UTC"; return t; } // UTC returns the current time as a parsed Time value in the UTC time zone. func UTC() *Time { return SecondsToUTC(Seconds()) } // SecondsToLocalTime converts sec, in number of seconds since the Unix epoch, // into a parsed Time value in the local time zone. func SecondsToLocalTime(sec int64) *Time { z, offset := lookupTimezone(sec); t := SecondsToUTC(sec + int64(offset)); t.Zone = z; t.ZoneOffset = offset; return t; } // LocalTime returns the current time as a parsed Time value in the local time zone. func LocalTime() *Time { return SecondsToLocalTime(Seconds()) } // Seconds returns the number of seconds since January 1, 1970 represented by the // parsed Time value. func (t *Time) Seconds() int64 { // First, accumulate days since January 1, 2001. // Using 2001 instead of 1970 makes the leap-year // handling easier (see SecondsToUTC), because // it is at the beginning of the 4-, 100-, and 400-year cycles. day := int64(0); // Rewrite year to be >= 2001. year := t.Year; if year < 2001 { n := (2001-year)/400 + 1; year += 400 * n; day -= daysPer400Years * n; } // Add in days from 400-year cycles. n := (year - 2001) / 400; year -= 400 * n; day += daysPer400Years * n; // Add in 100-year cycles. n = (year - 2001) / 100; year -= 100 * n; day += daysPer100Years * n; // Add in 4-year cycles. n = (year - 2001) / 4; year -= 4 * n; day += daysPer4Years * n; // Add in non-leap years. n = year - 2001; day += 365 * n; // Add in days this year. months := months(t.Year); for m := 0; m < t.Month-1; m++ { day += int64(months[m]) } day += int64(t.Day - 1); // Convert days to seconds since January 1, 2001. sec := day * secondsPerDay; // Add in time elapsed today. sec += int64(t.Hour) * 3600; sec += int64(t.Minute) * 60; sec += int64(t.Second); // Convert from seconds since 2001 to seconds since 1970. sec += days1970To2001 * secondsPerDay; // Account for local time zone. sec -= int64(t.ZoneOffset); return sec; } var longDayNames = []string{ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", } var shortDayNames = []string{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", } var shortMonthNames = []string{ "---", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", } func copy(dst []byte, s string) { for i := 0; i < len(s); i++ { dst[i] = s[i] } } func decimal(dst []byte, n int) { if n < 0 { n = 0 } for i := len(dst) - 1; i >= 0; i-- { dst[i] = byte(n%10 + '0'); n /= 10; } } func addString(buf []byte, bp int, s string) int { n := len(s); copy(buf[bp:bp+n], s); return bp + n; } // Just enough of strftime to implement the date formats below. // Not exported. func format(t *Time, fmt string) string { buf := make([]byte, 128); bp := 0; for i := 0; i < len(fmt); i++ { if fmt[i] == '%' { i++; switch fmt[i] { case 'A': // %A full weekday name bp = addString(buf, bp, longDayNames[t.Weekday]) case 'a': // %a abbreviated weekday name bp = addString(buf, bp, shortDayNames[t.Weekday]) case 'b': // %b abbreviated month name bp = addString(buf, bp, shortMonthNames[t.Month]) case 'd': // %d day of month (01-31) decimal(buf[bp:bp+2], t.Day); bp += 2; case 'e': // %e day of month ( 1-31) if t.Day >= 10 { decimal(buf[bp:bp+2], t.Day) } else { buf[bp] = ' '; buf[bp+1] = byte(t.Day + '0'); } bp += 2; case 'H': // %H hour 00-23 decimal(buf[bp:bp+2], t.Hour); bp += 2; case 'M': // %M minute 00-59 decimal(buf[bp:bp+2], t.Minute); bp += 2; case 'S': // %S second 00-59 decimal(buf[bp:bp+2], t.Second); bp += 2; case 'Y': // %Y year 2008 decimal(buf[bp:bp+4], int(t.Year)); bp += 4; case 'y': // %y year 08 decimal(buf[bp:bp+2], int(t.Year%100)); bp += 2; case 'Z': bp = addString(buf, bp, t.Zone) default: buf[bp] = '%'; buf[bp+1] = fmt[i]; bp += 2; } } else { buf[bp] = fmt[i]; bp++; } } return string(buf[0:bp]); } // Asctime formats the parsed time value in the style of // ANSI C asctime: Sun Nov 6 08:49:37 1994 func (t *Time) Asctime() string { return format(t, "%a %b %e %H:%M:%S %Y") } // RFC850 formats the parsed time value in the style of // RFC 850: Sunday, 06-Nov-94 08:49:37 UTC func (t *Time) RFC850() string { return format(t, "%A, %d-%b-%y %H:%M:%S %Z") } // RFC1123 formats the parsed time value in the style of // RFC 1123: Sun, 06 Nov 1994 08:49:37 UTC func (t *Time) RFC1123() string { return format(t, "%a, %d %b %Y %H:%M:%S %Z") } // String formats the parsed time value in the style of // date(1) - Sun Nov 6 08:49:37 UTC 1994 func (t *Time) String() string { return format(t, "%a %b %e %H:%M:%S %Z %Y") }