Skip to content

Commit cfcdb0b

Browse files
authored
Merge pull request xapi-project#58 from lippirk/xsi894-master
XSI-894 date.iso8601.to_float should assume UTC
2 parents 8225021 + 9d7c929 commit cfcdb0b

File tree

3 files changed

+20
-24
lines changed

3 files changed

+20
-24
lines changed

lib/xapi-stdext-date/date.ml

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
(* ==== RFC822 ==== *)
1616
type rfc822 = string
1717

18-
let months = [| "Jan"; "Feb"; "Mar"; "Apr"; "May"; "Jun";
18+
let months = [| "Jan"; "Feb"; "Mar"; "Apr"; "May"; "Jun";
1919
"Jul"; "Aug"; "Sep"; "Oct"; "Nov"; "Dec" |]
2020
let days = [| "Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat" |]
2121

@@ -30,9 +30,11 @@ let rfc822_to_string x = x
3030

3131
(* ==== ISO8601/RFC3339 ==== *)
3232

33-
type print_type = PrintLocal | PrintUTC
33+
type print_timezone = Empty | TZ of string
3434
(* we must store the print_type with iso8601 to handle the case where the local time zone is UTC *)
35-
type iso8601 = Ptime.date * Ptime.time * print_type
35+
type iso8601 = Ptime.date * Ptime.time * print_timezone
36+
37+
let utc = TZ "Z"
3638

3739
let of_dt print_type dt = let (date, time) = dt in (date, time, print_type)
3840
let to_dt (date, time, _) = (date, time)
@@ -57,23 +59,22 @@ let best_effort_iso8601_to_rfc3339 x =
5759
match tz with
5860
| None | Some "" ->
5961
(* the caller didn't specify a tz. we must try to add one so that ptime can at least attempt to parse *)
60-
(Printf.sprintf "%sZ" x, PrintLocal)
61-
| Some _ ->
62-
(* the caller specified a tz. we assume it's UTC because we don't accept anything else *)
63-
(x, PrintUTC)
62+
(Printf.sprintf "%sZ" x, Empty)
63+
| Some tz ->
64+
(x, TZ tz)
6465

6566
let of_string x =
66-
let (rfc3339, print_type) = best_effort_iso8601_to_rfc3339 x in
67+
let (rfc3339, print_timezone) = best_effort_iso8601_to_rfc3339 x in
6768
match Ptime.of_rfc3339 rfc3339 |> Ptime.rfc3339_error_to_msg with
6869
| Error (`Msg e) -> invalid_arg (Printf.sprintf "date.ml:of_string: %s" x)
6970
| Ok (t, tz, _) -> match tz with
70-
| None | Some 0 -> Ptime.to_date_time t |> of_dt print_type
71+
| None | Some 0 -> Ptime.to_date_time t |> of_dt print_timezone
7172
| Some _ -> invalid_arg (Printf.sprintf "date.ml:of_string: %s" x)
7273

7374
let to_string ((y,mon,d), ((h,min,s), _), print_type) =
7475
match print_type with
75-
| PrintUTC -> Printf.sprintf "%04i%02i%02iT%02i:%02i:%02iZ" y mon d h min s
76-
| PrintLocal -> Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i" y mon d h min s
76+
| TZ tz -> Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i%s" y mon d h min s tz
77+
| Empty -> Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i" y mon d h min s
7778

7879
let to_ptime_t t =
7980
match to_dt t |> Ptime.of_date_time with
@@ -85,21 +86,13 @@ let to_ptime_t t =
8586
let of_float s =
8687
match Ptime.of_float_s s with
8788
| None -> invalid_arg (Printf.sprintf "date.ml:of_float: %f" s)
88-
| Some t -> Ptime.to_date_time t |> of_dt PrintUTC
89-
90-
(* Convert tm in UTC back into calendar time x (using offset between above
91-
UTC and localtime fns to determine offset between UTC and localtime, then
92-
correcting for this)
93-
*)
94-
let to_float t =
95-
let (_, _, print_type) = t in
96-
match print_type with
97-
| PrintLocal -> invalid_arg "date.ml:to_float: expected utc"
98-
| PrintUTC -> to_ptime_t t |> Ptime.to_float_s
89+
| Some t -> Ptime.to_date_time t |> of_dt utc
90+
91+
let to_float t = to_ptime_t t |> Ptime.to_float_s
9992

10093
let _localtime current_tz_offset t =
10194
let tz_offset_s = current_tz_offset |> Option.value ~default:0 in
102-
let localtime = t |> Ptime.to_date_time ~tz_offset_s |> of_dt PrintLocal in
95+
let localtime = t |> Ptime.to_date_time ~tz_offset_s |> of_dt Empty in
10396
let (_, (_, localtime_offset), _) = localtime in
10497
if localtime_offset <> tz_offset_s then
10598
invalid_arg (

lib/xapi-stdext-date/date.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ type iso8601
2121
(** Convert calendar time [x] (as returned by e.g. Unix.time), to time in UTC. *)
2222
val of_float : float -> iso8601
2323

24-
(** Convert date/time to a float value: the number of seconds since 00:00:00 UTC, 1 Jan 1970. *)
24+
(** Convert date/time to a float value: the number of seconds since 00:00:00 UTC, 1 Jan 1970.
25+
* Assumes the underlying iso8601 is in UTC *)
2526
val to_float : iso8601 -> float
2627

2728
(** Convert date/time to an ISO 8601 formatted string. *)

lib/xapi-stdext-date/test.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ let iso8601_tests =
6868
check_string "can process missing tz no dash" missing_tz_no_dash (missing_tz_no_dash |> of_string |> to_string) ;
6969
check_string "can process missing tz with dashes, but return without dashes" missing_tz_no_dash (missing_tz_dash |> of_string |> to_string) ;
7070

71+
check_float "to_float assumes UTC" 1607620760. (missing_tz_no_dash |> of_string |> to_float) ;
72+
7173
let localtime' = localtime () in
7274
check_string "to_string inverts of_string for localtime" (localtime' |> to_string) (localtime' |> to_string |> of_string |> to_string) ;
7375
in

0 commit comments

Comments
 (0)