(** The temporal identity of a date: where in the liturgical year it sits, and the temporal cycle's own office for it. *) type ('s, 'r) t = { season : 's; week : int option; (** [None] exactly when the date falls outside every numbered week the rite defines (e.g. a season with no week numbering at all, or a transitional span between two numbered runs). A day being *named* is not by itself a reason for [None]: a named day that sits inside a numbered season run must carry that run's week the same as any other day in it. *) weekday : Date.weekday; office : 'r Celebration.t; } [@@deriving sexp] module type RITE = sig val id : string type season type rank val vocab : (season, rank) Vocab.t (** First day of the liturgical year opening in civil year [y]. *) val year_start : int -> Date.t (** Total over 1583..9999: every date yields exactly one temporal identity. *) val temporal : Date.t -> (season, rank) t end