| // 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"; | |
| "time" | |
| ) | |
| // Seconds reports the number of seconds since the Unix epoch, | |
| // January 1, 1970 00:00:00 UTC. | |
| func Seconds() int64 { | |
| sec, nsec, 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 west 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; | |
| } else { | |
| // Cut off 400 year cycles. | |
| n := day/daysPer400Years; | |
| year += 400*n; | |
| day -= daysPer400Years*n; | |
| } | |
| // Cut off 100-year cycles | |
| n := day/daysPer100Years; | |
| year += 100*n; | |
| day -= daysPer100Years*n; | |
| // Cut off 4-year cycles | |
| n = day/daysPer4Years; | |
| year += 4*n; | |
| day -= daysPer4Years*n; | |
| // Cut off non-leap years. | |
| n = day/365; | |
| 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, err := time.lookupTimezone(sec); | |
| if err != nil { | |
| return SecondsToUTC(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-1]); | |
| 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") | |
| } |