TzWorld (TzWorld v2.3.0)

Copy Markdown View Source

Resolve a timezone name from coordinates.

Summary

Functions

Returns all timezone name found for the given coordinates specified as either a Geo.Point, a Geo.PointZ or a tuple {lng, lat}

Returns the OTP app name of :tz_world

Reload the timezone geometry data from the on-disk files.

Returns the first timezone name found for the given coordinates specified as either a Geo.Point, a Geo.PointZ or a tuple {lng, lat}

Returns the installed version of time zone data

Types

backend()

@type backend() :: module()

backend_result()

@type backend_result() :: {:ok, term()} | {:error, term()}

Functions

all_timezones_at(point, backend \\ fetch_backend())

@spec all_timezones_at(Geo.Point.t(), backend()) :: {:ok, [String.t()]}
@spec all_timezones_at(Geo.PointZ.t(), backend()) :: {:ok, [String.t()]}
@spec all_timezones_at(
  {lng :: number(), lat :: number()},
  backend()
) :: {:ok, [String.t()]}

Returns all timezone name found for the given coordinates specified as either a Geo.Point, a Geo.PointZ or a tuple {lng, lat}

Arguments

  • point is a Geo.Point.t() a Geo.PointZ.t() or a tuple {lng, lat}

  • backend is any backend access module.

Returns

  • {:ok, timezone} or

  • {:error, :time_zone_not_found}

Notes

Note that the point is always expressed as lng followed by lat.

Examples

iex> TzWorld.all_timezones_at(%Geo.Point{coordinates: {3.2, 45.32}})
{:ok, ["Europe/Paris"]}

iex> TzWorld.all_timezones_at({3.2, 45.32})
{:ok, ["Europe/Paris"]}

iex> TzWorld.all_timezones_at({0.0, 0.0})
{:ok, []}

The algorithm starts by filtering out timezones whose bounding box does not contain the given point.

Once filtered, all timezones which contains the given point is returned, or an error tuple if none of the timezones match.

In rare cases, typically due to territorial disputes, one or more timezones may apply to a given location. This function returns all time zones that match.

app_name()

Returns the OTP app name of :tz_world

fetch_backend()

reload_timezone_data()

@spec reload_timezone_data() ::
  {:ok, [{module(), backend_result()}]} | {:error, [{module(), term()}]}

Reload the timezone geometry data from the on-disk files.

Iterates the list of known backends and asks each one that is currently running in this node to reload itself from disk. Backends that are not running are skipped — the function is safe to call regardless of which backends the host application has added to its supervision tree.

Returns

  • {:ok, results} when every running backend reloaded successfully. results is a list of {backend, result} pairs in reload order.

  • {:error, failures} when one or more running backends failed to reload. failures is a list of {backend, reason} pairs for the backends that did not return {:ok, _}.

Notes

  • Reload is performed sequentially in a fixed order (DetsWithIndexCache, EtsWithIndexCache, SpatialIndex) because EtsWithIndexCache reads from the DETS file rebuilt by DetsWithIndexCache.

  • Each backend's reload runs inside its own GenServer call, so concurrent reload requests against a single backend are serialized at its mailbox.

  • Lookups during reload are safe: SpatialIndex swaps its persistent-term entry atomically, and the other backends process lookup messages only after the reload returns.

Telemetry

The reload emits the following events:

  • [:tz_world, :reload, :start | :stop | :exception] — wraps the full call. :stop measurements include :duration. :stop metadata includes :result (the return value), :backends (list of running backends that participated), and :failure_count.

  • [:tz_world, :reload, :backend, :start | :stop | :exception] — wraps each per-backend reload. Metadata includes :backend (the module). :stop metadata also includes :result.

Example

# An app running only the default backend
TzWorld.reload_timezone_data()
#=> {:ok, [{TzWorld.Backend.SpatialIndex, {:ok, :loaded}}]}

timezone_at(point, backend \\ fetch_backend())

@spec timezone_at(Geo.Point.t(), backend()) :: {:ok, String.t()} | {:error, atom()}
@spec timezone_at(Geo.PointZ.t(), backend()) :: {:ok, String.t()} | {:error, atom()}
@spec timezone_at(
  {lng :: number(), lat :: number()},
  backend()
) :: {:ok, String.t()} | {:error, atom()}

Returns the first timezone name found for the given coordinates specified as either a Geo.Point, a Geo.PointZ or a tuple {lng, lat}

Arguments

  • point is a Geo.Point.t() a Geo.PointZ.t() or a tuple {lng, lat}

  • backend is any backend access module.

Returns

  • {:ok, timezone} or

  • {:error, :time_zone_not_found}

Notes

Note that the point is always expressed as lng followed by lat.

Examples

iex> TzWorld.timezone_at(%Geo.Point{coordinates: {3.2, 45.32}})
{:ok, "Europe/Paris"}

iex> TzWorld.timezone_at({3.2, 45.32})
{:ok, "Europe/Paris"}

iex> TzWorld.timezone_at({0.0, 0.0})
{:error, :time_zone_not_found}

The algorithm starts by filtering out timezones whose bounding box does not contain the given point.

Once filtered, the first timezone which contains the given point is returned, or an error tuple if none of the timezones match.

In rare cases, typically due to territorial disputes, one or more timezones may apply to a given location. This function returns the first time zone that matches.

version()

@spec version() :: {:ok, String.t()} | {:error, :enoent}

Returns the installed version of time zone data

Example

TzWorld.version
=> {:ok, "2020d"}