Changelog for Tz_World
Tz_World v2.3.0
This is the changelog for Tz_World v2.3.0 released on April 29th, 2026.
Breaking Changes
TzWorld.reload_timezone_data/0now returns{:ok, [{backend, result}, ...]}or{:error, [{backend, reason}, ...]}instead of a bare list. Callers that pattern-matched the previous return shape need updating.Adds
:telemetry ~> 1.0as a runtime dependency.
Enhancements
mix tz_world.updatefails fast with a clean error and exit 1 when the configured:data_dirdoes not exist. Pass--forceto create it on the fly.TzWorld.reload_timezone_data/0now actually works in every backend configuration: backends that aren't running are skipped instead of crashing the caller with:noproc. Reload also runs the backends in dependency-correct order (DETS before ETS).On-disk
.tzw1and.detsfiles are now written atomically (write-temp + rename in the same directory). Concurrent readers in another BEAM never observe a half-written file, even whilemix tz_world.updateis running.Reload emits
[:tz_world, :reload, :start | :stop | :exception]and[:tz_world, :reload, :backend, :start | :stop | :exception]telemetry events with:durationmeasurements and:backend/:resultmetadata.mix tz_world.updateno longer starts theSpatialIndexbackend internally; the version check reads the on-disk header directly. This removes the misleading "started without timezone data — runmix tz_world.update" warning that the update task itself used to log.
Bug Fixes
Fixed
TzWorld.Backend.EtsWithIndexCacheretaining stale entries across reloads. Shapes removed upstream (or whose bounding-box keys changed) now actually disappear from the cache.Fixed
TzWorld.Backend.SpatialIndexreload briefly exposing an inconsistent index. The three persistent-term entries are packed into a single key so reload is an atomic swap.Fixed
TzWorld.Backend.DetsWithIndexCachereload failing with:incompatible_argumentswhen another opener held a reference to the live DETS file.
Tz_World v2.2.0
This is the changelog for Tz_World v2.2.0released on April 28th, 2026. For older changelogs please consult the release tag on GitHub.
Bug Fixes
mix tz_world.updatenow produces a single clear error instead of a longFile.Errorstack trace when the configured:data_dirdoes not exist. To create the directory automatically, pass--force. This affects users who set:data_dirto a path outside the package'spriv/(e.g. an application-level data directory shared across releases).
Migration
- If you set
config :tz_world, data_dir: "..."to a directory that is not part of the build artifacts, runmix tz_world.update --forceonce on first install (or any install where the directory may not yet exist). The default:data_dir(the package'spriv/) always exists and is unaffected.
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.updateonce 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.SpatialIndexis now the default backend, and is the first entry in the default backend precedence list. Existing applications that do not pin:default_backendwill 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 category Speedup vs. the next-fastest existing backend ocean(no-match)18.2× sparse_or_large1.64× dense(cities)1.43× random uniform 1.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 byTzWorld.Backend.SpatialIndexon 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 newSpatialIndexbackend.TzWorld.Backend.EtsWithIndexCacheremains for users who want ETS-backed shape storage.Removes
TzWorld.Backend.Dets. Same reasoning asBackend.Ets.TzWorld.Backend.DetsWithIndexCacheremains for users who want disk-backed shape storage.
Migration
Applications that did not configure
:default_backendneed no changes —TzWorld.Backend.SpatialIndexis selected automatically.Applications that had
config :tz_world, default_backend: TzWorld.Backend.Memory(orEts,Dets) should switch toTzWorld.Backend.SpatialIndex, or to one of the remaining cache-backed alternatives (EtsWithIndexCache,DetsWithIndexCache).Supervision trees that explicitly start
TzWorld.Backend.Memory,TzWorld.Backend.Ets, orTzWorld.Backend.Detsshould switch toTzWorld.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
:wxand:observerin:extra_applicationssince this propogates and:wxmay 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.exsorruntime.exs. If so configured, that backend will be the default for calls toTzWorld.timezone_at/1. For example:
config :tz_world,
default_backend: MyTzWorldBackendAdds a
--traceflag tomix 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.
Always send a
User-Agentheader to the Github API to avoid 403 responses.Add
:sslto:extra_applicationsto support Elixir 1.15 and OTP 26.Update
TzWorld.Downloader.get_url/1to follow the erlef security guidelines.
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.Detsto not raise an exception if there is no timezone data available.
Enhancements
- Adds options to
mix tz_world.updatemix task:--include_oceanswill download a 10% larger geojson data set that covers the worlds oceans--forcewill 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
- Replace
Application.get_env/2withApplication.compile_env/2to remove warnings on Elixir 1.14. Now requires Elixir 1.10 as a minimum version.
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
:inetsand:public_keyto:extra_applicationsinmix.exsto 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 #12Be more resilient if the
:detsfile 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
:inetsand:sslapplications in the downloader mix taskAdd certificate verification when downloading updates to the geo data
Enhancements
Document the
:data_dirand:cacertfileconfiguration options it the README.md fileThe backends
:detsand:dets_with_index_cachenow open the:detsfile asaccess: :readwhich 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,lattoTzWorld.timezone_at/2the coordinates must be wrapped in a tuple. For exampleTzWorld.timezone_at({3.2, 45.32})making it consistent with theGeo.PointandGeo.PointZstrategies.
Configurable backends
TzWorld.Backend.Memorywhich retains all data in memory for fast (but not fastest) performance at the expense of using approximately 1Gb of memoryTzWorld.Backend.Detswhich uses Erlang's:detsdata store. This uses negligible memory at the expense of slow access times (approximaltey 500ms in testing)TzWorld.Backend.DetsWithIndexCachewhich balances memory usage and performance. This backend is recommended in most situations since its performance is similar toTzWorld.Backend.Memory(about 5% slower in testing) and uses about 25Mb of memoryTzWorld.Backend.Etswhich uses:etsfor storage. With the default settings of:compressedfor the:etstable its memory consumption is about 512Mb but with access that is over 20 times slower thanTzWorld.Backend.DetsWithIndexCacheTzWorld.Backend.EtsWithIndexCachewhich uses:etsfor 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/2to 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/2returns 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 usetime_zone.
Enhancements
- Allows both
%Geo.Point{}and%Geo.PointZ{}as parameters toTzWorld.timezone_at/1
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/2timezone_at/1returns 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}respectivelyThe timezone geojson data is no longer included in the package. Run
mix tz_world.updateto 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/1including usinghandle_continue/2to load the data file if it exists.Updated dependencies including geo to allow
1.x,2.xor3.xAdded
Jasonas an optional dependency to facilitate decoding the GeoJSON fromtimezone_boundary_builderThe 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.updatedownloads and processes the data. The functionTzWorld.Downloader.update_release/0can 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/1supports simplelng,latarguments as well as%Geo.Point{}structsAdded
CHANGELOG.mdAdded SRID to the GeoJSON
Updated package and ran dialyzer
Added a config option :data_dir specifies the location of the compressed etf. Default is
./privUpdated README, package and docs