Skip to content

Commit e41943e

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 <[email protected]>
1 parent d9193d0 commit e41943e

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 Universal Local 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
@@ -52,6 +74,21 @@ let tests =
5274
check_string "to_rfc3339 is backwards compatible" no_dash_utc_time_str
5375
(dash_time_str |> of_iso8601 |> to_rfc3339)
5476
in
77+
let test_localtime () =
78+
let time = localtime () in
79+
match
80+
time
81+
|> to_rfc3339
82+
|> best_effort_iso8601_to_rfc3339
83+
|> Ptime.of_rfc3339
84+
|> Ptime.rfc3339_error_to_msg
85+
with
86+
| Ok (_, tz, _) ->
87+
Alcotest.(check @@ option int)
88+
"localtime generates a timestamp without timezone" None tz
89+
| Error (`Msg msg) ->
90+
Alcotest.failf "Unexpected error: %s" msg
91+
in
5592
let test_localtime_string () =
5693
let[@warning "-8"] (Ok (t, _, _)) =
5794
Ptime.of_rfc3339 "2020-04-07T09:01:28Z"
@@ -83,17 +120,19 @@ let tests =
83120
(String.contains localtime_string 'Z')
84121
in
85122
let test_xsi894 () =
123+
let canonical = "20201210T17:19:20Z" in
86124
let missing_tz_no_dash = "20201210T17:19:20" in
87125
let missing_tz_dash = "2020-12-10T17:19:20" in
88-
check_string "can process missing tz no dash" missing_tz_no_dash
126+
check_string
127+
"Timestamp without timezones nor dashes is accepted, gets converted to \
128+
UTC"
129+
canonical
89130
(missing_tz_no_dash |> of_iso8601 |> to_rfc3339) ;
90-
check_string "can process missing tz with dashes, but return without dashes"
91-
missing_tz_no_dash
92-
(missing_tz_dash |> of_iso8601 |> to_rfc3339) ;
93-
let localtime' = localtime () in
94-
check_string "to_rfc3339 inverts of_iso8601 for localtime"
95-
(localtime' |> to_rfc3339)
96-
(localtime' |> to_rfc3339 |> of_iso8601 |> to_rfc3339)
131+
check_string
132+
"Timestamp without timezones, and dashes is accepted, gets converted to \
133+
UTC"
134+
canonical
135+
(missing_tz_dash |> of_iso8601 |> to_rfc3339)
97136
in
98137
let test_email_date (unix_timestamp, expected) =
99138
let formatted = of_unix_time unix_timestamp |> to_rfc822 in
@@ -132,9 +171,10 @@ let tests =
132171
, `Quick
133172
, test_to_rfc3339_backwards_compatibility
134173
)
174+
; ("localtime is printed without timezone", `Quick, test_localtime)
135175
; ("test_localtime_string", `Quick, test_localtime_string)
136176
; ("test_ca342171", `Quick, test_ca342171)
137-
; ("test_xsi894", `Quick, test_xsi894)
177+
; ("Parsing datetimes without timezones", `Quick, test_xsi894)
138178
; ( "Date w/o timezone to POSIX time conversion"
139179
, `Quick
140180
, test_no_timezone_to_unix

0 commit comments

Comments
 (0)