diff options
Diffstat (limited to 'lib/kernel/date_spec.ml')
| -rw-r--r-- | lib/kernel/date_spec.ml | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/lib/kernel/date_spec.ml b/lib/kernel/date_spec.ml index 76e21e3..732f6b1 100644 --- a/lib/kernel/date_spec.ml +++ b/lib/kernel/date_spec.ml @@ -4,7 +4,11 @@ open Sexplib0.Sexp_conv sanctoral needs -- a fixed calendar date -- because EF movable feasts come from the rite's temporal code, not from data. Sunday-relative and Easter-relative forms arrive with the OF sanctoral. *) -type t = Fixed of { month : int; day : int } [@@deriving sexp] +module Repr = struct + type t = Fixed of { month : int; day : int } [@@deriving sexp] +end + +type t = Repr.t = Fixed of { month : int; day : int } (* Leap-year maximum, so 29 February is constructible; it simply does not resolve in a common year. *) @@ -23,3 +27,17 @@ let fixed ~month ~day = let resolve t ~year = match t with | Fixed { month; day } -> Result.to_option (Date.make ~year ~month ~day) + +let sexp_of_t = Repr.sexp_of_t + +(* Validating parser, matching Slug and Lang: [ppx_sexp_conv]'s derived + [t_of_sexp] (relocated to [Repr] above) accepts any in-range int pair, so + [(Fixed (month 13) (day 40))] would otherwise deserialise into a spec that + silently never resolves -- a saint quietly vanishing with no diagnostic. + Re-running the value through [fixed] closes that gap the same way loaders + already close it for slugs and language codes. *) +let t_of_sexp sexp = + let (Fixed { month; day }) = Repr.t_of_sexp sexp in + match fixed ~month ~day with + | Ok t -> t + | Error msg -> Sexplib0.Sexp_conv.of_sexp_error msg sexp |
