github ↗
docs menu

Module Talon.Time

Civil time values: stamps, spans and dates.

These are the OCaml values that temporal cells read as: a datetime cell reads as a stamp, a duration or a time of day as a span, and a date as a date. All three are exact integers. Time here is civil (POSIX) time: every day lasts 86,400 seconds and there are no leap seconds. Timescales such as TAI are extension types.

Conversions name their unit, as in to_ms and Span.of_us. Converting to a coarser unit is total and rounds toward negative infinity. Converting from a unit coarser than nanoseconds can overflow: the of_* functions then return None, and the Span constructors raise Invalid_argument.

Instants and wall clocks

A stamp is a signed count of nanoseconds since 1970-01-01 00:00:00 on a clock, from -263 to 263 - 1, about 1677-09-21 to 2262-04-11. A stamp's type states which of two clocks it counts. An instant counts UTC. It is a point on the global timeline, the same reading for everyone. A wall clock counts a local calendar and clock face, a reading a person saw, such as a logger's 02:30. A wall clock takes an instant only once a zone says where the clock hung, and two sites' wall clocks do not compare as moments.

The two meet only through a zone, in Talon.Expr.Temporal: wall reads an instant on a zone's clock, and localize finds a wall clock's instant under stated policies, because a zone's clock can skip or repeat a reading. A stamp of the wrong clock is a type error, so a literal, a column handle or a function cannot mix the two.

Composing with ptime. An instant becomes a Ptime.t over to_s and to_ns; a wall clock, read as UTC, the same way:

ocaml
let to_ptime t =
  let s = Time.to_s t in
  let ps = Int64.(mul 1000L (sub (Time.to_ns t) (mul s 1_000_000_000L))) in
  Ptime.of_span Ptime.Span.(add (of_int_s (Int64.to_int s)) (v (0, ps)))
#type !+'c stamp

The type for stamps of the clock 'c.

#type utc

The index of the UTC clock.

#type local

The index of a wall clock.

#type instant = utc stamp

The type for instants.

#type wall = local stamp

The type for wall clocks.

#type _ clock =
  1. #| Utc : utc clock
    (*

    The UTC clock of an instant.

    *)
  2. #| Local : local clock
    (*

    The clock of a wall clock.

    *)

The type for the witness of a stamp's clock, which a column type holds.

#val of_ns : int64 -> 'c stamp

of_ns n is the stamp n nanoseconds after 1970-01-01 00:00:00 of its clock.

#val of_us : int64 -> 'c stamp option

of_us n is the stamp n microseconds after 1970-01-01 00:00:00 of its clock, or None if it is out of range.

#val of_ms : int64 -> 'c stamp option

of_ms n is like of_us in milliseconds.

#val of_s : int64 -> 'c stamp option

of_s n is like of_us in seconds.

#val to_ns : 'c stamp -> int64

to_ns t is the number of nanoseconds from 1970-01-01 00:00:00 of t's clock to t.

#val to_us : 'c stamp -> int64

to_us t is the number of whole microseconds from 1970-01-01 00:00:00 of t's clock to t, rounded toward negative infinity: the stamp one nanosecond before the epoch gives -1L. of_us (to_us t) is t whenever t is a whole microsecond.

#val to_ms : 'c stamp -> int64

to_ms t is like to_us in milliseconds.

#val to_s : 'c stamp -> int64

to_s t is like to_us in seconds.

#val equal : 'c stamp -> 'c stamp -> bool

equal t0 t1 is true iff t0 and t1 are the same reading of one clock.

#val compare : 'c stamp -> 'c stamp -> int

compare t0 t1 orders stamps of one clock chronologically. It is compatible with equal.

#val pp : Stdlib.Format.formatter -> 'c stamp -> unit

pp ppf t formats t as its civil date and time of day in ISO 8601's extended format, YYYY-MM-DDThh:mm:ss, followed by a point and 3, 6 or 9 digits, the fewest that are exact, when t is not a whole second: 2024-03-15T09:30:00, 1969-12-31T23:59:59.999999999. It writes no zone designator, since a stamp does not hold its clock at run time.

Spans

#type span

The type for spans: a signed count of nanoseconds, from -263 to 263 \- 1, about 292 years either way. A span lasts the same everywhere; calendar lengths such as a month are steps.

#module Span : sig ... end

Spans.

Dates

#type date

The type for dates: a day of the proleptic Gregorian calendar, counted in days since 1970-01-01. Dates range over the days that fit in a signed 32-bit integer, about the years -5,877,641 to 5,881,580.

#module Date : sig ... end

Dates.

Calendar steps

#type step =
  1. #| Months of int
    (*

    Months n is n calendar months.

    *)
  2. #| Weeks of int
    (*

    Weeks n is n calendar weeks. Weeks begin on Monday.

    *)
  3. #| Days of int
    (*

    Days n is n calendar days.

    *)
  4. #| Exact of span
    (*

    Exact d is the span d.

    *)

The type for steps: the units in which temporal expressions floor and offset stamps and dates. A step of n calendar units has no fixed length, since months have 28 to 31 days and, in a zone with daylight saving time, a day lasts 23, 24 or 25 hours.

#val pp_step : Stdlib.Format.formatter -> step -> unit

pp_step ppf s formats Months n as nmo, Weeks n as nw, Days n as nd, and Exact d as Span.pp formats d: 1mo, 2w, -1d, 15m.