Source file src/pkg/time/time.go
1
2
3
4
5
6
7
8 package time
9
10 import "errors"
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 type Time struct {
35
36
37 sec int64
38
39
40
41
42 nsec int32
43
44
45
46
47
48
49 loc *Location
50 }
51
52
53 func (t Time) After(u Time) bool {
54 return t.sec > u.sec || t.sec == u.sec && t.nsec > u.nsec
55 }
56
57
58 func (t Time) Before(u Time) bool {
59 return t.sec < u.sec || t.sec == u.sec && t.nsec < u.nsec
60 }
61
62
63
64
65
66
67 func (t Time) Equal(u Time) bool {
68 return t.sec == u.sec && t.nsec == u.nsec
69 }
70
71
72 type Month int
73
74 const (
75 January Month = 1 + iota
76 February
77 March
78 April
79 May
80 June
81 July
82 August
83 September
84 October
85 November
86 December
87 )
88
89 var months = [...]string{
90 "January",
91 "February",
92 "March",
93 "April",
94 "May",
95 "June",
96 "July",
97 "August",
98 "September",
99 "October",
100 "November",
101 "December",
102 }
103
104
105 func (m Month) String() string { return months[m-1] }
106
107
108 type Weekday int
109
110 const (
111 Sunday Weekday = iota
112 Monday
113 Tuesday
114 Wednesday
115 Thursday
116 Friday
117 Saturday
118 )
119
120 var days = [...]string{
121 "Sunday",
122 "Monday",
123 "Tuesday",
124 "Wednesday",
125 "Thursday",
126 "Friday",
127 "Saturday",
128 }
129
130
131 func (d Weekday) String() string { return days[d] }
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 const (
214
215
216
217 absoluteZeroYear = -292277022399
218
219
220
221 internalYear = 1
222
223
224 unixYear = 1970
225
226
227 absoluteToInternal int64 = (absoluteZeroYear - internalYear) * 365.2425 * secondsPerDay
228 internalToAbsolute = -absoluteToInternal
229
230 unixToInternal int64 = (1969*365 + 1969/4 - 1969/100 + 1969/400) * secondsPerDay
231 internalToUnix int64 = -unixToInternal
232 )
233
234
235
236 func (t Time) IsZero() bool {
237 return t.sec == 0 && t.nsec == 0
238 }
239
240
241
242 func (t Time) abs() uint64 {
243 l := t.loc
244
245 if l == nil || l == &localLoc {
246 l = l.get()
247 }
248 sec := t.sec + internalToUnix
249 if l != &utcLoc {
250 if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
251 sec += int64(l.cacheZone.offset)
252 } else {
253 _, offset, _, _, _ := l.lookup(sec)
254 sec += int64(offset)
255 }
256 }
257 return uint64(sec + (unixToInternal + internalToAbsolute))
258 }
259
260
261
262 func (t Time) locabs() (name string, offset int, abs uint64) {
263 l := t.loc
264 if l == nil || l == &localLoc {
265 l = l.get()
266 }
267
268 sec := t.sec + internalToUnix
269 if l != &utcLoc {
270 if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
271 name = l.cacheZone.name
272 offset = l.cacheZone.offset
273 } else {
274 name, offset, _, _, _ = l.lookup(sec)
275 }
276 sec += int64(offset)
277 } else {
278 name = "UTC"
279 }
280 abs = uint64(sec + (unixToInternal + internalToAbsolute))
281 return
282 }
283
284
285 func (t Time) Date() (year int, month Month, day int) {
286 year, month, day, _ = t.date(true)
287 return
288 }
289
290
291 func (t Time) Year() int {
292 year, _, _, _ := t.date(false)
293 return year
294 }
295
296
297 func (t Time) Month() Month {
298 _, month, _, _ := t.date(true)
299 return month
300 }
301
302
303 func (t Time) Day() int {
304 _, _, day, _ := t.date(true)
305 return day
306 }
307
308
309 func (t Time) Weekday() Weekday {
310 return absWeekday(t.abs())
311 }
312
313
314 func absWeekday(abs uint64) Weekday {
315
316 sec := (abs + uint64(Monday)*secondsPerDay) % secondsPerWeek
317 return Weekday(int(sec) / secondsPerDay)
318 }
319
320
321
322
323
324 func (t Time) ISOWeek() (year, week int) {
325 year, month, day, yday := t.date(true)
326 wday := int(t.Weekday()+6) % 7
327 const (
328 Mon int = iota
329 Tue
330 Wed
331 Thu
332 Fri
333 Sat
334 Sun
335 )
336
337
338
339
340
341
342 week = (yday - wday + 7) / 7
343
344
345
346
347
348 jan1wday := (wday - yday + 7*53) % 7
349 if Tue <= jan1wday && jan1wday <= Thu {
350 week++
351 }
352
353
354
355 if week == 0 {
356 year--
357 week = 52
358
359
360
361 if jan1wday == Fri || (jan1wday == Sat && isLeap(year)) {
362 week++
363 }
364 }
365
366
367
368
369 if month == December && day >= 29 && wday < Thu {
370 if dec31wday := (wday + 31 - day) % 7; Mon <= dec31wday && dec31wday <= Wed {
371 year++
372 week = 1
373 }
374 }
375
376 return
377 }
378
379
380 func (t Time) Clock() (hour, min, sec int) {
381 return absClock(t.abs())
382 }
383
384
385 func absClock(abs uint64) (hour, min, sec int) {
386 sec = int(abs % secondsPerDay)
387 hour = sec / secondsPerHour
388 sec -= hour * secondsPerHour
389 min = sec / secondsPerMinute
390 sec -= min * secondsPerMinute
391 return
392 }
393
394
395 func (t Time) Hour() int {
396 return int(t.abs()%secondsPerDay) / secondsPerHour
397 }
398
399
400 func (t Time) Minute() int {
401 return int(t.abs()%secondsPerHour) / secondsPerMinute
402 }
403
404
405 func (t Time) Second() int {
406 return int(t.abs() % secondsPerMinute)
407 }
408
409
410
411 func (t Time) Nanosecond() int {
412 return int(t.nsec)
413 }
414
415
416
417 func (t Time) YearDay() int {
418 _, _, _, yday := t.date(false)
419 return yday + 1
420 }
421
422
423
424
425 type Duration int64
426
427
428
429
430
431
432
433
434
435
436
437
438 const (
439 Nanosecond Duration = 1
440 Microsecond = 1000 * Nanosecond
441 Millisecond = 1000 * Microsecond
442 Second = 1000 * Millisecond
443 Minute = 60 * Second
444 Hour = 60 * Minute
445 )
446
447
448
449
450
451
452 func (d Duration) String() string {
453
454 var buf [32]byte
455 w := len(buf)
456
457 u := uint64(d)
458 neg := d < 0
459 if neg {
460 u = -u
461 }
462
463 if u < uint64(Second) {
464
465
466 var (
467 prec int
468 unit byte
469 )
470 switch {
471 case u == 0:
472 return "0"
473 case u < uint64(Microsecond):
474
475 prec = 0
476 unit = 'n'
477 case u < uint64(Millisecond):
478
479 prec = 3
480 unit = 'u'
481 default:
482
483 prec = 6
484 unit = 'm'
485 }
486 w -= 2
487 buf[w] = unit
488 buf[w+1] = 's'
489 w, u = fmtFrac(buf[:w], u, prec)
490 w = fmtInt(buf[:w], u)
491 } else {
492 w--
493 buf[w] = 's'
494
495 w, u = fmtFrac(buf[:w], u, 9)
496
497
498 w = fmtInt(buf[:w], u%60)
499 u /= 60
500
501
502 if u > 0 {
503 w--
504 buf[w] = 'm'
505 w = fmtInt(buf[:w], u%60)
506 u /= 60
507
508
509
510 if u > 0 {
511 w--
512 buf[w] = 'h'
513 w = fmtInt(buf[:w], u)
514 }
515 }
516 }
517
518 if neg {
519 w--
520 buf[w] = '-'
521 }
522
523 return string(buf[w:])
524 }
525
526
527
528
529
530 func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) {
531
532 w := len(buf)
533 print := false
534 for i := 0; i < prec; i++ {
535 digit := v % 10
536 print = print || digit != 0
537 if print {
538 w--
539 buf[w] = byte(digit) + '0'
540 }
541 v /= 10
542 }
543 if print {
544 w--
545 buf[w] = '.'
546 }
547 return w, v
548 }
549
550
551
552 func fmtInt(buf []byte, v uint64) int {
553 w := len(buf)
554 if v == 0 {
555 w--
556 buf[w] = '0'
557 } else {
558 for v > 0 {
559 w--
560 buf[w] = byte(v%10) + '0'
561 v /= 10
562 }
563 }
564 return w
565 }
566
567
568 func (d Duration) Nanoseconds() int64 { return int64(d) }
569
570
571
572
573
574
575
576
577
578
579
580 func (d Duration) Seconds() float64 {
581 sec := d / Second
582 nsec := d % Second
583 return float64(sec) + float64(nsec)*1e-9
584 }
585
586
587 func (d Duration) Minutes() float64 {
588 min := d / Minute
589 nsec := d % Minute
590 return float64(min) + float64(nsec)*(1e-9/60)
591 }
592
593
594 func (d Duration) Hours() float64 {
595 hour := d / Hour
596 nsec := d % Hour
597 return float64(hour) + float64(nsec)*(1e-9/60/60)
598 }
599
600
601 func (t Time) Add(d Duration) Time {
602 t.sec += int64(d / 1e9)
603 t.nsec += int32(d % 1e9)
604 if t.nsec >= 1e9 {
605 t.sec++
606 t.nsec -= 1e9
607 } else if t.nsec < 0 {
608 t.sec--
609 t.nsec += 1e9
610 }
611 return t
612 }
613
614
615
616 func (t Time) Sub(u Time) Duration {
617 return Duration(t.sec-u.sec)*Second + Duration(t.nsec-u.nsec)
618 }
619
620
621
622 func Since(t Time) Duration {
623 return Now().Sub(t)
624 }
625
626
627
628
629
630
631
632
633
634 func (t Time) AddDate(years int, months int, days int) Time {
635 year, month, day := t.Date()
636 hour, min, sec := t.Clock()
637 return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.loc)
638 }
639
640 const (
641 secondsPerMinute = 60
642 secondsPerHour = 60 * 60
643 secondsPerDay = 24 * secondsPerHour
644 secondsPerWeek = 7 * secondsPerDay
645 daysPer400Years = 365*400 + 97
646 daysPer100Years = 365*100 + 24
647 daysPer4Years = 365*4 + 1
648 days1970To2001 = 31*365 + 8
649 )
650
651
652
653 func (t Time) date(full bool) (year int, month Month, day int, yday int) {
654 return absDate(t.abs(), full)
655 }
656
657
658 func absDate(abs uint64, full bool) (year int, month Month, day int, yday int) {
659
660 d := abs / secondsPerDay
661
662
663 n := d / daysPer400Years
664 y := 400 * n
665 d -= daysPer400Years * n
666
667
668
669
670
671 n = d / daysPer100Years
672 n -= n >> 2
673 y += 100 * n
674 d -= daysPer100Years * n
675
676
677
678
679 n = d / daysPer4Years
680 y += 4 * n
681 d -= daysPer4Years * n
682
683
684
685
686
687 n = d / 365
688 n -= n >> 2
689 y += n
690 d -= 365 * n
691
692 year = int(int64(y) + absoluteZeroYear)
693 yday = int(d)
694
695 if !full {
696 return
697 }
698
699 day = yday
700 if isLeap(year) {
701
702 switch {
703 case day > 31+29-1:
704
705 day--
706 case day == 31+29-1:
707
708 month = February
709 day = 29
710 return
711 }
712 }
713
714
715
716 month = Month(day / 31)
717 end := int(daysBefore[month+1])
718 var begin int
719 if day >= end {
720 month++
721 begin = end
722 } else {
723 begin = int(daysBefore[month])
724 }
725
726 month++
727 day = day - begin + 1
728 return
729 }
730
731
732
733
734 var daysBefore = [...]int32{
735 0,
736 31,
737 31 + 28,
738 31 + 28 + 31,
739 31 + 28 + 31 + 30,
740 31 + 28 + 31 + 30 + 31,
741 31 + 28 + 31 + 30 + 31 + 30,
742 31 + 28 + 31 + 30 + 31 + 30 + 31,
743 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
744 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
745 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
746 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
747 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
748 }
749
750 func daysIn(m Month, year int) int {
751 if m == February && isLeap(year) {
752 return 29
753 }
754 return int(daysBefore[m] - daysBefore[m-1])
755 }
756
757
758 func now() (sec int64, nsec int32)
759
760
761 func Now() Time {
762 sec, nsec := now()
763 return Time{sec + unixToInternal, nsec, Local}
764 }
765
766
767 func (t Time) UTC() Time {
768 t.loc = UTC
769 return t
770 }
771
772
773 func (t Time) Local() Time {
774 t.loc = Local
775 return t
776 }
777
778
779
780
781 func (t Time) In(loc *Location) Time {
782 if loc == nil {
783 panic("time: missing Location in call to Time.In")
784 }
785 t.loc = loc
786 return t
787 }
788
789
790 func (t Time) Location() *Location {
791 l := t.loc
792 if l == nil {
793 l = UTC
794 }
795 return l
796 }
797
798
799
800 func (t Time) Zone() (name string, offset int) {
801 name, offset, _, _, _ = t.loc.lookup(t.sec + internalToUnix)
802 return
803 }
804
805
806
807 func (t Time) Unix() int64 {
808 return t.sec + internalToUnix
809 }
810
811
812
813
814
815 func (t Time) UnixNano() int64 {
816 return (t.sec+internalToUnix)*1e9 + int64(t.nsec)
817 }
818
819 const timeGobVersion byte = 1
820
821
822 func (t Time) GobEncode() ([]byte, error) {
823 var offsetMin int16
824
825 if t.Location() == &utcLoc {
826 offsetMin = -1
827 } else {
828 _, offset := t.Zone()
829 if offset%60 != 0 {
830 return nil, errors.New("Time.GobEncode: zone offset has fractional minute")
831 }
832 offset /= 60
833 if offset < -32768 || offset == -1 || offset > 32767 {
834 return nil, errors.New("Time.GobEncode: unexpected zone offset")
835 }
836 offsetMin = int16(offset)
837 }
838
839 enc := []byte{
840 timeGobVersion,
841 byte(t.sec >> 56),
842 byte(t.sec >> 48),
843 byte(t.sec >> 40),
844 byte(t.sec >> 32),
845 byte(t.sec >> 24),
846 byte(t.sec >> 16),
847 byte(t.sec >> 8),
848 byte(t.sec),
849 byte(t.nsec >> 24),
850 byte(t.nsec >> 16),
851 byte(t.nsec >> 8),
852 byte(t.nsec),
853 byte(offsetMin >> 8),
854 byte(offsetMin),
855 }
856
857 return enc, nil
858 }
859
860
861 func (t *Time) GobDecode(buf []byte) error {
862 if len(buf) == 0 {
863 return errors.New("Time.GobDecode: no data")
864 }
865
866 if buf[0] != timeGobVersion {
867 return errors.New("Time.GobDecode: unsupported version")
868 }
869
870 if len(buf) != 1+ 8+ 4+ 2 {
871 return errors.New("Time.GobDecode: invalid length")
872 }
873
874 buf = buf[1:]
875 t.sec = int64(buf[7]) | int64(buf[6])<<8 | int64(buf[5])<<16 | int64(buf[4])<<24 |
876 int64(buf[3])<<32 | int64(buf[2])<<40 | int64(buf[1])<<48 | int64(buf[0])<<56
877
878 buf = buf[8:]
879 t.nsec = int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24
880
881 buf = buf[4:]
882 offset := int(int16(buf[1])|int16(buf[0])<<8) * 60
883
884 if offset == -1*60 {
885 t.loc = &utcLoc
886 } else if _, localoff, _, _, _ := Local.lookup(t.sec + internalToUnix); offset == localoff {
887 t.loc = Local
888 } else {
889 t.loc = FixedZone("", offset)
890 }
891
892 return nil
893 }
894
895
896
897 func (t Time) MarshalJSON() ([]byte, error) {
898 if y := t.Year(); y < 0 || y >= 10000 {
899 return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
900 }
901 return []byte(t.Format(`"` + RFC3339Nano + `"`)), nil
902 }
903
904
905
906 func (t *Time) UnmarshalJSON(data []byte) (err error) {
907
908 *t, err = Parse(`"`+RFC3339+`"`, string(data))
909 return
910 }
911
912
913
914
915 func Unix(sec int64, nsec int64) Time {
916 if nsec < 0 || nsec >= 1e9 {
917 n := nsec / 1e9
918 sec += n
919 nsec -= n * 1e9
920 if nsec < 0 {
921 nsec += 1e9
922 sec--
923 }
924 }
925 return Time{sec + unixToInternal, int32(nsec), Local}
926 }
927
928 func isLeap(year int) bool {
929 return year%4 == 0 && (year%100 != 0 || year%400 == 0)
930 }
931
932
933
934
935 func norm(hi, lo, base int) (nhi, nlo int) {
936 if lo < 0 {
937 n := (-lo-1)/base + 1
938 hi -= n
939 lo += n * base
940 }
941 if lo >= base {
942 n := lo / base
943 hi += n
944 lo -= n * base
945 }
946 return hi, lo
947 }
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965 func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {
966 if loc == nil {
967 panic("time: missing Location in call to Date")
968 }
969
970
971 m := int(month) - 1
972 year, m = norm(year, m, 12)
973 month = Month(m) + 1
974
975
976 sec, nsec = norm(sec, nsec, 1e9)
977 min, sec = norm(min, sec, 60)
978 hour, min = norm(hour, min, 60)
979 day, hour = norm(day, hour, 24)
980
981 y := uint64(int64(year) - absoluteZeroYear)
982
983
984
985
986 n := y / 400
987 y -= 400 * n
988 d := daysPer400Years * n
989
990
991 n = y / 100
992 y -= 100 * n
993 d += daysPer100Years * n
994
995
996 n = y / 4
997 y -= 4 * n
998 d += daysPer4Years * n
999
1000
1001 n = y
1002 d += 365 * n
1003
1004
1005 d += uint64(daysBefore[month-1])
1006 if isLeap(year) && month >= March {
1007 d++
1008 }
1009
1010
1011 d += uint64(day - 1)
1012
1013
1014 abs := d * secondsPerDay
1015 abs += uint64(hour*secondsPerHour + min*secondsPerMinute + sec)
1016
1017 unix := int64(abs) + (absoluteToInternal + internalToUnix)
1018
1019
1020
1021
1022
1023 _, offset, _, start, end := loc.lookup(unix)
1024 if offset != 0 {
1025 switch utc := unix - int64(offset); {
1026 case utc < start:
1027 _, offset, _, _, _ = loc.lookup(start - 1)
1028 case utc >= end:
1029 _, offset, _, _, _ = loc.lookup(end)
1030 }
1031 unix -= int64(offset)
1032 }
1033
1034 return Time{unix + unixToInternal, int32(nsec), loc}
1035 }
1036
1037
1038
1039 func (t Time) Truncate(d Duration) Time {
1040 if d <= 0 {
1041 return t
1042 }
1043 _, r := div(t, d)
1044 return t.Add(-r)
1045 }
1046
1047
1048
1049
1050 func (t Time) Round(d Duration) Time {
1051 if d <= 0 {
1052 return t
1053 }
1054 _, r := div(t, d)
1055 if r+r < d {
1056 return t.Add(-r)
1057 }
1058 return t.Add(d - r)
1059 }
1060
1061
1062
1063
1064 func div(t Time, d Duration) (qmod2 int, r Duration) {
1065 neg := false
1066 if t.sec < 0 {
1067
1068 neg = true
1069 t.sec = -t.sec
1070 t.nsec = -t.nsec
1071 if t.nsec < 0 {
1072 t.nsec += 1e9
1073 t.sec--
1074 }
1075 }
1076
1077 switch {
1078
1079 case d < Second && Second%(d+d) == 0:
1080 qmod2 = int(t.nsec/int32(d)) & 1
1081 r = Duration(t.nsec % int32(d))
1082
1083
1084 case d%Second == 0:
1085 d1 := int64(d / Second)
1086 qmod2 = int(t.sec/d1) & 1
1087 r = Duration(t.sec%d1)*Second + Duration(t.nsec)
1088
1089
1090
1091
1092
1093 default:
1094
1095 sec := uint64(t.sec)
1096 tmp := (sec >> 32) * 1e9
1097 u1 := tmp >> 32
1098 u0 := tmp << 32
1099 tmp = uint64(sec&0xFFFFFFFF) * 1e9
1100 u0x, u0 := u0, u0+tmp
1101 if u0 < u0x {
1102 u1++
1103 }
1104 u0x, u0 = u0, u0+uint64(t.nsec)
1105 if u0 < u0x {
1106 u1++
1107 }
1108
1109
1110
1111 d1 := uint64(d)
1112 for d1>>63 != 1 {
1113 d1 <<= 1
1114 }
1115 d0 := uint64(0)
1116 for {
1117 qmod2 = 0
1118 if u1 > d1 || u1 == d1 && u0 >= d0 {
1119
1120 qmod2 = 1
1121 u0x, u0 = u0, u0-d0
1122 if u0 > u0x {
1123 u1--
1124 }
1125 u1 -= d1
1126 }
1127 if d1 == 0 && d0 == uint64(d) {
1128 break
1129 }
1130 d0 >>= 1
1131 d0 |= (d1 & 1) << 63
1132 d1 >>= 1
1133 }
1134 r = Duration(u0)
1135 }
1136
1137 if neg && r != 0 {
1138
1139
1140
1141
1142
1143
1144 qmod2 ^= 1
1145 r = d - r
1146 }
1147 return
1148 }
View as plain text