diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e94d4671c..22c3303ad9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,6 +103,8 @@ jobs: run: TZ=Etc/GMT-3 ./v test vlib/time/ - name: Test time functions in a timezone UTC+12 run: TZ=Etc/GMT-12 ./v test vlib/time/ + - name: Test time functions in a timezone using daylight saving (Europe/Paris) + run: TZ=Europe/Paris ./v test vlib/time/ - name: Test building v tools run: ./v -silent build-tools - name: v doctor diff --git a/vlib/time/parse.v b/vlib/time/parse.v index ad484994d6..16bbedc535 100644 --- a/vlib/time/parse.v +++ b/vlib/time/parse.v @@ -111,5 +111,5 @@ pub fn parse_iso8601(s string) ?Time { t = unix2(int(unix_time), t.microsecond) } // Convert the time to local time - return to_local_time(t) + return t.to_local_time() } diff --git a/vlib/time/parse_test.v b/vlib/time/parse_test.v index 2980f04dd1..9cb580f6d4 100644 --- a/vlib/time/parse_test.v +++ b/vlib/time/parse_test.v @@ -1,5 +1,4 @@ import time -import math fn test_parse() { s := '2018-01-27 12:48:34' @@ -50,15 +49,20 @@ fn test_parse_rfc2822_invalid() { } fn test_parse_iso8601() { - // Because there is a small difference between time.now() - time.utc and actual offset, - // round to the nearest hour. - offset := time.Duration(i64(math.round((time.now() - time.utc()).hours())) * time.hour) + // Because the offset between local time and UTC is not constant in regions + // that use daylight saving times we need to calculate separete offsets for + // summer and winter + offset_summer := time.Duration(time.new_time(year: 2020, month: 6, day: 5, hour: 15).to_local_time() - + time.new_time(year: 2020, month: 6, day: 5, hour: 15)) + offset_winter := time.Duration(time.new_time(year: 2020, month: 11, day: 5, hour: 15).to_local_time() - + time.new_time(year: 2020, month: 11, day: 5, hour: 15)) formats := [ '2020-06-05T15:38:06Z', '2020-06-05T15:38:06.015959Z', '2020-06-05T15:38:06.015959+00:00', '2020-06-05T15:38:06.015959+02:00', '2020-06-05T15:38:06.015959-02:00', + '2020-11-05T15:38:06.015959Z' ] times := [ [2020, 6, 5, 15, 38, 6, 0], @@ -66,6 +70,7 @@ fn test_parse_iso8601() { [2020, 6, 5, 15, 38, 6, 15959], [2020, 6, 5, 13, 38, 6, 15959], [2020, 6, 5, 17, 38, 6, 15959], + [2020, 11, 5, 15, 38, 6, 15959], ] for i, format in formats { t := time.parse_iso8601(format) or { @@ -81,7 +86,7 @@ fn test_parse_iso8601() { minute: data[4] second: data[5] microsecond: data[6] - ).add(offset) + ).add(if i <= 4 { offset_summer } else { offset_winter }) assert t.year == t2.year assert t.month == t2.month assert t.day == t2.day diff --git a/vlib/time/time_nix.c.v b/vlib/time/time_nix.c.v index 9dd884b1e9..008bfa1bb6 100644 --- a/vlib/time/time_nix.c.v +++ b/vlib/time/time_nix.c.v @@ -24,7 +24,7 @@ fn make_unix_time(t C.tm) int { return int(C.timegm(&t)) } -fn to_local_time(t Time) Time { +pub fn (t Time) to_local_time() Time { loc_tm := C.tm{} C.localtime_r(time_t(&t.unix), &loc_tm) return convert_ctime(loc_tm, t.microsecond) diff --git a/vlib/time/time_windows.c.v b/vlib/time/time_windows.c.v index 4ef4d97989..b02a532b4a 100644 --- a/vlib/time/time_windows.c.v +++ b/vlib/time/time_windows.c.v @@ -93,7 +93,7 @@ fn local_as_unix_time() int { return make_unix_time(tm) } -fn to_local_time(t Time) Time { +pub fn (t Time) to_local_time() Time { st_utc := SystemTime{ year: u16(t.year) month: u16(t.month)