# Timezone Boundary Builder and the art of shipping timezone polygons

> evansiroky/timezone-boundary-builder turns OpenStreetMap boundary relations into shapefile and GeoJSON products whose polygons each carry one IANA timezone identifier. The interesting part is not the extraction but the three competing notions of "same timezone" it publishes side by side, and the release cadence it inherits from the timezone database.

**evansiroky/timezone-boundary-builder** — A tool to extract data from Open Street Map (OSM) to build the boundaries of the world's timezones.

- Repository: https://github.com/evansiroky/timezone-boundary-builder
- Stars: 1,135 · Forks: 95
- Language: JavaScript
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/evansiroky-timezone-boundary-builder

## From OpenStreetMap relations to one tzid per polygon

Most timezone lookup problems are really geometry problems. Given a longitude and a latitude, which offset applies, and where does that answer change? The timezone database answers the first question with rules, and leaves the second one to whoever has to draw it on a map. Timezone Boundary Builder takes that second job seriously: it produces a shapefile of the world's timezone boundaries using OpenStreetMap data, and each resulting shape is tied to exactly one timezone identifier.

The target audience is therefore anyone who has to answer "which zone is this point in" offline or inside a database. That means map renderers, geocoding services, scheduling products and analytics pipelines that would otherwise call out to a hosted timezone API on every request.

The data is published as release artifacts rather than as a running service, and the project states that data has been made available since October 2016. The extraction code itself is JavaScript, with `index.js` as the entry point and a `util/` directory beside it. Because the artifacts are files, adoption means downloading a release and loading it, not wiring a dependency into a request path.

## Every shape carries one timezone identifier and nothing else

The schema is deliberately minimal. Each boundary is associated with a single timezone identifier as defined by the timezone database, and the project gives two examples: `America/Los_Angeles` and `Asia/Shanghai`. Each shape or GeoJSON object has a single attribute, or property, called `tzid`.

That single-field design is the whole contract. A consumer reads the polygon, reads `tzid`, and looks up that string. There is no nested attribute carrying historical offsets, no per-polygon DST rules, no country code, and no population figure. Everything else has to be derived by the user.

The release files also identify the dataset variation through the file name prefix, with values such as `timezones` and `timezones-with-oceans` for the base product. The naming convention predates the current variation scheme and is kept, in the project's own description, for backwards compatibility with the methodology it used when it started publishing. Practical consequence for an engineer: the data product is identified by filename, and the semantics of that filename are the only thing distinguishing one download from another.

## Three timekeeping stories: comprehensive, 1970, and now

Since release 2023d the project publishes three variations, and this is the design decision worth understanding before picking a file.

The comprehensive variation keeps every timezone identifier the timezone database produced under the older practice of at least one zone per country, minus zones it judged unnecessary for lack of supporting evidence. It should mostly align with the `zone.tab` list in the timezone database project, and it is the base set from which the other two are derived. It also assumes that pre-1970 time change data, marked as deprecated in the database, is actually correct.

The same since 1970 variation merges zones that have agreed on their timekeeping method since 1970, and it should mostly align with `zone1970.tab`. The same since now variation merges zones that agree as of the approximate release date, aligning with `zonenow.tab`. Both merges are performed with the `@tubular/time` library, and in the merged output the zone with the largest city population supplies the `tzid`.

## The oceans toggle doubles the file count

Orthogonal to the three timekeeping methods is a second axis: whether ocean zones are included. The project produces one variant with no ocean zones and another that includes them, and the file prefixes reflect this, for instance `timezones-with-oceans` and `timezones-with-oceans-1970`.

This matters more than it first appears. A maritime service that must resolve a GPS fix in open water has no land polygon to look up, so the inland-only product is useless to it. An inland product, on the other hand, has a much smaller storage footprint, and the project makes the smaller footprint an explicit goal of the merged variations, since merging removes boundaries and simplifies polygons.

So the catalogue is not one file. It is a matrix of timekeeping method against ocean handling, in two output formats, GeoJSON or Shapefile. Anyone automating a download has to encode that matrix, and anyone picking a single file has to justify which cell of it their use case actually needs.

## Release numbering is slaved to the timezone database

The versioning scheme is unusual and worth internalising before you build an updater around it. Release names are `2026e`, `2026d`, `2026c` and so on, matching the timezone database's own release names. The project states plainly that it will only create a new release after the timezone database creates one.

Even that guarantee has a caveat the project spells out. A new release is always made when a timezone is created or deprecated in a database release. For database releases without that trigger, this project may still publish, if boundary definitions changed, a bug fix was needed, or a new feature was introduced, but that may not always happen. And some database releases are skipped entirely when a release from this project was still being worked on.

In practice that means database releases and project releases do not line up one to one. Recent project releases were 2026e on 2026-10-11, 2026d on 2026-09-16 and 2026c on 2026-07-11. The last push to the repository was on 2026-10-11, and the repository is not archived, so the code is being worked on, but the public artifact timeline is driven by an upstream project you do not control.

## Getting the data: the releases page and a local build

