Changelog for Tz_World

Tz_World v2.1.0

This is the changelog for Tz_World v2.1.0 released on April 27th, 2026. For older changelogs please consult the release tag on GitHub.

Enhancements

THe primary focus in this release is peak memory used during the mix tz_world.update process. With the changes in this release, peak memory has been reduced from about 920Mb to about 70Mb.

  • On-disk data format upgraded; existing installations must run mix tz_world.update once after upgrading.

  • The :jason dependency has been removed in favour of the built-in :json module (with :json_polyfill on OTP < 27)."

Tz_World v2.0.0

This is the changelog for Tz_World v2.0.0 released on April 27th, 2026. For older changelogs please consult the release tag on GitHub.

Enhancements

  • Adds TzWorld.Backend.SpatialIndex, a new backend that resolves timezones using a pure-Elixir R-tree (Sort-Tile-Recursive packed) held in :persistent_term. Lookups bypass the GenServer mailbox and read directly from :persistent_term, eliminating the linear bounding-box scan used by the previous backends.

  • TzWorld.Backend.SpatialIndex is now the default backend, and is the first entry in the default backend precedence list. Existing applications that do not pin :default_backend will pick it up automatically.

  • Benchmarked against the previous backends across a categorised fixture set (dense regions, sparse/large zones, small/thin zones, ocean points with no match, points adjacent to the international date line):

    Input categorySpeedup vs. the next-fastest existing backend
    ocean (no-match)18.2×
    sparse_or_large1.64×
    dense (cities)1.43×
    random uniform1.42×
    small_or_thin1.08×

    The largest wins are on no-match queries: previously, points in the open ocean caused a full scan of every shape's bounding box; the R-tree exits at the root.

  • Adds TzWorld.SpatialIndex, a small standalone R-tree implementation (build + stab) used by the new backend.

  • Adds TzWorld.TimezoneFixtures, a categorised set of coordinate fixtures used by both the test suite and the benchmark.

Breaking Changes

  • Removes TzWorld.Backend.Memory. It is strictly dominated by TzWorld.Backend.SpatialIndex on every measured workload (same memory profile, faster lookups, no GenServer round-trip).

  • Removes TzWorld.Backend.Ets. Without an in-memory bbox index, every lookup on a no-match point performed a full ETS scan via match-spec — orders of magnitude slower than the index-cache variant or the new SpatialIndex backend. TzWorld.Backend.EtsWithIndexCache remains for users who want ETS-backed shape storage.

  • Removes TzWorld.Backend.Dets. Same reasoning as Backend.Ets. TzWorld.Backend.DetsWithIndexCache remains for users who want disk-backed shape storage.

Migration

  • Applications that did not configure :default_backend need no changes — TzWorld.Backend.SpatialIndex is selected automatically.

  • Applications that had config :tz_world, default_backend: TzWorld.Backend.Memory (or Ets, Dets) should switch to TzWorld.Backend.SpatialIndex, or to one of the remaining cache-backed alternatives (EtsWithIndexCache, DetsWithIndexCache).

  • Supervision trees that explicitly start TzWorld.Backend.Memory, TzWorld.Backend.Ets, or TzWorld.Backend.Dets should switch to TzWorld.Backend.SpatialIndex (or another remaining backend).

Tz_World v1.4.2

This is the changelog for Tz_World v1.4.2 released on January 19th, 2026. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Fix absoluate path error in the zip file generation. For security reasons, the contents of a zip file should not have an absolute path. THis is now corrected.

  • Fix compiler warning on Elixir 1.20.

Tz_World v1.4.1

This is the changelog for Tz_World v1.4.1 released on October 21st, 2024. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Don't include :wx and :observer in :extra_applications since this propogates and :wx may not be compiled in the target runtime. Thanks to @mayel for the report. Fixes #43.

Tz_World v1.4.0

This is the changelog for Tz_World v1.4.0 released on September 29th, 2024. For older changelogs please consult the release tag on GitHub

Enhancements

  • Adds support for easier configuration of default custom backends. In previous releases, the default backend was resolved by only considering the built-in backends. From this release, a custom backend can be configured in config.exs or runtime.exs. If so configured, that backend will be the default for calls to TzWorld.timezone_at/1. For example:
config :tz_world,
  default_backend: MyTzWorldBackend
  • Adds a --trace flag to mix tz_world.update. This flag will trigger additional logging during the update process including memory utilization on the BEAM.

  • Adds some memory use optimizations during the download process. Relates to #38 but likely does not fully solve this issue.

  • Add support for geo 4.0.

Tz_World v1.3.3

This is the changelog for Tz_World v1.3.3 released on May 27th, 2024. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Fixes compiler warnings for Elixir 1.17.

Tz_World v1.3.2

This is the changelog for Tz_World v1.3.2 released on December 2nd 2023. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Fixes compiler warnings for Elixir 1.16.

Tz_World v1.3.1

This is the changelog for Tz_World v1.3.1 released on August 17th, 2023. For older changelogs please consult the release tag on GitHub

Bug Fixes

Thanks to @mjquinlan2000 for the report of issues on Elixir 1.15 and OTP 26.

Tz_World v1.3.0

This is the changelog for Tz_World v1.3.0 released on April 5th, 2023. For older changelogs please consult the release tag on GitHub

Enhancements

  • Add httpc set_options/1 support. Thanks to @gabrielgiordan for the PR (and the PR for fixing CI).

Tz_World v1.2.0

This is the changelog for Tz_World v1.2.0 released on October 12th, 2022. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Fix TzWorld.Backend.Dets to not raise an exception if there is no timezone data available.

