package timere

  1. Overview
  2. Docs
type t

This is the core type of Timere used to encode computation over time.

The following documentation may call value of type t "a Timere object", or "timere".

exception Invalid_format_string of string

Printing exception

type tz_offset_s = int
type timestamp = int64
type 'a range = [
  1. | `Range_inc of 'a * 'a
  2. | `Range_exc of 'a * 'a
]

Basic constructors

val now : unit -> t

Time right now

val always : t

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)

val empty : t

Empty interval

val years : int list -> t

years l is a shorthand for pattern ~years:l ()

val year_ranges : int range list -> t

year_ranges l is a shorthand for pattern ~year_ranges:l ()

type month = [
  1. | `Jan
  2. | `Feb
  3. | `Mar
  4. | `Apr
  5. | `May
  6. | `Jun
  7. | `Jul
  8. | `Aug
  9. | `Sep
  10. | `Oct
  11. | `Nov
  12. | `Dec
]
val months : month list -> t

months l is a shorthand for pattern ~months:l ()

val month_ranges : month range list -> t

month_ranges l is a shorthand for pattern ~month_ranges:l ()

val days : int list -> t

days l is a shorthand for pattern ~month_days:l ()

val day_ranges : int range list -> t

day_ranges l is a shorthand for pattern ~month_day_ranges:l ()