The published path is the releases page, and that is where the project points users who want the data. It does not offer a package install for the data itself; there is no command in the documentation for pulling a shapefile.

The code path is a Node.js program. The package manifest names `index.js` as the entry point and requires a modern runtime:

```json
{
  "name": "timezone-boundary-builder",
  "version": "1.0.0",
  "main": "index.js",
  "engines": {
    "node": ">=12"
  }
}
```

The manifest also lists the extraction stack, including `overpass-ts` for querying OpenStreetMap, `osmtogeojson` for converting OSM output to GeoJSON, `shpjs` and `jsts` among others and `@tubular/time` for the zone merging described earlier. A lint pass over the JSON files is wired into the test script:

```json
  "scripts": {
    "test": "standard && node lint-json.js"
  },
```

A contributor working on the source rather than the data would clone the repository, install those dependencies, and run the entry point. The repository also carries `osmBoundarySources.json`, `timezones.json`, `expectedZoneOverlaps.json`, a `TZ_RELEASE` marker and a `CHANGELOG.md`, which together suggest the build reads local configuration and checks its own output for zone overlaps.

## Where the merged variants give up on history

The limitations here are explicit and honest in the project's own wording, which is unusual enough to quote closely. The same since now variation "is only suitable for use cases that need to know the current or future time at a location", and it will provide potentially incorrect data for observed timekeeping methods in the past at certain locations. The 1970 variation carries the mirror risk: it may provide potentially incorrect data for observed timekeeping methods prior to 1970.

The second limitation is the merging rule. When two zones are combined, the surviving `tzid` is the one belonging to the zone with the largest city population. That is a sensible heuristic for current-time lookups and a poor one for historical research, where the relevant city may not have been the largest.

A third constraint is the premise of the comprehensive set, that deprecated pre-1970 database data is treated as correct. Where that assumption does not hold, the supposedly broadest product is the one carrying the most speculation. The with-oceans product has its own consequence, since including ocean zones enlarges every file and forces a choice about disk and load time.

## Two licences, a checksum file and a Travis configuration

Licensing is split across two files at the repository root, `CODE_LICENSE` and `DATA_LICENSE`, and the package manifest declares the project itself as MIT. The practical reading, without offering any legal opinion, is that the code and the generated boundary data are covered separately, so a redistribution of the shapefiles needs its own look at `DATA_LICENSE` rather than an assumption that MIT covers the output.

On the engineering side, the presence of a `.travis.yml` alongside `lint-json.js` and `expectedZoneOverlaps.json` points to continuous integration and a checked expectation file for zone overlaps. The overlaps file is a quality gate rather than a documentation artifact: a build that starts producing overlapping zones for the same identifier can be caught. The `TZ_RELEASE` file is the sort of marker that lets the build line up with a specific timezone database release, which is exactly the coordination problem the release numbering scheme creates.

## Conclusion

Teams that need a point-in-time zone lookup against coordinates should take the 1970 variant and check its tzid attribution against a population source first. Projects that need historical accuracy before 1970, or that expect a fresh release every month, should plan around the fact that this project only publishes after the timezone database does and explicitly merges zones by city population.

## FAQ

### What is timezone-boundary-builder and what does it produce?

It is a tool that extracts data from OpenStreetMap to build the boundaries of the world's timezones. Each shape or GeoJSON object carries a single property called `tzid`, holding one identifier from the timezone database.

### How do I install or get the timezone boundary data from timezone-boundary-builder?

The data is published as download artifacts on the project's GitHub releases page, and the project states that data has been made available there since October 2016. The source itself is a Node.js program with `index.js` as the entry point and a manifest requiring Node 12 or newer.

### Which timezone-boundary-builder file should I use for a simple coordinate lookup?

For current or future time at a location, the same since now variation is the documented fit, published with the `timezones-now` or `timezones-with-oceans-now` prefix. The same since 1970 variation is the one that matches what the timezone database officially supports, and the comprehensive variation keeps the fullest zone list.

### How often does timezone-boundary-builder publish new releases?

Release names follow the timezone database, and the project only creates a new release after the timezone database creates one. Some database releases are skipped when a project release was still being worked on, so the two timelines do not match one to one.

### Is timezone-boundary-builder still being worked on?

The repository is not archived and the last push was on 2026-10-11, with releases 2026e on 2026-10-11, 2026d on 2026-09-16 and 2026c on 2026-07-11. Recent activity in the code does not change the release rule, which remains tied to the timezone database.

## Sources

- [evansiroky/timezone-boundary-builder on GitHub](https://github.com/evansiroky/timezone-boundary-builder)
- [Issues](https://github.com/evansiroky/timezone-boundary-builder/issues)
- [License: MIT](https://github.com/evansiroky/timezone-boundary-builder/blob/master/LICENSE)
- [README](https://github.com/evansiroky/timezone-boundary-builder/blob/master/README.md)
- [Releases](https://github.com/evansiroky/timezone-boundary-builder/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/evansiroky-timezone-boundary-builder
