Update to current version of Go library.
[platform/upstream/gcc.git] / libgo / go / time / time.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package time provides functionality for measuring and displaying time.
6 package time
7
8 // Days of the week.
9 const (
10         Sunday = iota
11         Monday
12         Tuesday
13         Wednesday
14         Thursday
15         Friday
16         Saturday
17 )
18
19 // Time is the struct representing a parsed time value.
20 type Time struct {
21         Year                 int64  // 2006 is 2006
22         Month, Day           int    // Jan-2 is 1, 2
23         Hour, Minute, Second int    // 15:04:05 is 15, 4, 5.
24         Weekday              int    // Sunday, Monday, ...
25         ZoneOffset           int    // seconds east of UTC, e.g. -7*60*60 for -0700
26         Zone                 string // e.g., "MST"
27 }
28
29 var nonleapyear = []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
30 var leapyear = []int{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
31
32 func months(year int64) []int {
33         if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
34                 return leapyear
35         }
36         return nonleapyear
37 }
38
39 const (
40         secondsPerDay   = 24 * 60 * 60
41         daysPer400Years = 365*400 + 97
42         daysPer100Years = 365*100 + 24
43         daysPer4Years   = 365*4 + 1
44         days1970To2001  = 31*365 + 8
45 )
46
47 // SecondsToUTC converts sec, in number of seconds since the Unix epoch,
48 // into a parsed Time value in the UTC time zone.
49 func SecondsToUTC(sec int64) *Time {
50         t := new(Time)
51
52         // Split into time and day.
53         day := sec / secondsPerDay
54         sec -= day * secondsPerDay
55         if sec < 0 {
56                 day--
57                 sec += secondsPerDay
58         }
59
60         // Time
61         t.Hour = int(sec / 3600)
62         t.Minute = int((sec / 60) % 60)
63         t.Second = int(sec % 60)
64
65         // Day 0 = January 1, 1970 was a Thursday
66         t.Weekday = int((day + Thursday) % 7)
67         if t.Weekday < 0 {
68                 t.Weekday += 7
69         }
70
71         // Change day from 0 = 1970 to 0 = 2001,
72         // to make leap year calculations easier
73         // (2001 begins 4-, 100-, and 400-year cycles ending in a leap year.)
74         day -= days1970To2001
75
76         year := int64(2001)
77         if day < 0 {
78                 // Go back enough 400 year cycles to make day positive.
79                 n := -day/daysPer400Years + 1
80                 year -= 400 * n
81                 day += daysPer400Years * n
82         }
83
84         // Cut off 400 year cycles.
85         n := day / daysPer400Years
86         year += 400 * n
87         day -= daysPer400Years * n
88
89         // Cut off 100-year cycles
90         n = day / daysPer100Years
91         if n > 3 { // happens on last day of 400th year
92                 n = 3
93         }
94         year += 100 * n
95         day -= daysPer100Years * n
96
97         // Cut off 4-year cycles
98         n = day / daysPer4Years
99         if n > 24 { // happens on last day of 100th year
100                 n = 24
101         }
102         year += 4 * n
103         day -= daysPer4Years * n
104
105         // Cut off non-leap years.
106         n = day / 365
107         if n > 3 { // happens on last day of 4th year
108                 n = 3
109         }
110         year += n
111         day -= 365 * n
112
113         t.Year = year
114
115         // If someone ever needs yearday,
116         // tyearday = day (+1?)
117
118         months := months(year)
119         var m int
120         yday := int(day)
121         for m = 0; m < 12 && yday >= months[m]; m++ {
122                 yday -= months[m]
123         }
124         t.Month = m + 1
125         t.Day = yday + 1
126         t.Zone = "UTC"
127
128         return t
129 }
130
131 // UTC returns the current time as a parsed Time value in the UTC time zone.
132 func UTC() *Time { return SecondsToUTC(Seconds()) }
133
134 // SecondsToLocalTime converts sec, in number of seconds since the Unix epoch,
135 // into a parsed Time value in the local time zone.
136 func SecondsToLocalTime(sec int64) *Time {
137         z, offset := lookupTimezone(sec)
138         t := SecondsToUTC(sec + int64(offset))
139         t.Zone = z
140         t.ZoneOffset = offset
141         return t
142 }
143
144 // LocalTime returns the current time as a parsed Time value in the local time zone.
145 func LocalTime() *Time { return SecondsToLocalTime(Seconds()) }
146
147 // Seconds returns the number of seconds since January 1, 1970 represented by the
148 // parsed Time value.
149 func (t *Time) Seconds() int64 {
150         // First, accumulate days since January 1, 2001.
151         // Using 2001 instead of 1970 makes the leap-year
152         // handling easier (see SecondsToUTC), because
153         // it is at the beginning of the 4-, 100-, and 400-year cycles.
154         day := int64(0)
155
156         // Rewrite year to be >= 2001.
157         year := t.Year
158         if year < 2001 {
159                 n := (2001-year)/400 + 1
160                 year += 400 * n
161                 day -= daysPer400Years * n
162         }
163
164         // Add in days from 400-year cycles.
165         n := (year - 2001) / 400
166         year -= 400 * n
167         day += daysPer400Years * n
168
169         // Add in 100-year cycles.
170         n = (year - 2001) / 100
171         year -= 100 * n
172         day += daysPer100Years * n
173
174         // Add in 4-year cycles.
175         n = (year - 2001) / 4
176         year -= 4 * n
177         day += daysPer4Years * n
178
179         // Add in non-leap years.
180         n = year - 2001
181         day += 365 * n
182
183         // Add in days this year.
184         months := months(t.Year)
185         for m := 0; m < t.Month-1; m++ {
186                 day += int64(months[m])
187         }
188         day += int64(t.Day - 1)
189
190         // Convert days to seconds since January 1, 2001.
191         sec := day * secondsPerDay
192
193         // Add in time elapsed today.
194         sec += int64(t.Hour) * 3600
195         sec += int64(t.Minute) * 60
196         sec += int64(t.Second)
197
198         // Convert from seconds since 2001 to seconds since 1970.
199         sec += days1970To2001 * secondsPerDay
200
201         // Account for local time zone.
202         sec -= int64(t.ZoneOffset)
203         return sec
204 }