// 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. // Package time provides functionality for measuring and displaying time. package time // 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 // 2006 is 2006 Month, Day int // Jan-2 is 1, 2 Hour, Minute, Second int // 15:04:05 is 15, 4, 5. Nanosecond int // Fractional second. ZoneOffset int // seconds east of UTC, e.g. -7*60*60 for -0700 Zone string // e.g., "MST" } 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) // 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 } // NanosecondsToUTC converts nsec, in number of nanoseconds since the Unix epoch, // into a parsed Time value in the UTC time zone. func NanosecondsToUTC(nsec int64) *Time { // This one calls SecondsToUTC rather than the other way around because // that admits a much larger span of time; NanosecondsToUTC is limited // to a few hundred years only. t := SecondsToUTC(nsec / 1e9) t.Nanosecond = int(nsec % 1e9) return t } // UTC returns the current time as a parsed Time value in the UTC time zone. func UTC() *Time { return NanosecondsToUTC(Nanoseconds()) } // 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 } // NanosecondsToLocalTime converts nsec, in number of nanoseconds since the Unix epoch, // into a parsed Time value in the local time zone. func NanosecondsToLocalTime(nsec int64) *Time { t := SecondsToLocalTime(nsec / 1e9) t.Nanosecond = int(nsec % 1e9) return t } // LocalTime returns the current time as a parsed Time value in the local time zone. func LocalTime() *Time { return NanosecondsToLocalTime(Nanoseconds()) } // 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 } // Nanoseconds returns the number of nanoseconds since January 1, 1970 represented by the // parsed Time value. func (t *Time) Nanoseconds() int64 { return t.Seconds()*1e9 + int64(t.Nanosecond) } // Weekday returns the time's day of the week. Sunday is day 0. func (t *Time) Weekday() int { sec := t.Seconds() + int64(t.ZoneOffset) day := sec / secondsPerDay sec -= day * secondsPerDay if sec < 0 { day-- } // Day 0 = January 1, 1970 was a Thursday weekday := int((day + Thursday) % 7) if weekday < 0 { weekday += 7 } return weekday }