time: fix `time.parse_iso8601(2037-07-23)?.add_days(181).str() == "1901-12-13 17:31:44"`

pull/10684/head
Delyan Angelov 2021-07-06 18:51:47 +03:00
parent 9f8c3cc159
commit 55eeb701a9
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
8 changed files with 29 additions and 16 deletions

View File

@ -0,0 +1,13 @@
import time
fn test_time_after_2038_works() {
after_time := time.parse_iso8601('2037-07-23') or { time.now() }
dump(after_time)
error_time := after_time.add_days(180)
dump(error_time)
assert error_time.str() == '2038-01-19 00:00:00'
// NB: the next date is after Y2K38, it should NOT wrap:
error_time2 := after_time.add_days(181)
dump(error_time2)
assert error_time2.str() == '2038-01-20 00:00:00'
}

View File

@ -381,7 +381,7 @@ fn test_subtract() {
second: 3 second: 3
microsecond: 100 microsecond: 100
}) })
t2 := unix2(int(t1.unix) + d_seconds, t1.microsecond + d_microseconds) t2 := unix2(i64(t1.unix) + d_seconds, t1.microsecond + d_microseconds)
d1 := t2 - t1 d1 := t2 - t1
d2 := t1 - t2 d2 := t1 - t2
assert d1 > 0 assert d1 > 0

View File

@ -135,6 +135,6 @@ pub fn parse_iso8601(s string) ?Time {
} else if unix_offset > 0 { } else if unix_offset > 0 {
unix_time += u64(unix_offset) unix_time += u64(unix_offset)
} }
t = unix2(int(unix_time), t.microsecond) t = unix2(i64(unix_time), t.microsecond)
return t return t
} }

View File

@ -137,7 +137,7 @@ pub fn utc() Time {
// in this API call // in this API call
t := C.time(0) t := C.time(0)
_ = C.time(&t) _ = C.time(&t)
return unix2(int(t), 0) return unix2(i64(t), 0)
} }
// smonth returns month name. // smonth returns month name.
@ -186,7 +186,7 @@ pub fn (t Time) add(d Duration) Time {
microseconds := i64(t.unix) * 1000 * 1000 + t.microsecond + d.microseconds() microseconds := i64(t.unix) * 1000 * 1000 + t.microsecond + d.microseconds()
unix := microseconds / (1000 * 1000) unix := microseconds / (1000 * 1000)
micro := microseconds % (1000 * 1000) micro := microseconds % (1000 * 1000)
return unix2(int(unix), int(micro)) return unix2(unix, int(micro))
} }
// add_seconds returns a new time struct with an added number of seconds. // add_seconds returns a new time struct with an added number of seconds.

View File

@ -80,5 +80,5 @@ fn darwin_utc() Time {
// get the high precision time as UTC clock // get the high precision time as UTC clock
tv := C.timeval{} tv := C.timeval{}
C.gettimeofday(&tv, 0) C.gettimeofday(&tv, 0)
return unix2(int(tv.tv_sec), int(tv.tv_usec)) return unix2(i64(tv.tv_sec), int(tv.tv_usec))
} }

View File

@ -86,7 +86,7 @@ fn linux_utc() Time {
// and use the nanoseconds part // and use the nanoseconds part
mut ts := C.timespec{} mut ts := C.timespec{}
C.clock_gettime(C.CLOCK_REALTIME, &ts) C.clock_gettime(C.CLOCK_REALTIME, &ts)
return unix2(int(ts.tv_sec), int(ts.tv_nsec / 1000)) return unix2(i64(ts.tv_sec), int(ts.tv_nsec / 1000))
} }
// dummy to compile with all compilers // dummy to compile with all compilers

View File

@ -18,7 +18,7 @@ fn solaris_utc() Time {
// and use the nanoseconds part // and use the nanoseconds part
mut ts := C.timespec{} mut ts := C.timespec{}
C.clock_gettime(C.CLOCK_REALTIME, &ts) C.clock_gettime(C.CLOCK_REALTIME, &ts)
return unix2(int(ts.tv_sec), int(ts.tv_nsec / 1000)) return unix2(i64(ts.tv_sec), int(ts.tv_nsec / 1000))
} }
// dummy to compile with all compilers // dummy to compile with all compilers

