From 02c80bd445aecdcfdf1a34cfc2e1a7ac99e93e8d Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Thu, 31 Mar 2022 23:11:17 +0200 Subject: [PATCH] time: fix repetitive time.now().local().local().local() offsetting the time further and further (#13861) --- vlib/time/time.c.v | 4 ++++ vlib/time/time.v | 3 ++- vlib/time/time_nix.c.v | 6 +++++- vlib/time/time_test.v | 9 +++++++++ vlib/time/time_windows.c.v | 1 + 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/vlib/time/time.c.v b/vlib/time/time.c.v index 503c4815f5..9816706dfd 100644 --- a/vlib/time/time.c.v +++ b/vlib/time/time.c.v @@ -117,5 +117,9 @@ fn convert_ctime(t C.tm, microsecond int) Time { second: t.tm_sec microsecond: microsecond 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 } } diff --git a/vlib/time/time.v b/vlib/time/time.v index 3a7eff3a59..986d729cfe 100644 --- a/vlib/time/time.v +++ b/vlib/time/time.v @@ -45,6 +45,7 @@ pub: second int microsecond int unix i64 + is_local bool // used to make time.now().local().local() == time.now().local() } // FormatDelimiter contains different time formats. @@ -348,7 +349,7 @@ pub fn (d Duration) str() string { // offset returns time zone UTC offset in seconds. pub fn offset() int { - t := now() + t := utc() local := t.local() return int(local.unix - t.unix) } diff --git a/vlib/time/time_nix.c.v b/vlib/time/time_nix.c.v index 5d88b6ff8e..7bf12f3222 100644 --- a/vlib/time/time_nix.c.v +++ b/vlib/time/time_nix.c.v @@ -20,7 +20,8 @@ struct C.tm { 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 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. pub fn (t Time) local() Time { + if t.is_local { + return t + } loc_tm := C.tm{} C.localtime_r(voidptr(&t.unix), &loc_tm) return convert_ctime(loc_tm, t.microsecond) diff --git a/vlib/time/time_test.v b/vlib/time/time_test.v index 66da15b459..c657b2c8ce 100644 --- a/vlib/time/time_test.v +++ b/vlib/time/time_test.v @@ -254,3 +254,12 @@ fn test_since() { d2 := time.since(t1) 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() +} diff --git a/vlib/time/time_windows.c.v b/vlib/time/time_windows.c.v index 0b676db4d2..19d2e71e36 100644 --- a/vlib/time/time_windows.c.v +++ b/vlib/time/time_windows.c.v @@ -104,6 +104,7 @@ pub fn (t Time) local() Time { hour: u16(t.hour) minute: u16(t.minute) second: u16(t.second) + millisecond: u16(t.microsecond / 1000) } st_local := SystemTime{} C.SystemTimeToTzSpecificLocalTime(voidptr(0), &st_utc, &st_local)