Skip to main content

Timezone Trout

This library tries to solve the common problem of figuring out what time zone a specific address or a phone number is in. It does so by using several mappings that are generated with the help of pytz, Geonames.org, and TimezoneFinder

Current version is fairly accurate for the United States, Canada, Australia, and countries which fit within a single time zone.

Vocabulary used in this library:

  • PST - time zone name
  • America/Los_Angeles - time zone identifier
  • UTC-07:00 or -420 - UTC offset (the latter given in minutes)
  • DST - Daylight Saving Time

The US Zipcode data is provided by www.geonames.org under the Creative Commons Attribution 3.0 License.

Starting in v1.0.0, this library requires Python version 3.6 or above.

Examples

>>> tztrout.tz_ids_for_phone('+16503334444')
[u'America/Los_Angeles']
>>> tztrout.tz_ids_for_phone('+49 (0)711 400 40990')
[u'Europe/Berlin', u'Europe/Busingen']
>>> tztrout.tz_ids_for_address('US', state='CA')
[u'America/Los_Angeles']
>>> tztrout.tz_ids_for_address('PL')
[u'Europe/Warsaw']
>>> tztrout.tz_ids_for_address('CN')
[
    u'Asia/Shanghai',
    u'Asia/Harbin',
    u'Asia/Chongqing',
    u'Asia/Urumqi',
    u'Asia/Kashgar'
]
>>> import tztrout
>>> tztrout.tz_ids_for_tz_name('PDT')  # ran during DST
[
    u'America/Dawson',
    u'America/Los_Angeles',
    u'America/Santa_Isabel',
    u'America/Tijuana',
    u'America/Vancouver',
    u'America/Whitehorse',
    u'Canada/Pacific',
    u'US/Pacific'
]
>>> tztrout.tz_ids_for_tz_name('PDT')  # ran outside of the DST period
[]
>>> tztrout.local_time_for_phone('+1 (650) 333-4444')
datetime.datetime(2013, 9, 16, 17, 45, 43, 0000000, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)

>>> tztrout.local_time_for_phone('+48 601 941 311)
datetime.datetime(2013, 9, 17, 2, 45, 43, 0000000, tzinfo=<DstTzInfo 'Europe/Warsaw' CEST+2:00:00 DST>)
>>> tztrout.local_time_for_address('US', state='CA')
datetime.datetime(2013, 9, 16, 17, 45, 43, 0000000, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
>>> tztrout.local_time_for_address('PL')
datetime.datetime(2013, 9, 17, 2, 45, 43, 0000000, tzinfo=<DstTzInfo 'Europe/Warsaw' CEST+2:00:00 DST>)
>>> tztrout.non_dst_offset_for_tz_id('America/New_York')
-300
>>> tztrout.non_dst_offset_for_tz_id('Europe/Berlin')
60
>>> tztrout.non_dst_offset_for_tz_id('UTC')
0
>>> tztrout.non_dst_offset_for_tz_id('Invalid/Zone')
None
>>> tztrout.tz_ids_for_offset(-7 * 60)  # during DST
[
    u'America/Creston',
    u'America/Dawson',
    u'America/Dawson_Creek',
    u'America/Hermosillo',
    u'America/Los_Angeles',
    u'America/Phoenix',
    u'America/Santa_Isabel',
    u'America/Tijuana',
    u'America/Vancouver',
    u'America/Whitehorse',
    u'Canada/Pacific',
    u'US/Arizona',
    u'US/Pacific'
]
>>> tztrout.tz_ids_for_offset(+2 * 60)  # during DST
[
    "Africa/Blantyre",
    "Africa/Bujumbura",
    "Africa/Cairo",
    "Africa/Ceuta",
    "Africa/Gaborone",
    "Africa/Harare",
    "Africa/Johannesburg",
    "Africa/Kigali",
    "Africa/Lubumbashi",
    "Africa/Lusaka",
    "Africa/Maputo",
    "Africa/Maseru",
    "Africa/Mbabane",
    "Africa/Tripoli",
    "Africa/Windhoek",
    "Arctic/Longyearbyen",
    "Europe/Amsterdam",
    "Europe/Andorra",
    "Europe/Belgrade",
    "Europe/Berlin",
    "Europe/Bratislava",
    "Europe/Brussels",
    "Europe/Budapest",
    "Europe/Busingen",
    "Europe/Copenhagen",
    "Europe/Gibraltar",
    "Europe/Ljubljana",
    "Europe/Luxembourg",
    "Europe/Madrid",
    "Europe/Malta",
    "Europe/Monaco",
    "Europe/Oslo",
    "Europe/Paris",
    "Europe/Podgorica",
    "Europe/Prague",
    "Europe/Rome",
    "Europe/San_Marino",
    "Europe/Sarajevo",
    "Europe/Skopje",
    "Europe/Stockholm",
    "Europe/Tirane",
    "Europe/Vaduz",
    "Europe/Vatican",
    "Europe/Vienna",
    "Europe/Warsaw",
    "Europe/Zagreb",
    "Europe/Zurich"
]

Testing

Just run pytest

Regenerating the data

Time zones, addresses, and phone numbers are in a constant flux and hence the data used by this library needs to be regenerated periodically. To do so, upgrade the pytz and timezonefinder dependencies, and run python regenerate_data.py. If this doesn't fix the problem, consider opening an issue or adding an exception in data_exceptions.py.

Known Issues

  • Australian Central Western Standard Time (CWST) is treated as Australian Central Standard Time (ACST). See Australian anomalies for more details.
  • Lord Howe Standard Time (LHST) is treated as Australian Eastern Standard Time (AEST). In reality, they're 30 minutes apart.
  • The whole state of British Columbia (Canada) is recognized as Pacific Time, although a small portion of its south-east territory should be recognized as Mountain Time.
  • The whole state of Ontario (Canada) is recognized as Eastern Time, although a small portion of its west territory should be recognized as Central Time.
  • All +1 867 phone numbers are recognized as Mountain Time, although this prefix is shared by three Canadian territories in the Arctic far north, spanning across Pacific, Mountain, and Central Time.

Releasing a New Version

  1. Make sure the code has been thoroughly reviewed and tested in a realistic production environment.
  2. Update setup.py and CHANGELOG.md. Make sure you include any breaking changes.
  3. Run the release github action with the correct version number.

Alternatively, once the changes to setup.py and CHANGELOG.md are complete you can manually:

  1. Run python setup.py sdist and twine upload dist/<PACKAGE_TO_UPLOAD>.
  2. Push a new tag pointing to the released commit, format: v0.13 for example.

Release files for tz-trout 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tz-trout 1.2.0
File Size Uploaded
tz_trout-1.2.0.tar.gz 760.7 kB Details

Release files / tz_trout-1.2.0.tar.gz

Download URL tz_trout-1.2.0.tar.gz
Size 760.7 kB
Tags Source
SHA-256 checksum
How to use checksums
58e734fd4c36ef14989e7b31ca35e13a1281b5090a571ffb8f4f1b3719984ec3
BLAKE2b-256 checksum
How to use checksums
5bfd199b3d92e4bc3f328fe3f3abceed191651d7e676bb51d99fa3554ccb00b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.2.0 This release

1 release file

1.1.2

1 release file

1.1.1

1 release file

1.1.0

1 release file

1.0.5

1 release file

1.0.4

1 release file

1.0.3

1 release file

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.6

1 release file

0.1.5

1 release file

0.1.4

2 release files

0.1.3

1 release file

0.1.2

1 release file

0.1.1

1 release file

0.1

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page