This repository has no description
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** Date and time types for JMAP.
7
8 JMAP uses RFC 3339 formatted date-time strings. *)
9
10(** RFC 3339 date-time with any timezone offset *)
11module Rfc3339 = struct
12 type t = Ptime.t
13
14 let of_string s =
15 match Ptime.of_rfc3339 s with
16 | Ok (t, _, _) -> Ok t
17 | Error _ -> Error (Printf.sprintf "Invalid RFC 3339 date: %s" s)
18
19 let to_string t =
20 (* Format with 'T' separator and timezone offset *)
21 Ptime.to_rfc3339 ~tz_offset_s:0 t
22
23 let jsont =
24 let kind = "Date" in
25 let dec s =
26 match of_string s with
27 | Ok t -> t
28 | Error msg -> Jsont.Error.msgf Jsont.Meta.none "%s: %s" kind msg
29 in
30 let enc = to_string in
31 Jsont.map ~kind ~dec ~enc Jsont.string
32end
33
34(** UTC date-time (must use 'Z' timezone suffix) *)
35module Utc = struct
36 type t = Ptime.t
37
38 let of_string s =
39 (* Must end with 'Z' for UTC *)
40 let len = String.length s in
41 if len > 0 && s.[len - 1] <> 'Z' then
42 Error "UTCDate must use 'Z' timezone suffix"
43 else
44 match Ptime.of_rfc3339 s with
45 | Ok (t, _, _) -> Ok t
46 | Error _ -> Error (Printf.sprintf "Invalid RFC 3339 UTC date: %s" s)
47
48 let to_string t =
49 (* Always format with 'Z' suffix *)
50 Ptime.to_rfc3339 ~tz_offset_s:0 t
51
52 let of_ptime t = t
53 let to_ptime t = t
54
55 let jsont =
56 let kind = "UTCDate" in
57 let dec s =
58 match of_string s with
59 | Ok t -> t
60 | Error msg -> Jsont.Error.msgf Jsont.Meta.none "%s: %s" kind msg
61 in
62 let enc = to_string in
63 Jsont.map ~kind ~dec ~enc Jsont.string
64end