Tempo.LeapSeconds (Tempo v0.5.0)

Copy Markdown View Source

The canonical list of positive leap seconds announced by the International Earth Rotation and Reference Systems Service (IERS) since the UTC–TAI framework began in 1972.

A leap second is inserted as 23:59:60 at the end of either June 30 or December 31 UTC. The values below are the official IERS Bulletin C insertion dates; there have been 27 positive leap seconds to date and no negative ones.

This module is the reference used by Tempo.Interval.spans_leap_second?/1 and Tempo.Interval.leap_seconds_spanned/1 to detect whether a half-open interval contains a real IERS insertion.

The data is static; IERS publishes new bulletins twice a year, and when a new leap second is announced (or negative ones adopted — the CGPM agreed in 2022 to phase leap seconds out by

  1. the list should be extended and a new Tempo release cut.

Summary

Functions

Return the list of {year, month, day} tuples on which a positive leap second has been inserted.

Return the most recent {year, month, day} on which a leap second was inserted.

Return true when a positive leap second was inserted at the end of the given UTC date (i.e. 23:59:60 UTC exists on that day).

Return the list of {year, month, day} tuples on which a negative leap second has been announced.

Functions

dates()

@spec dates() :: [{integer(), 1..12, 1..31}, ...]

Return the list of {year, month, day} tuples on which a positive leap second has been inserted.

Examples

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

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

latest()

@spec latest() :: {integer(), 1..12, 1..31}

Return the most recent {year, month, day} on which a leap second was inserted.

Useful for documentation, UI, and "are we likely to hit a leap second soon?" reasoning. Not used by the validator.

Examples

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

on_date?(year, month, day)

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

Return true when a positive leap second was inserted at the end of the given UTC date (i.e. 23:59:60 UTC exists on that day).

Arguments

  • year, month, day are integers. Month must be 6 or 12 and day must be 30 or 31 respectively for any leap second to have been possible — other inputs return false.

Examples

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

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

iex> Tempo.LeapSeconds.on_date?(2016, 6, 30)
false

removals()

@spec removals() :: [{integer(), 1..12, 1..31}]

Return the list of {year, month, day} tuples on which a negative leap second has been announced.

A negative leap second removes the final second of a UTC day — the second numbered 58 is followed directly by 00 of the next minute, with no 59. No negative leap second has ever been used since UTC–TAI began in 1972, but the CGPM agreed in 2022 that they may become necessary from roughly 2035 onwards (and that the leap-second mechanism will be replaced entirely by around 2035–2040).

The list is empty today. When IERS announces one, it will be added here, and interval-level detection via Tempo.Interval.spans_leap_second?/1 will cover both positive and negative insertions. Negative leap seconds will contribute a -1 second to Tempo.Interval.duration(iv, leap_seconds: true) rather than +1.

Examples

iex> Tempo.LeapSeconds.removals()
[]