time: fix repetitive time.now().local().local().local() offsetting the time further and further (#13861)

pull/13887/head
Vincenzo Palazzo 2022-03-31 23:11:17 +02:00 committed by GitHub
parent 9c1981a309
commit 02c80bd445
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 2 deletions

View File

@ -117,5 +117,9 @@ fn convert_ctime(t C.tm, microsecond int) Time {
second: t.tm_sec second: t.tm_sec
microsecond: microsecond microsecond: microsecond
unix: make_unix_time(t) unix: make_unix_time(t)
// for the actual code base when we
// call convert_ctime, it is always
// when we manage the local time.
is_local: true
} }
} }

View File

@ -45,6 +45,7 @@ pub:
second int second int
microsecond int microsecond int
unix i64 unix i64
is_local bool // used to make time.now().local().local() == time.now().local()
} }
// FormatDelimiter contains different time formats. // FormatDelimiter contains different time formats.
@ -348,7 +349,7 @@ pub fn (d Duration) str() string {
// offset returns time zone UTC offset in seconds. // offset returns time zone UTC offset in seconds.
pub fn offset() int { pub fn offset() int {
t := now() t := utc()
local := t.local() local := t.local()
return int(local.unix - t.unix) return int(local.unix - t.unix)
} }

View File

@ -20,7 +20,8 @@ struct C.tm {
fn C.timegm(&C.tm) C.time_t fn C.timegm(&C.tm) C.time_t
// fn C.gmtime_r(&tm, &gbuf) // prefering localtime_r over the localtime because
// from docs localtime_r is thread safe,
fn C.localtime_r(t &C.time_t, tm &C.tm) fn C.localtime_r(t &C.time_t, tm &C.tm)
fn make_unix_time(t C.tm) i64 { fn make_unix_time(t C.tm) i64 {
@ -29,6 +30,9 @@ fn make_unix_time(t C.tm) i64 {
// local returns t with the location set to local time. // local returns t with the location set to local time.
pub fn (t Time) local() Time { pub fn (t Time) local() Time {
if t.is_local {
return t
}
loc_tm := C.tm{} loc_tm := C.tm{}
C.localtime_r(voidptr(&t.unix), &loc_tm) C.localtime_r(voidptr(&t.unix), &loc_tm)
return convert_ctime(loc_tm, t.microsecond) return convert_ctime(loc_tm, t.microsecond)

View File

@ -254,3 +254,12 @@ fn test_since() {
d2 := time.since(t1) d2 := time.since(t1)
assert d2 >= 40_000_000 assert d2 >= 40_000_000
} }
// issue relate https://github.com/vlang/v/issues/13828
// problem: the local method add 2h on the time in a Linux machine
// the other machine are not tested in a local env
fn test_recursive_local_call() {
now_tm := time.now()
assert now_tm.str() == now_tm.local().str()
assert now_tm.local().str() == now_tm.local().local().str()
}

View File

@ -104,6 +104,7 @@ pub fn (t Time) local() Time {
hour: u16(t.hour) hour: u16(t.hour)
minute: u16(t.minute) minute: u16(t.minute)
second: u16(t.second) second: u16(t.second)
millisecond: u16(t.microsecond / 1000)
} }
st_local := SystemTime{} st_local := SystemTime{}
C.SystemTimeToTzSpecificLocalTime(voidptr(0), &st_utc, &st_local) C.SystemTimeToTzSpecificLocalTime(voidptr(0), &st_utc, &st_local)