package timedesc

  1. Overview
  2. Docs

Source file ISO8601.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
let to_date_time s : (Date_time.t, string) result =
  let open MParser in
  let open Parser_components in
  let hm_p =
    choice
      [
        attempt
          (two_digit_nat_zero
           >>= fun hour ->
           optional (char ':')
           >> two_digit_nat_zero
           >>= fun minute -> return (hour, minute));
        (two_digit_nat_zero >>= fun hour -> return (hour, 0));
      ]
  in
  let hms_p =
    choice
      [
        attempt
          (two_digit_nat_zero
           >>= fun hour ->
           optional (char ':')
           >> two_digit_nat_zero
           >>= fun minute ->
           optional (char ':')
           >> two_digit_nat_zero
           >>= fun second ->
           choice [ char '.'; char ',' ]
           >> num_string
           >>= fun s ->
           let s = if String.length s > 9 then String.sub s 0 9 else s in
           let len = String.length s in
           if len = 9 then return (hour, minute, second, int_of_string s)
           else
             let diff = 9 - len in
             let ns =
               int_of_float
               @@ CCFloat.round
               @@ (float_of_int (int_of_string s) *. (10. ** float_of_int diff))
             in
             return (hour, minute, second, ns));
        attempt
          (two_digit_nat_zero
           >>= fun hour ->
           optional (char ':')
           >> two_digit_nat_zero
           >>= fun minute ->
           optional (char ':')
           >> two_digit_nat_zero
           >>= fun second -> return (hour, minute, second, 0));
        (hm_p |>> fun (hour, minute) -> (hour, minute, 0, 0));
      ]
  in
  let offset_p =
    char 'Z'
    >>$ Span.zero
        <|> (char '+'
             >>$ `Pos
                 <|> (char '-' >>$ `Neg)
             >>= fun sign ->
             hm_p
             |>> fun (hour, minute) ->
             Span.For_human'.make_exn ~sign ~hours:hour ~minutes:minute ())
  in
  let p =
    nat_zero
    >>= fun year ->
    char '-'
    >> max_two_digit_nat_zero
    >>= fun month ->
    char '-'
    >> max_two_digit_nat_zero
    >>= fun day ->
    any_char
    >> hms_p
    >>= fun (hour, minute, second, ns) ->
    offset_p
    >>= fun offset ->
    let hour, minute, second, ns =
      if hour = 24 && minute = 0 && second = 0 && ns = 0 then
        (23, 59, 59, Span.ns_count_in_s - 1)
      else (hour, minute, second, ns)
    in
    match
      Date_time.Ymd_date_time.make_unambiguous ~year ~month ~day ~hour ~minute
        ~second ~ns ~offset_from_utc:offset ()
    with
    | Error e ->
      fail
        (Printf.sprintf "Invalid date time: %s"
           (Date_time.Ymd_date_time.string_of_error e))
    | Ok x -> return x
    | exception Invalid_argument msg -> fail msg
  in
  parse_string p s () |> result_of_mparser_result

let to_timestamp s =
  match to_date_time s with
  | Ok dt -> Ok (Date_time.to_timestamp_single dt)
  | Error msg -> Error msg
OCaml

Innovation. Community. Security.