# `Tempo.LeapSeconds`
[🔗](https://github.com/elixir-tempo/tempo/blob/v2.1.0/lib/tempo/leap_seconds.ex#L1)

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.

# `date`

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

A UTC date at whose end a leap second falls.

# `count`

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

* `expression` is a `t:Tempo.t/0`, as for `spanned/1`.

### Returns

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

### Examples

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

# `dates`

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

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

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

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

```elixir
@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 `t: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, []}

---

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