Skip to content

Commit 905f8e6

Browse files
committed
clock: Add timezone to all parsed dates
Previously the dates without timezone were assumed to use UTC when being converted to unix time, but the datatype maintained the lack of timezone when being printed. This means that the problematic timezoneless timestamps were kept and could be produced by the hosts. Since the dates are assumed to be UTC, add the timezone when they are parsed for the first time. Now their timezone is displayed at all times. The output of Localtime is kept without a timezone because clients are not prepared to accept arbitrary timezones in dates. (Both the SDK and XO(Lite)) Signed-off-by: Pau Ruiz Safont <pau.ruizsafont@cloud.com>
1 parent 6736669 commit 905f8e6

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

ocaml/libs/clock/date.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ let best_effort_iso8601_to_rfc3339 x =
5656
in
5757
match tz with
5858
| None | Some "" ->
59-
(* the caller didn't specify a tz, use the Unqualified Local Time *)
60-
Printf.sprintf "%s-00:00" x
59+
(* the caller didn't specify a tz, assume Coordinatel Universal Time *)
60+
Printf.sprintf "%sZ" x
6161
| Some _ ->
6262
x
6363

ocaml/libs/clock/test_date.ml

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@ let dash_time_str = "2020-04-07T08:28:32Z"
1010

1111
let no_dash_utc_time_str = "20200407T08:28:32Z"
1212

13+
let best_effort_iso8601_to_rfc3339 x =
14+
let x =
15+
try
16+
Scanf.sscanf x "%04d%02d%02dT%s" (fun y mon d rest ->
17+
Printf.sprintf "%04d-%02d-%02dT%s" y mon d rest
18+
)
19+
with _ -> x
20+
in
21+
let tz =
22+
try
23+
Scanf.sscanf x "%04d-%02d-%02dT%02d:%02d:%02d%s" (fun _ _ _ _ _ _ tz ->
24+
Some tz
25+
)
26+
with _ -> None
27+
in
28+
match tz with
29+
| None | Some "" ->
30+
(* the caller didn't specify a tz, use the Unqualified Local Time *)
31+
Printf.sprintf "%s-00:00" x
32+
| Some _ ->
33+
x
34+
1335
let tests =
1436
let test_of_unix_time_invertible () =
1537
let non_int_time = 1586245987.70200706 in
@@ -55,6 +77,21 @@ let tests =
5577
check_string "to_rfc3339 is backwards compatible" no_dash_utc_time_str
5678
(dash_time_str |> of_iso8601 |> to_rfc3339)
5779
in
80+
let test_localtime () =
81+
let time = localtime () in
82+
match
83+
time
84+
|> to_rfc3339
85+
|> best_effort_iso8601_to_rfc3339
86+
|> Ptime.of_rfc3339
87+
|> Ptime.rfc3339_error_to_msg
88+
with
89+
| Ok (_, tz, _) ->
90+
Alcotest.(check @@ option int)
91+
"localtime generates a timestamp without timezone" None tz
92+
| Error (`Msg msg) ->
93+
Alcotest.failf "Unexpected error: %s" msg
94+
in
5895
let test_localtime_string () =
5996
let[@warning "-8"] (Ok (t, _, _)) =
6097
Ptime.of_rfc3339 "2020-04-07T09:01:28Z"
@@ -86,17 +123,19 @@ let tests =
86123
(String.contains localtime_string 'Z')
87124
in
88125
let test_xsi894 () =
126+
let canonical = "20201210T17:19:20Z" in
89127
let missing_tz_no_dash = "20201210T17:19:20" in
90128
let missing_tz_dash = "2020-12-10T17:19:20" in
91-
check_string "can process missing tz no dash" missing_tz_no_dash
129+
check_string
130+
"Timestamp without timezones nor dashes is accepted, gets converted to \
131+
UTC"
132+
canonical
92133
(missing_tz_no_dash |> of_iso8601 |> to_rfc3339) ;
93-
check_string "can process missing tz with dashes, but return without dashes"
94-
missing_tz_no_dash
95-
(missing_tz_dash |> of_iso8601 |> to_rfc3339) ;
96-
let localtime' = localtime () in
97-
check_string "to_rfc3339 inverts of_iso8601 for localtime"
98-
(localtime' |> to_rfc3339)
99-
(localtime' |> to_rfc3339 |> of_iso8601 |> to_rfc3339)
134+
check_string
135+
"Timestamp without timezones, and dashes is accepted, gets converted to \
136+
UTC"
137+
canonical
138+
(missing_tz_dash |> of_iso8601 |> to_rfc3339)
100139
in
101140
let test_email_date (unix_timestamp, expected) =
102141
let formatted = of_unix_time unix_timestamp |> to_rfc822 in
@@ -135,9 +174,10 @@ let tests =
135174
, `Quick
136175
, test_to_rfc3339_backwards_compatibility
137176
)
177+
; ("localtime is printed without timezone", `Quick, test_localtime)
138178
; ("test_localtime_string", `Quick, test_localtime_string)
139179
; ("test_ca342171", `Quick, test_ca342171)
140-
; ("test_xsi894", `Quick, test_xsi894)
180+
; ("Parsing datetimes without timezones", `Quick, test_xsi894)
141181
; ( "Date w/o timezone to POSIX time conversion"
142182
, `Quick
143183
, test_no_timezone_to_unix

0 commit comments

Comments
 (0)