package timere
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=1fee8b8201899be96982918c17a4fa2952b18343f91d97b90743a38e4eb8b792
doc/timere/Timere/index.html
Module Timere
Source
Date time reasoning
Timere provides a set of highly expressive APIs to describe scheduling constraints, and an efficient resolution algorithm
This is the core type of Timere that represents sets of points in time, more precisely, unions of time intervals. For example, "all Mondays of year 2000 at the UTC timezone".
We call Timere.t
values "timere object"; internally they are rich expressions representing the time computations (union, intersection, etc.), lazily forced into more low-level descriptions (lazy sequences of intervals).
Basic constructors
Entire interval that Timere can handle, i.e. [0000 Jan 01 14:00:00 +00:00:00, 9999 Dec 31 09:59:58 +00:00:00)
timestamps l
skip_invalid
defaults to false
timestamps s
skip_invalid
defaults to false
Pattern matching constructors
val pattern :
?years:int list ->
?year_ranges:int range list ->
?months:int list ->
?month_ranges:int range list ->
?days:int list ->
?day_ranges:int range list ->
?weekdays:Timedesc.weekday list ->
?weekday_ranges:Timedesc.weekday range list ->
?hours:int list ->
?hour_ranges:int range list ->
?minutes:int list ->
?minute_ranges:int range list ->
?seconds:int list ->
?second_ranges:int range list ->
?ns:int list ->
?ns_ranges:int range list ->
unit ->
t
Pattern matches over date times.
A pattern p
matches date time dt
if
(year of dt is in p.years or p.year_ranges) && (month of dt is in p.months or p.month_ranges) && (month day of dt is in p.month_days or p.month_day_ranges) && (weekday of dt is in p.weekdays or p.weekday_ranges) && (hour of dt is in p.hours or p.hour_ranges) && (minute of dt is in p.minutes or p.minute_ranges) && (second of dt is in p.seconds or p.second_ranges) && (ns of dt is in p.ns or p.ns_ranges)
Empty pattern levels are treated as wildcard, e.g. if p.years
and p.year_ranges
are both empty, then (dt.year is in p.years or p.year_ranges)
is true
.
year_ranges l
is a shorthand for pattern ~year_ranges:l ()
month_ranges l
is a shorthand for pattern ~month_ranges:l ()
day_ranges l
is a shorthand for pattern ~month_day_ranges:l ()
weekdays l
is a shorthand for pattern ~weekdays:l ()
weekday_ranges l
is a shorthand for pattern ~weekday_ranges:l ()
hour_ranges l
is a shorthand for pattern ~hour_ranges:l ()
minute_ranges l
is a shorthand for pattern ~minute_ranges:l ()
second_ranges l
is a shorthand for pattern ~second_ranges:l ()
nth_weekday_of_month n wday
picks the nth weekday of all months, where 1 <= n && n <= 5
Intervals
Explicit intervals
intervals l
skip_invalid
defaults to false
interval_seq s
skip_invalid
defaults to false
sorted_intervals l
skip_invalid
defaults to false
sorted_interval_seq s
skip_invalid
defaults to false
Pattern matching intervals
Pattern matching intervals are designed to handle intervals where start and end points follow some pattern, but cannot be captured by pattern
efficiently, e.g. you cannot represent "5:30pm to 6:11pm" via a single pattern
val pattern_intervals :
?inc_exc:inc_exc ->
?bound:Timedesc.Span.t ->
[ `Whole | `Fst | `Snd ] ->
points ->
points ->
t
pattern_intervals mode p1 p2
for each point x
matched by p1
, then for the earliest point y
matched by p2
such that x < y && y - x <= bound
- if
mode = `Whole && inc_exc = `Exc
, yields (x, y) - if
mode = `Whole && inc_exc = `Inc
, yields (x, y + 1) - if
mode = `Fst
, yields (x, x + 1) - if
mode = `Snd
, yields (y, y + 1)
above implies inc_exc
does not impact operations if mode is `Fst
or `Snd
.
inc_exc
defaults to `Exc
.
Default bound
is inferred as follows, and should suffice in yielding desired results for most cases:
if p2 is YMDHMS then (year of p2 - year of p1 + 1) * 366 days if p2 is MDHMS then 366 days if p2 is DHMS then if day of p1 < day of p2 then 31 - day of p2 days else 31 days if p2 is HMS then 30 hours if p2 is MS then 1 hours if p2 is S then 1 minutes
where we say p2 is YMDHMS
if p2 = Points.make_exn ~year:_ ... ()
and so on.
Examples:
pattern_intervals `Whole
(Points.make ~hour:13 ~minute:0 ~second:0 ()) (* p1 *)
(Points.make ~hour:14 ~minute:0 ~second:0 ()) (* p2 *)
yields all the "1pm to 2pm" intervals, since at each "1pm" mark represented by p1
, searching forward up to 24 hour period, we can find a "2pm" mark in p2
pattern_intervals `Whole
(Points.make ~month:2 ~day:10 ~hour:13 ~minute:0 ~second:0 ()) (* p1 *)
(Points.make ~hour:14 ~minute:0 ~second:0 ()) (* p2 *)
yields all the "Feb 10th 1pm to 2pm" intervals (or specifically "Feb 10th 1pm to Feb 10th 2pm")
pattern_intervals `Whole
(Points.make ~month:`Feb ~day:10 ~hour:23 ~minute:0 ~second:0 ()) (* p1 *)
(Points.make ~hour:3 ~minute:0 ~second:0 ()) (* p2 *)
yields all the "Feb 10th 11pm to 3am" intervals (or specifically "Feb 10th 11pm to Feb 11th 3am")
For example, Points.make_exn ~hour:3 ~minute:0 ~second:0 ()
has a lower precision than make_points_exn ~day:10 ~hour:12 ~minute:30 ~second:0 ()
.
Hour minute second intervals
Convenience wrappers around points
and pattern_intervals
Same as pattern_intervals ...
with bound fixed to Span.For_human.make ~days:1 ()
inc_exc
defaults to `Exc
Algebraic operations
Negation of timere.
not t
is equivalent to all the intervals not included in t
.
with_tz tz t
changes the time zone to evaluate t
in to tz
Chunking
type chunking = [
| `Disjoint_intervals
| `By_duration of Timedesc.Span.t
| `By_duration_drop_partial of Timedesc.Span.t
| `At_year_boundary
| `At_month_boundary
]
Ways to chunk/slice time intervals for the selector.
`Disjoint_intervals
gives a sequence of disjoint intervals to the selector, specifically they are in ascending order, non-overlapping, non-connecting, and unique`By_duration
slices in the fixed size specified by the duration. Partial chunks (chunks less than the fixed size) are preserved.`By_duration_drop_partial
slices in the fixed size specified by the duration. Partial chunks (chunks less than the fixed size) are discarded.`At_year_boundary
slices at the year boundary (e.g.2021 Jan 1st 00:00:00
)`At_month_boundary
slices at the month boundary (e.g.Aug 1st 00:00:00
)
chunk chunking f t
applies chunked
selector f
on t
.
Chunked selectors
You may find (%>)
useful for chaining selectors together, e.g. drop 5 %> take 2
chunk_again chunking f
applies chunked
selector f
as a selector
Take every nth chunk, specifically 0
th, n
th, 2n
th, 3n
th, ...
Infix operators
Composition, mainly for chunked selectors
f1 %> f2
is equivalent to fun x -> x |> f1 |> f2
.
Resolution
val resolve :
?search_using_tz:Timedesc.Time_zone.t ->
t ->
(Timedesc.Interval.t Seq.t, string) result
Resolves a Timere object into a concrete interval sequence. * * Intervals are left-closed, right-open, i.e. each interval is * of the form [x, y)
, which includes x and excludes y. *
S-expressions
These functions are suitable for debugging, serializing and deserializing timeres.
The sexp is a precise description of the steps used to construct a timere. As such deserialization is accurate and goes through the exact same construction steps (including validation) as one would using the construction API directly.