type weekday = [
  1. | `Sun
  2. | `Mon
  3. | `Tue
  4. | `Wed
  5. | `Thu
  6. | `Fri
  7. | `Sat
]
val weekdays : weekday list -> t

weekdays l is a shorthand for pattern ~weekdays:l ()

val weekday_ranges : weekday range list -> t

weekday_ranges l is a shorthand for pattern ~weekday_ranges:l ()

val hours : int list -> t

hours l is a shorthand for pattern ~hours:l ()

val hour_ranges : int range list -> t

hour_ranges l is a shorthand for pattern ~hour_ranges:l ()

val minutes : int list -> t

minutes l is a shorthand for pattern ~minutes:l ()

val minute_ranges : int range list -> t

minute_ranges l is a shorthand for pattern ~minute_ranges:l ()

val seconds : int list -> t

seconds l is a shorthand for pattern ~seconds:l ()

val second_ranges : int range list -> t

second_ranges l is a shorthand for pattern ~second_ranges:l ()

val pattern : ?years:int list -> ?year_ranges:int range list -> ?months:month list -> ?month_ranges:month range list -> ?days:int list -> ?day_ranges:int range list -> ?weekdays:weekday list -> ?weekday_ranges: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 -> unit -> t

Pattern matches over date times.

A pattern p matches date time dt if

(dt.year is in p.years or p.year_ranges)
&& (dt.month is in p.months or p.month_ranges)
&& (dt.month_day is in p.month_days or p.month_day_ranges)
&& (dt.weekday is in p.weekdays or p.weekday_ranges)
&& (dt.hour is in p.hours or p.hour_ranges)
&& (dt.minute is in p.minutes or p.minute_ranges)
&& (dt.second is in p.seconds or p.second_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.

val nth_weekday_of_month : int -> weekday -> t

nth_weekday_of_month n wday picks the nth weekday of all months, where 1 <= n && n <= 5

Algebraic operations

val inter : t list -> t

Intersection of list of timeres.

inter [] is equivalent to empty.

val union : t list -> t

Union of list of timeres.

union [] is equivalent to empty.

val not : t -> t

Negation of timere.

not t is equivalent to all the intervals not included in t.

Duration

module Duration : sig ... end
val shift : Duration.t -> t -> t
val lengthen : Duration.t -> t -> t

Time zone

module Time_zone : sig ... end
val with_tz : Time_zone.t -> t -> t

with_tz tz t changes the time zone to evaluate t in to tz

Date time and timestamps

module Date_time : sig ... end
val date_time : Date_time.t -> t
val before : Date_time.t -> t
val after : Date_time.t -> t
val date_times : Date_time.t list -> t
val date_time_seq : Date_time.t Seq.t -> t
val sorted_date_times : Date_time.t list -> t
val sorted_date_time_seq : Date_time.t Seq.t -> t
val timestamp_now : unit -> timestamp
val timestamp_min : int64
val timestamp_max : int64
exception Invalid_timestamp
val timestamp : timestamp -> t
val before_timestamp : timestamp -> t
val after_timestamp : timestamp -> t
val timestamps : ?skip_invalid:bool -> timestamp list -> t

timestamps l

skip_invalid defaults to false

val timestamp_seq : ?skip_invalid:bool -> timestamp Seq.t -> t

timestamps s

skip_invalid defaults to false

val sorted_timestamps : ?skip_invalid:bool -> timestamp list -> t
val sorted_timestamp_seq : ?skip_invalid:bool -> timestamp Seq.t -> t

Intervals

Explicit

exception Interval_is_invalid
exception Intervals_are_not_sorted
type interval = timestamp * timestamp
val intervals : ?skip_invalid:bool -> interval list -> t

intervals l

skip_invalid defaults to false

val interval_seq : ?skip_invalid:bool -> interval Seq.t -> t

interval_seq s

skip_invalid defaults to false

val sorted_intervals : ?skip_invalid:bool -> interval list -> t

sorted_intervals l

skip_invalid defaults to false

val sorted_interval_seq : ?skip_invalid:bool -> interval Seq.t -> t

sorted_interval_seq s

skip_invalid defaults to false

Pattern matching

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

type points
val make_points : ?tz:Time_zone.t -> ?tz_offset_s:int -> ?year:int -> ?month:month -> ?day:int -> ?weekday:weekday -> ?hour:int -> ?minute:int -> second:int -> unit -> points option

make_points call must be exactly one of the following forms (ignoring tz and tz_offset_s which are optional in all cases)

make_points ~year:_ ~month:_ ~day:_     ~hour:_ ~minute:_ ~second:_ ()
make_points         ~month:_ ~day:_     ~hour:_ ~minute:_ ~second:_ ()
make_points                  ~day:_     ~hour:_ ~minute:_ ~second:_ ()
make_points                  ~weekday:_ ~hour:_ ~minute:_ ~second:_ ()
make_points                             ~hour:_ ~minute:_ ~second:_ ()
make_points                                     ~minute:_ ~second:_ ()
make_points                                               ~second:_ ()

returns Error otherwise

val make_points_exn : ?tz:Time_zone.t -> ?tz_offset_s:int -> ?year:int -> ?month:month -> ?day:int -> ?weekday:weekday -> ?hour:int -> ?minute:int -> second:int -> unit -> points
val bounded_intervals : [ `Whole | `Snd ] -> Duration.t -> points -> points -> t

bounded_intervals mode bound 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, yields (x, y)
  • if mode = `Snd, yields (y, y + 1)

Examples:

bounded_intervals `Whole (Duration.make ~days:1 ())
  (make_points ~hour:13 ~minute:0 ~second:0 ()) (* p1 *)
  (make_points ~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

bounded_intervals `Whole (Duration.make ~days:1 ())
  (make_points ~month:`Feb ~day:10 ~hour:13 ~minute:0 ~second:0 ()) (* p1 *)
  (make_points                     ~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")

bounded_intervals `Whole (Duration.make ~days:1 ())
  (make_points ~month:`Feb ~day:10 ~hour:23 ~minute:0 ~second:0 ()) (* p1 *)
  (make_points                     ~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")

  • raises Invalid_argument

    if precision (number of date time arguments passed to make_points during construction) of p1 < precision of p2

    For example, make_points_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 bounded_intervals

type hms = private {
  1. hour : int;
  2. minute : int;
  3. second : int;
}
val make_hms : hour:int -> minute:int -> second:int -> hms option
val make_hms_exn : hour:int -> minute:int -> second:int -> hms
val hms_intervals_inc : hms -> hms -> t

Same as hms_intervals_exc ... with end point increased by one second

val hms_intervals_exc : hms -> hms -> t

Same as bounded_intervals ... with bound fixed to Duration.make ~days:1 ()

val pp_hms : Format.formatter -> hms -> unit
val string_of_hms : hms -> string

Chunking

type chunked
type chunking = [
  1. | `Disjoint_intervals
  2. | `By_duration of Duration.t
  3. | `By_duration_drop_partial of Duration.t
  4. | `At_year_boundary
  5. | `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)
val chunk : chunking -> (chunked -> chunked) -> t -> t

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

val chunk_again : chunking -> chunked -> chunked

chunk_again chunking f applies chunked selector f as a selector

val first : chunked -> chunked

Takes only first chunk

val take : int -> chunked -> chunked

Takes n chunks

val take_nth : int -> chunked -> chunked

Take every nth chunk, specifically 0th, nth, 2nth, 3nth, ...

val drop : int -> chunked -> chunked

Discard n chunks

Lightweight chunking

These are strictly less flexible than chunking functions provided in Chunking, but can be significantly more efficient than the equivalent implemented with chunk ...

val first_point : t -> t
val take_points : int -> t -> t
val drop_points : int -> t -> t

Infix operators

val (&) : t -> t -> t
val (|||) : t -> t -> t
val (%>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c

Composition, mainly for chunked selectors

f1 %> f2 is equivalent to fun x -> x |> f1 |> f2.

Resolution

val resolve : ?search_using_tz:Time_zone.t -> t -> (interval Seq.t, string) result

Resolves a Timere object into a concrete interval sequence

Pretty printers

val string_of_timestamp : ?display_using_tz:Time_zone.t -> ?format:string -> timestamp -> string

Pretty printing for timestamp.

Follows same format string rules and default format string as Date_time.to_string.

val pp_timestamp : ?display_using_tz:Time_zone.t -> ?format:string -> unit -> Format.formatter -> timestamp -> unit
val string_of_interval : ?display_using_tz:Time_zone.t -> ?format:string -> interval -> string

Pretty printing for interval.

Default format string:

[{syear} {smon:Xxx} {smday:0X} {shour:0X}:{smin:0X}:{ssec:0X} \
{stzoff-sign}{stzoff-hour:0X}:{stzoff-min:0X}:{stzoff-sec:0X}, {eyear} \
{emon:Xxx} {emday:0X} {ehour:0X}:{emin:0X}:{esec:0X} \
{etzoff-sign}{etzoff-hour:0X}:{etzoff-min:0X}:{etzoff-sec:0X})

Follows same format string rules as Date_time.to_string, but tags are prefixed with 's' for "start time", and 'e' for "end exc time", e.g. for interval (x, y)

  • {syear} gives year of the x
  • {ehour:cX} gives hour of the y
val pp_interval : ?display_using_tz:Time_zone.t -> ?format:string -> unit -> Format.formatter -> interval -> unit
val pp_intervals : ?display_using_tz:Time_zone.t -> ?format:string -> ?sep:unit Fmt.t -> unit -> Format.formatter -> interval Seq.t -> unit

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.

val to_sexp : t -> CCSexp.t
val to_sexp_string : t -> string
val of_sexp : CCSexp.t -> (t, string) result
val of_sexp_string : string -> (t, string) result
val pp_sexp : Format.formatter -> t -> unit

Misc

module Utils : sig ... end
OCaml

Innovation. Community. Security.