From 94cab8a08505bf283bfd5326fcdfc6daca8c6514 Mon Sep 17 00:00:00 2001 From: "Petter A. Urkedal" Date: Tue, 31 Dec 2019 14:38:07 +0100 Subject: [PATCH] Fix timezone and sub-second in RFC822 parser. --- lib/syndic_date.ml | 62 ++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/lib/syndic_date.ml b/lib/syndic_date.ml index 7d965bd..5ba9d75 100644 --- a/lib/syndic_date.ml +++ b/lib/syndic_date.ml @@ -43,43 +43,35 @@ let of_rfc822 s = float_of_string (String.sub maybe_s 1 (String.length maybe_s - 1)) else 0. in - let span = Ptime.Span.of_int_s ((h * 3600) + (m * 60)) in - let span = - map (fun x -> Some (Ptime.Span.add span x)) (Ptime.Span.of_float_s s) + (* FIXME: this should be made more robust. *) + let tz_offset_s = + match z with + | "" | "GMT" | "UT" | "Z" -> 0 + | "EST" -> -5 * 3600 + | "EDT" -> -4 * 3600 + | "CST" -> -6 * 3600 + | "CDT" -> -5 * 3600 + | "MST" -> -7 * 3600 + | "MDT" -> -6 * 3600 + | "PST" -> -8 * 3600 + | "PDT" -> -7 * 3600 + | "A" -> -1 * 3600 + | "M" -> -12 * 3600 + | "N" -> 1 * 3600 + | "Y" -> 12 * 3600 + | _ -> + let zh = sscanf (String.sub z 0 3) "%i" (fun i -> i) in + let zm = sscanf (String.sub z 3 2) "%i" (fun i -> i) in + let tz_sign = if zh < 0 then -1 else 1 in + if zh < 0 then tz_sign * ((-zh * 3600) + (zm * 60)) + else tz_sign * ((zh * 3600) + (zm * 60)) in - let date_and_time = - if z = "" || z = "GMT" || z = "UT" || z = "Z" then - map2 (fun date span -> Ptime.add_span date span) date span - |> map (fun x -> Some (Ptime.to_date_time x)) - else - (* FIXME: this should be made more robust. *) - let tz_offset_s = - match z with - | "EST" -> -5 * 3600 - | "EDT" -> -4 * 3600 - | "CST" -> -6 * 3600 - | "CDT" -> -5 * 3600 - | "MST" -> -7 * 3600 - | "MDT" -> -6 * 3600 - | "PST" -> -8 * 3600 - | "PDT" -> -7 * 3600 - | "A" -> -1 * 3600 - | "M" -> -12 * 3600 - | "N" -> 1 * 3600 - | "Y" -> 12 * 3600 - | _ -> - let zh = sscanf (String.sub z 0 3) "%i" (fun i -> i) in - let zm = sscanf (String.sub z 3 2) "%i" (fun i -> i) in - let tz_sign = if zh < 0 then -1 else 1 in - if zh < 0 then tz_sign * ((-zh * 3600) + (zm * 60)) - else tz_sign * ((zh * 3600) + (zm * 60)) - in - let rt = map2 (fun date span -> Ptime.add_span date span) date span in - (* XXX: We lose minutes with this conversion, but Calendar does not - propose to handle minutes. *) - map (fun x -> Some (Ptime.to_date_time ~tz_offset_s x)) rt + let span = Ptime.Span.of_int_s ((h * 3600) + (m * 60) - tz_offset_s) in + let span = + map (fun x -> Some (Ptime.Span.add span x)) + (Ptime.Span.of_float_s s) in - match map Ptime.of_date_time date_and_time with + match map2 (fun date span -> Ptime.add_span date span) date span with | Some x -> x | None -> invalid_arg (sprintf "Syndic.Date.of_rfc822: cannot parse") in