# `NervesTime`
[🔗](https://github.com/nerves-time/nerves_time/blob/v0.4.12/lib/nerves_time.ex#L9)

Keep time in sync on Nerves devices

`NervesTime` keeps the system clock on [Nerves](http://nerves-project.org)
devices in sync when connected to the network and close to in sync when
disconnected. It's especially useful for devices lacking a [Battery-backed
real-time clock](https://en.wikipedia.org/wiki/Real-time_clock) and will
advance the clock at startup to a reasonable guess.

Nearly all configuration is via the application config (`config.exs`). The
following keys are available:

* `:servers` - a list of NTP servers for time synchronization. Specifying an
  empty list turns off NTP
* `:time_file` - a file path for tracking the time. It allows the system to
  start with a reasonable time quickly on boot and before the Internet is
  available for NTP to work.
* `:earliest_time` - times before this are considered invalid and adjusted
* `:latest_time` - times after this are considered invalid and adjusted
* `:ntpd` - the absolute path to the Busybox `ntpd`. This only needs to be
  set if your system does not provide `ntpd` in the `$PATH`.
* `:await_initialization_timeout` - Timeout to await a successful system time
  initialization on startup before continuing asynchronously. Set in milliseconds.
  Defaults to `0`.

# `ntpd_event`

```elixir
@type ntpd_event() ::
  :sync_status | :sync_acquired | :sync_updated | :sync_lost | :clock_step
```

NTP daemon event names emitted to subscribers.

# `ntpd_event_report`

```elixir
@type ntpd_event_report() :: %{
  freq_drift_ppm: integer(),
  offset: float(),
  stratum: integer(),
  poll_interval: integer()
}
```

Metadata reported by the NTP helper script for a synchronization event.

# `sync_status`

```elixir
@type sync_status() :: %{
  synchronized?: boolean(),
  last_sync_report: ntpd_event_report() | nil,
  sync_acquired_at: DateTime.t() | nil,
  last_sync_at: DateTime.t() | nil
}
```

Current NTP synchronization state.

# `ntp_servers`

```elixir
@spec ntp_servers() :: [String.t()] | {:error, term()}
```

Return the current NTP servers

# `restart_ntpd`

```elixir
@spec restart_ntpd() :: :ok | {:error, term()}
```

Manually restart the NTP daemon

This is normally not necessary since `NervesTime` handles restarting it
automatically. An example of a reason to call this function is if you know
when the Internet becomes available. For this case, calling `restart_ntp`
will cancel `ntpd`'s internal timeouts and cause it to immediately send time
requests. If using NTP Pool, be sure not to violate its terms of service by
calling this function too frequently.

# `set_ntp_servers`

```elixir
@spec set_ntp_servers([String.t()]) :: :ok
```

Set the list of NTP servers

Use this function to replace the list of NTP servers that are queried for
time. It is also possible to set this list in your `config.exs` by doing
something like the following:

```elixir
config :nerves_time, :servers, [
  "0.pool.ntp.org",
  "1.pool.ntp.org",
  "2.pool.ntp.org",
  "3.pool.ntp.org"
]
```

`NervesTime` uses [NTP Pool](https://www.ntppool.org/en/) by default. To
disable this and configure servers solely at runtime, specify an empty list
in `config.exs`:

```elixir
config :nerves_time, :servers, []
```

# `set_system_time`

```elixir
@spec set_system_time(NaiveDateTime.t()) :: :ok | :error
```

Set the system time

# `subscribe`

```elixir
@spec subscribe(pid()) :: :ok
```

Subscribe a process to NTP daemon events.

Subscribers receive messages in the form:

    {:nerves_time, event, report}

Where `event` is one of:

  * `:sync_status`
  * `:sync_acquired`
  * `:sync_updated`
  * `:sync_lost`
  * `:clock_step`

`:sync_status` is sent immediately when subscribing so new subscribers can
observe the current synchronization state without replaying old events.

# `sync_status`

```elixir
@spec sync_status() :: sync_status()
```

Return the current NTP synchronization status.

# `synchronized?`

```elixir
@spec synchronized?() :: boolean()
```

Check whether NTP is synchronized with the configured NTP servers

It's possible that the time is already set correctly when this returns false.
`NervesTime` decides that NTP is synchronized when `ntpd` sends a
notification that the device's clock stratum is 4 or less. Clock adjustments
occur before this, though.

Once NTP is synchronized, it will remain that way until the `nerves_time`
application is restarted.

# `unsubscribe`

```elixir
@spec unsubscribe(pid()) :: :ok
```

Unsubscribe a process from NTP daemon events.

---

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