Enhancements

  • Adds options to mix tz_world.update mix task:
    • --include_oceans will download a 10% larger geojson data set that covers the worlds oceans
    • --force will force a data update, even if the data is the latest release. This can be used to switch between data that includes oceans and that which does not.
    • Thanks to @lguminski for the feedback and suggestion.

Tz_World v1.1.0

This is the changelog for Tz_World v1.1.0 released on August 26th, 2022. For older changelogs please consult the release tag on GitHub

Enhancements

Tz_World v1.0.0

This is the changelog for Tz_World v1.0.0 released on October 19th, 2021. For older changelogs please consult the release tag on GitHub

Enhancements

  • Update to version 1.0.0 since the API has been stable for a year.

Tz_World v0.7.1

This is the changelog for Tz_World v0.7.1 released on November 6th, 2020. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Don't use tests for the external data version since that changes outside of the code lifesycle

Tz_World v0.7.0

This is the changelog for Tz_World v0.7.0 released on October 10th, 2020. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Add :inets and :public_key to :extra_applications in mix.exs to make Elixir 1.11 happy.

Tz_World v0.6.0

This is the changelog for Tz_World v0.6.0 released on June 10th, 2020. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Honour the configuration for :data_dir. Thanks to @superhawk610. Fixes #12

  • Be more resilient if the :dets file is not in place

Tz_World v0.5.0

This is the changelog for Tz_World v0.5.0 released on May 23rd, 2020. For older changelogs please consult the release tag on GitHub

Bug Fixes

  • Move compile time configuration of the data directory to runtime and remove hard-coded default path

  • Start :inets and :ssl applications in the downloader mix task

  • Add certificate verification when downloading updates to the geo data

Enhancements

  • Document the :data_dir and :cacertfile configuration options it the README.md file

  • The backends :dets and :dets_with_index_cache now open the :dets file as access: :read which prevents errors if the file is abnormally closed.

Tz_World v0.4.0

This is the changelog for Tz_World v0.4.0 released on May 12th, 2020. For older changelogs please consult the release tag on GitHub

  • Adds configurable backends. Each backend is a GenServer that must be added to an applications supervision tree or started manually.

Breaking change

  • When specifying a lng, lat to TzWorld.timezone_at/2 the coordinates must be wrapped in a tuple. For example TzWorld.timezone_at({3.2, 45.32}) making it consistent with the Geo.Point and Geo.PointZ strategies.

Configurable backends

  • TzWorld.Backend.Memory which retains all data in memory for fast (but not fastest) performance at the expense of using approximately 1Gb of memory
  • TzWorld.Backend.Dets which uses Erlang's :dets data store. This uses negligible memory at the expense of slow access times (approximaltey 500ms in testing)
  • TzWorld.Backend.DetsWithIndexCache which balances memory usage and performance. This backend is recommended in most situations since its performance is similar to TzWorld.Backend.Memory (about 5% slower in testing) and uses about 25Mb of memory
  • TzWorld.Backend.Ets which uses :ets for storage. With the default settings of :compressed for the :ets table its memory consumption is about 512Mb but with access that is over 20 times slower than TzWorld.Backend.DetsWithIndexCache
  • TzWorld.Backend.EtsWithIndexCache which uses :ets for storage with an additional in-memory cache of the bounding boxes. This still uses about 512Mb but is faster than any of the other backends by about 40%

Enhancements

  • Add TzWorld.all_timezones_at/2 to return all timezones for a given location. In rare cases, usually disputed territory, multiple timezones may be declared for overlapping regions. TzWorld.all_timezones_at/2 returns a (potentially empty) list of all time zones known for a given point. Futher testing of this function is required and will be completed before version 1.0.

Tz_World v0.3.0

This is the changelog for Tz_World v0.3.0 released on December 4th, 2019. For older changelogs please consult the release tag on GitHub

Breaking Changes

  • Changes the error return from {:error, :timezone_not_found} to {:error, :time_zone_not_found} since both Elixir and Tzdata use time_zone.

Enhancements

Tz_World v0.2.0

This is the changelog for Tz_World v0.2.0 released on November 28th, 2019. For older changelogs please consult the release tag on GitHub

Breaking Changes

  • Requires OTP 21 and Elixir 1.6 or later due to the use of GenServer's handle_continue/2

  • timezone_at/1 returns tagged tuples {:ok, result} or {:error, reason}. There can be at least two reasons for an error: no data file is available or no timezone is found. These return {:error, :enoent} and {:error, :timezone_not_found} respectively

  • The timezone geojson data is no longer included in the package. Run mix tz_world.update to install or update it.

  • No longer uses Ecto or PostGIS for calculations.

Enhancements

  • Updated to latest shape data. Takes the geo JSON shape data directly from timezone-boundary-builder releases

  • Conforms TzWorker to the modern child_spec/1 including using handle_continue/2 to load the data file if it exists.

  • Updated dependencies including geo to allow 1.x, 2.x or 3.x

  • Added Jason as an optional dependency to facilitate decoding the GeoJSON from timezone_boundary_builder

  • The timezone geojson data is no longer included in the package. Its size isn't supported on hex and it bloats the repo too. A mix task tz_world.update downloads and processes the data. The function TzWorld.Downloader.update_release/0 can be called at any time to look for a new release, download it and load it into the running server with no downtime.

  • timezone_at/1 supports simple lng, lat arguments as well as %Geo.Point{} structs

  • Added CHANGELOG.md

  • Added SRID to the GeoJSON

  • Updated package and ran dialyzer

  • Added a config option :data_dir specifies the location of the compressed etf. Default is ./priv

  • Updated README, package and docs