# `Tempo.LeapSeconds`
[🔗](https://github.com/kipcole9/tempo/blob/v0.5.0/lib/tempo/leap_seconds.ex#L1)

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
2035) the list should be extended and a new Tempo release cut.

# `dates`

```elixir
@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`

```elixir
@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?`

```elixir
@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`

```elixir
@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()
    []

---

*Consult [api-reference.md](api-reference.md) for complete listing*
