@@ -48,67 +48,39 @@ pub fn unix2(abs i64, microsecond int) Time {
4848
4949fn calculate_date_from_offset (day_offset_ i64 ) (int , int , int ) {
5050 mut day_offset := day_offset_
51- // Move offset to year 2001 as it's the start of a new 400-year cycle
52- // Code below this rely on the fact that the day_offset is lined up with the 400-year cycle
53- // 1970-2000 (inclusive) has 31 years (8 of which are leap years)
54- mut year := 2001
55- day_offset - = 31 * 365 + 8
56- // Account for 400 year cycle
57- year + = int (day_offset / days_per_400_ years) * 400
58- day_offset % = days_per_400_ years
59- // Account for 100 year cycle
60- if day_offset == days_per_100_ years * 4 {
61- year + = 300
62- day_offset - = days_per_100_ years * 3
63- } else {
64- year + = int (day_offset / days_per_100_ years) * 100
65- day_offset % = days_per_100_ years
66- }
67- // Account for 4 year cycle
68- if day_offset == days_per_4_ years * 25 {
69- year + = 96
70- day_offset - = days_per_4_ years * 24
51+
52+ // source: http://howardhinnant.github.io/date_algorithms.html#civil_from_days
53+
54+ // shift from 1970-01-01 to 0000-03-01
55+ day_offset + = 719468 // int(days_per_400_years * 1970 / 400 - (28+31))
56+
57+ mut era := 0
58+ if day_offset > = 0 {
59+ era = int (day_offset / days_per_400_ years)
7160 } else {
72- year + = int (day_offset / days_per_4_ years) * 4
73- day_offset % = days_per_4_ years
61+ era = int ((day_offset - days_per_400_ years - 1 ) / days_per_400_ years)
7462 }
75- // Account for every year
76- if day_offset == 365 * 4 {
77- year + = 3
78- day_offset - = 365 * 3
63+ // doe(day of era) [0, 146096]
64+ doe := day_offset - era * days_per_400_ years
65+ // yoe(year of era) [0, 399]
66+ yoe := (doe - doe / (days_per_4_ years - 1 ) + doe / days_per_100_ years - doe / (days_per_400_ years - 1 )) / days_in_year
67+ // year number
68+ mut y := int (yoe + era * 400 )
69+ // doy (day of year), with year beginning Mar 1 [0, 365]
70+ doy := doe - (days_in_year * yoe + yoe / 4 - yoe / 100 )
71+
72+ mp := (5 * doy + 2 ) / 153
73+ d := int (doy - (153 * mp + 2 ) / 5 + 1 )
74+ mut m := int (mp)
75+ if mp < 10 {
76+ m + = 3
7977 } else {
80- year + = int (day_offset / 365 )
81- day_offset % = 365
82- }
83- if day_offset < 0 {
84- year--
85- if is_leap_year (year) {
86- day_offset + = 366
87- } else {
88- day_offset + = 365
89- }
90- }
91- if is_leap_year (year) {
92- if day_offset > 31 + 29 - 1 {
93- // After leap day; pretend it wasn't there.
94- day_offset--
95- } else if day_offset == 31 + 29 - 1 {
96- // Leap day.
97- return year, 2 , 29
98- }
99- }
100- mut estimated_month := day_offset / 31
101- for day_offset > = days_before[estimated_month + 1 ] {
102- estimated_month++
78+ m - = 9
10379 }
104- for day_offset < days_before[estimated_month] {
105- if estimated_month == 0 {
106- break
107- }
108- estimated_month--
80+ if m < = 2 {
81+ y + = 1
10982 }
110- day_offset - = days_before[estimated_month]
111- return year, int (estimated_month + 1 ), int (day_offset + 1 )
83+ return y, m, d
11284}
11385
11486fn calculate_time_from_offset (second_offset_ i64 ) (int , int , int ) {
0 commit comments