View File

@ -25,7 +25,7 @@ pub fn unix(abs int) Time {
} }
// unix2 returns a time struct from Unix time and microsecond value // unix2 returns a time struct from Unix time and microsecond value
pub fn unix2(abs int, microsecond int) Time { pub fn unix2(abs i64, microsecond int) Time {
// Split into day and time // Split into day and time
mut day_offset := abs / seconds_per_day mut day_offset := abs / seconds_per_day
if abs % seconds_per_day < 0 { if abs % seconds_per_day < 0 {
@ -46,7 +46,7 @@ pub fn unix2(abs int, microsecond int) Time {
} }
} }
fn calculate_date_from_offset(day_offset_ int) (int, int, int) { fn calculate_date_from_offset(day_offset_ i64) (int, int, int) {
mut day_offset := day_offset_ mut day_offset := day_offset_
// Move offset to year 2001 as it's the start of a new 400-year cycle // Move offset to year 2001 as it's the start of a new 400-year cycle
// Code below this rely on the fact that the day_offset is lined up with the 400-year cycle // Code below this rely on the fact that the day_offset is lined up with the 400-year cycle
@ -54,14 +54,14 @@ fn calculate_date_from_offset(day_offset_ int) (int, int, int) {
mut year := 2001 mut year := 2001
day_offset -= 31 * 365 + 8 day_offset -= 31 * 365 + 8
// Account for 400 year cycle // Account for 400 year cycle
year += (day_offset / days_per_400_years) * 400 year += int(day_offset / days_per_400_years) * 400
day_offset %= days_per_400_years day_offset %= days_per_400_years
// Account for 100 year cycle // Account for 100 year cycle
if day_offset == days_per_100_years * 4 { if day_offset == days_per_100_years * 4 {
year += 300 year += 300
day_offset -= days_per_100_years * 3 day_offset -= days_per_100_years * 3
} else { } else {
year += (day_offset / days_per_100_years) * 100 year += int(day_offset / days_per_100_years) * 100
day_offset %= days_per_100_years day_offset %= days_per_100_years
} }
// Account for 4 year cycle // Account for 4 year cycle
@ -69,7 +69,7 @@ fn calculate_date_from_offset(day_offset_ int) (int, int, int) {
year += 96 year += 96
day_offset -= days_per_4_years * 24 day_offset -= days_per_4_years * 24
} else { } else {
year += (day_offset / days_per_4_years) * 4 year += int(day_offset / days_per_4_years) * 4
day_offset %= days_per_4_years day_offset %= days_per_4_years
} }
// Account for every year // Account for every year
@ -77,7 +77,7 @@ fn calculate_date_from_offset(day_offset_ int) (int, int, int) {
year += 3 year += 3
day_offset -= 365 * 3 day_offset -= 365 * 3
} else { } else {
year += (day_offset / 365) year += int(day_offset / 365)
day_offset %= 365 day_offset %= 365
} }
if day_offset < 0 { if day_offset < 0 {
@ -108,10 +108,10 @@ fn calculate_date_from_offset(day_offset_ int) (int, int, int) {
estimated_month-- estimated_month--
} }
day_offset -= days_before[estimated_month] day_offset -= days_before[estimated_month]
return year, estimated_month + 1, day_offset + 1 return year, int(estimated_month + 1), int(day_offset + 1)
} }
fn calculate_time_from_offset(second_offset_ int) (int, int, int) { fn calculate_time_from_offset(second_offset_ i64) (int, int, int) {
mut second_offset := second_offset_ mut second_offset := second_offset_
if second_offset < 0 { if second_offset < 0 {
second_offset += seconds_per_day second_offset += seconds_per_day
@ -120,5 +120,5 @@ fn calculate_time_from_offset(second_offset_ int) (int, int, int) {
second_offset %= seconds_per_hour second_offset %= seconds_per_hour
min := second_offset / seconds_per_minute min := second_offset / seconds_per_minute
second_offset %= seconds_per_minute second_offset %= seconds_per_minute
return hour_, min, second_offset return int(hour_), int(min), int(second_offset)
} }