@@ -508,25 +508,25 @@ func (t Time) locabs() (name string, offset int, abs uint64) {
508
508
509
509
// Date returns the year, month, and day in which t occurs.
510
510
func (t Time ) Date () (year int , month Month , day int ) {
511
- year , month , day = t . date ( true )
511
+ year , month , day = absDate ( t . abs () )
512
512
return
513
513
}
514
514
515
515
// Year returns the year in which t occurs.
516
516
func (t Time ) Year () int {
517
- year , _ , _ := t .date ( false )
517
+ year , _ , _ := t .Date ( )
518
518
return year
519
519
}
520
520
521
521
// Month returns the month of the year specified by t.
522
522
func (t Time ) Month () Month {
523
- _ , month , _ := t .date ( true )
523
+ _ , month , _ := t .Date ( )
524
524
return month
525
525
}
526
526
527
527
// Day returns the day of the month specified by t.
528
528
func (t Time ) Day () int {
529
- _ , _ , day := t .date ( true )
529
+ _ , _ , day := t .Date ( )
530
530
return day
531
531
}
532
532
@@ -565,7 +565,7 @@ func (t Time) ISOWeek() (year, week int) {
565
565
}
566
566
// find the Thursday of the calendar week
567
567
abs += uint64 (d ) * secondsPerDay
568
- year , _ , _ , yday := absDateWithYday (abs , false )
568
+ year , yday := absYearDay (abs )
569
569
return year , yday / 7 + 1
570
570
}
571
571
@@ -608,7 +608,8 @@ func (t Time) Nanosecond() int {
608
608
// YearDay returns the day of the year specified by t, in the range [1,365] for non-leap years,
609
609
// and [1,366] in leap years.
610
610
func (t Time ) YearDay () int {
611
- return absYearDay (t .abs ()) + 1
611
+ _ , yday := absYearDay (t .abs ())
612
+ return yday + 1
612
613
}
613
614
614
615
// A Duration represents the elapsed time between two instants
@@ -974,27 +975,25 @@ const (
974
975
daysPer400Years = 365 * 400 + 97
975
976
daysPer100Years = 365 * 100 + 24
976
977
daysPer4Years = 365 * 4 + 1
978
+
979
+ // Neri-Schneider shift and correction constants. (ns_s is chosen so that
980
+ // 1970 is roughly in the middle of the range of their algorithms validity.)
981
+ ns_s = uint32 (3670 )
982
+ ns_K = uint32 (719468 + 146097 * ns_s )
983
+ ns_L = int (400 * ns_s )
977
984
)
978
985
979
- // date computes the year, day of year, and when full=true,
980
- // the month and day in which t occurs.
981
- func (t Time ) date (full bool ) (year int , month Month , day int ) {
982
- return absDate (t .abs (), full )
983
- }
986
+ // Computes the year, month and day given the absolute time.
987
+ func absDate (abs uint64 ) (year int , month Month , day int ) {
984
988
985
- // The algorithm is figure 12 of Neri, Schneider, "Euclidean affine functions
986
- // and their application to calendar algorithms".
987
- // https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172
988
- func absDate (abs uint64 , full bool ) (year int , month Month , day int ) {
989
989
daysAbs := int64 (abs / secondsPerDay )
990
990
daysUnix := int32 (daysAbs - (unixToInternal + internalToAbsolute )/ secondsPerDay )
991
991
992
- // Shift and correction constants.
993
- s := uint32 (3670 )
994
- K := uint32 (719468 + 146097 * s )
995
- L := int (400 * s )
992
+ // The algorithm is figure 12 of Neri, Schneider, "Euclidean affine functions
993
+ // and their application to calendar algorithms".
994
+ // https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172
996
995
997
- N := uint32 (daysUnix ) + K
996
+ N := uint32 (daysUnix ) + ns_K
998
997
999
998
// Century
1000
999
N_1 := 4 * N + 3
@@ -1005,48 +1004,43 @@ func absDate(abs uint64, full bool) (year int, month Month, day int) {
1005
1004
N_2 := R | 3
1006
1005
P_2 := 2939745 * uint64 (N_2 )
1007
1006
Z := uint32 (P_2 / 4294967296 )
1008
- N_Y := uint32 (P_2 % 4294967296 ) / 2939745 / 4
1007
+ N_Y := uint32 (P_2 % 4294967296 ) / 11758980
1009
1008
1010
1009
J := 0
1011
1010
if N_Y >= 306 {
1012
1011
J = 1
1013
1012
}
1014
1013
1015
1014
Y := 100 * C + Z
1016
- year = int (Y ) - L + J
1017
-
1018
- if ! full {
1019
- return
1020
- }
1015
+ year = int (Y ) - ns_L + J
1021
1016
1022
1017
// Month and day
1023
1018
N_3 := 2141 * N_Y + 197913
1024
- M := N_3 / 65536
1025
- D := N_3 % 65536 / 2141
1019
+ M := uint16 ( N_3 / 65536 )
1020
+ D := uint16 ( N_3 % 65536 ) / 2141
1026
1021
1027
1022
month = Month (M )
1028
1023
if J == 1 {
1029
- month = Month ( M - 12 )
1024
+ month -= 12
1030
1025
}
1031
- day = int (D + 1 )
1026
+ day = int (D ) + 1
1032
1027
1033
1028
return
1034
1029
}
1035
1030
1036
- // The algorithm is basicaly figure 12 of Neri, Schneider, "Euclidean affine functions
1037
- // and their application to calendar algorithms", adapted to calculate yday.
1038
- // https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172
1039
- func absDateWithYday (abs uint64 , full bool ) (year int , month Month , day int , yday int ) {
1040
- daysAbs := int64 (abs / secondsPerDay )
1031
+ // Computes the year and the year day (in [0, 365]) given the absolute time.
1032
+ func absYearDay (abs uint64 ) (year int , yday int ) {
1041
1033
1034
+ daysAbs := int64 (abs / secondsPerDay )
1042
1035
daysUnix := int32 (daysAbs - (unixToInternal + internalToAbsolute )/ secondsPerDay )
1043
1036
1044
- // Shift and correction constants.
1045
- s := uint32 (3670 ) // chosen so that 1970 is roughly in the middle of the range
1046
- K := uint32 (719468 + 146097 * s )
1047
- L := int (400 * s )
1037
+ // The algorithm is adapted from figure 12 of Neri, Schneider, "Euclidean affine
1038
+ // functions and their application to calendar algorithms".
1039
+ // https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172
1048
1040
1049
- N := uint32 (daysUnix ) + K
1041
+ // The natural epoch for this algorithm is 0001-Jan-01, i.e, 306 days after
1042
+ // 0000-Mar-01
1043
+ N := uint32 (daysUnix ) + ns_K - 306
1050
1044
1051
1045
// Century
1052
1046
N_1 := 4 * N + 3
@@ -1055,73 +1049,18 @@ func absDateWithYday(abs uint64, full bool) (year int, month Month, day int, yda
1055
1049
// Year
1056
1050
R := N_1 % 146097
1057
1051
N_2 := R | 3
1052
+
1058
1053
P_2 := 2939745 * uint64 (N_2 )
1059
1054
Z := uint32 (P_2 / 4294967296 )
1060
- N_Y := uint32 (P_2 % 4294967296 ) / 2939745 / 4
1061
-
1062
- isLeapYear := 0
1063
- if Z != 0 {
1064
- if Z % 4 == 0 {
1065
- isLeapYear = 1
1066
- }
1067
- } else if C % 4 == 0 {
1068
- isLeapYear = 1
1069
- }
1070
-
1071
- J := 0
1072
- if N_Y >= 306 {
1073
- J = 1
1074
- }
1075
-
1076
- yday = int (N_Y )
1077
- if J == 1 {
1078
- yday = yday - 306
1079
- } else {
1080
- yday = yday + 31 + 28 + isLeapYear
1081
- }
1082
-
1055
+ N_Y := uint32 (P_2 % 4294967296 ) / 11758980
1083
1056
Y := 100 * C + Z
1084
- year = int (Y ) - L + J
1085
-
1086
- if ! full {
1087
- return
1088
- }
1089
1057
1090
- // Month and day
1091
- N_3 := 2141 * N_Y + 197913
1092
- M := N_3 / 65536
1093
- D := N_3 % 65536 / 2141
1094
-
1095
- month = Month (M )
1096
- if J == 1 {
1097
- month = Month (M - 12 )
1098
- }
1099
- day = int (D + 1 )
1058
+ year = int (Y ) - ns_L + 1
1059
+ yday = int (N_Y )
1100
1060
1101
1061
return
1102
1062
}
1103
1063
1104
- func absYearDay (abs uint64 ) int {
1105
- daysAbs := int64 (abs / secondsPerDay )
1106
- daysUnix := int32 (daysAbs - (unixToInternal + internalToAbsolute )/ secondsPerDay )
1107
-
1108
- // Shift and correction constants.
1109
- s := uint32 (3670 ) // chosen so that 1970 is roughly in the middle of the range
1110
- K := uint32 (719468 - 306 + 146097 * s )
1111
- N := uint32 (daysUnix ) + K
1112
-
1113
- // Century
1114
- N_1 := 4 * N + 3
1115
-
1116
- // Year
1117
- R := N_1 % 146097
1118
- N_2 := R | 3
1119
- P_2 := 2939745 * uint64 (N_2 )
1120
- N_Y := uint32 (P_2 % 4294967296 ) / 2939745 / 4
1121
-
1122
- return int (N_Y )
1123
- }
1124
-
1125
1064
// daysBefore[m] counts the number of days in a non-leap year
1126
1065
// before month m begins. There is an entry for m=12, counting
1127
1066
// the number of days before January of next year (365).
@@ -1150,16 +1089,15 @@ func daysIn(m Month, year int) int {
1150
1089
1151
1090
// daysSinceEpoch takes a year, month and day and returns the number of days from
1152
1091
// Jan 1 1970 (Unix time) to the given date.
1153
- // The algorithm is figure 13 of Neri, Schneider, "Euclidean affine functions
1154
- // and their application to calendar algorithms".
1155
- // https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172
1156
- // It gives correct results if the date is in the range [-1,468,000/Mar/01, 1,471,745/Fev/28].
1157
1092
func daysSinceEpoch (year int , month Month , day int ) int32 {
1158
- s := uint32 (3670 ) // chosen so that 1970 is roughly in the middle of the range
1159
- K := uint32 (719468 + 146097 * s )
1160
- L := int (400 * s )
1161
1093
1162
- y := uint32 (year + L )
1094
+ // The algorithm is figure 13 of Neri, Schneider, "Euclidean affine functions
1095
+ // and their application to calendar algorithms".
1096
+ // https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172
1097
+ // It gives correct results if the date is in the range
1098
+ // [-1,468,000/Mar/01, 1,471,745/Fev/28].
1099
+
1100
+ y := uint32 (year + ns_L )
1163
1101
m := uint32 (month )
1164
1102
if month < 3 {
1165
1103
y --
@@ -1174,7 +1112,7 @@ func daysSinceEpoch(year int, month Month, day int) int32 {
1174
1112
m_star := (153 * m - 457 ) / 5
1175
1113
n := y_star + m_star + d
1176
1114
1177
- return int32 (n - K )
1115
+ return int32 (n - ns_K )
1178
1116
}
1179
1117
1180
1118
// Provided by package runtime.
@@ -1512,7 +1450,11 @@ func (t Time) IsDST() bool {
1512
1450
}
1513
1451
1514
1452
func isLeap (year int ) bool {
1515
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0 )
1453
+ d := 3
1454
+ if year % 25 == 0 {
1455
+ d = 15
1456
+ }
1457
+ return (year & d ) == 0
1516
1458
}
1517
1459
1518
1460
// norm returns nhi, nlo such that
0 commit comments