Tempo.LeapSeconds (Tempo v2.1.1)

Copy Markdown View Source

The leap seconds the International Earth Rotation and Reference Systems Service (IERS) has announced since UTC began in 1972, and which of them an expression spans.

A leap second is inserted as 23:59:60 at the end of the 30th of June or the 31st of December UTC. There have been 27, all inserted and none removed. Tempo reads no second numbered 60, as Elixir's own types read none: a leap second is a fact about a span of time, not a value. spanned/1 lists the ones a span holds, and Tempo.duration/2 with leap_seconds: true counts them into its length.

The list is fixed when Tempo is released. The IERS announces a leap second about six months ahead, and the General Conference on Weights and Measures resolved in 2022 to stop inserting them by 2035.

Summary

Types

A UTC date at whose end a leap second falls.

Functions

The seconds an expression's leap seconds add to its length: one for each inserted, less one for each removed.

The UTC dates at whose end a leap second was inserted, in order.

The most recent UTC date at whose end a leap second was inserted.

Whether a leap second was inserted at the end of a UTC date.

The UTC dates at whose end a leap second was removed: the second numbered 59 left out. None has been, and the list is empty until one is announced.

The leap seconds an expression spans: those that fall within the time it covers, each as the UTC date it ends.

Types

date()

@type date() :: {year :: integer(), month :: 1..12, day :: 1..31}

A UTC date at whose end a leap second falls.

Functions

count(expression)

@spec count(Tempo.t()) :: {:ok, integer()} | {:error, Exception.t()}

The seconds an expression's leap seconds add to its length: one for each inserted, less one for each removed.

Arguments

Returns

  • {:ok, seconds}, or {:error, exception} as spanned/1 returns it.

Examples

iex> Tempo.LeapSeconds.count(~o"2015/2017")
{:ok, 2}

dates()

@spec dates() :: [date()]

The UTC dates at whose end a leap second was inserted, in order.

Returns

  • A list of {year, month, day}.

Examples

iex> {2016, 12, 31} in Tempo.LeapSeconds.dates()
true

iex> length(Tempo.LeapSeconds.dates())
27

latest()

@spec latest() :: date()

The most recent UTC date at whose end a leap second was inserted.

Returns

  • {year, month, day}.

Examples

iex> Tempo.LeapSeconds.latest()
{2016, 12, 31}

on_date?(year, month, day)

@spec on_date?(integer(), integer(), integer()) :: boolean()

Whether a leap second was inserted at the end of a UTC date.

Arguments

  • year, month and day are the integers of a Gregorian date.

Returns

  • true or false.

Examples

iex> Tempo.LeapSeconds.on_date?(2016, 12, 31)
true

iex> Tempo.LeapSeconds.on_date?(2026, 12, 31)
false

removals()

@spec removals() :: [date()]

The UTC dates at whose end a leap second was removed: the second numbered 59 left out. None has been, and the list is empty until one is announced.

Returns

  • A list of {year, month, day}.

Examples

iex> Tempo.LeapSeconds.removals()
[]

spanned(expression)

@spec spanned(Tempo.t()) :: {:ok, [date()]} | {:error, Exception.t()}

The leap seconds an expression spans: those that fall within the time it covers, each as the UTC date it ends.

A leap second lies between 23:59:59 and the midnight after it, so a span holds one when it begins before that midnight and runs to it or past it. An expression with no zone is read on UTC's clock.

Arguments

  • expression is a Tempo.t/0 with a year: a value, an interval, a set or a bounded recurrence.

Returns

  • {:ok, dates}, a list of {year, month, day} in order, empty when it spans none.

  • {:error, %Tempo.ConversionError{}} for an expression with no year (:needs_a_year), with no end (:unbounded), or anything that is no expression (:not_an_expression).

Examples

iex> Tempo.LeapSeconds.spanned(~o"2015/2017")
{:ok, [{2015, 6, 30}, {2016, 12, 31}]}

iex> Tempo.LeapSeconds.spanned(~o"2016-12-31T23:59:00Z/2017-01-01T00:01:00Z")
{:ok, [{2016, 12, 31}]}

iex> Tempo.LeapSeconds.spanned(~o"2026-06-15")
{:ok, []}