diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..06d4463 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: monthly + groups: + actions: + patterns: + - "*" \ No newline at end of file diff --git a/.github/workflows/auto-tag.yml b/.github/workflows/auto-tag.yml new file mode 100644 index 0000000..475583e --- /dev/null +++ b/.github/workflows/auto-tag.yml @@ -0,0 +1,40 @@ +name: Auto Tag on Version Bump + +on: + push: + branches: + - master + paths: + - VERSION + +jobs: + tag-repo: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Get current version + id: version + run: | + VERSION=$(cat VERSION) + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Check if tag already exists + id: checktag + run: | + if git rev-parse "v${{ steps.version.outputs.version }}" >/dev/null 2>&1; then + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + + - name: Push tag + if: steps.checktag.outputs.skip == 'false' + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git tag "${{ steps.version.outputs.version }}" + git push origin "${{ steps.version.outputs.version }}" diff --git a/.github/workflows/check-for-updates.yml b/.github/workflows/check-for-updates.yml index e5c2774..119d1d0 100644 --- a/.github/workflows/check-for-updates.yml +++ b/.github/workflows/check-for-updates.yml @@ -36,12 +36,12 @@ jobs: if: needs.check-pr-exists.outputs.pr_exists == 'false' # Run only if no PR exists steps: - name: Check out repository (shallow) - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: fetch-depth: 1 # Shallow clone to save time - name: Set up Python 3.12 - uses: actions/setup-python@v4 + uses: actions/setup-python@v6 with: python-version: '3.12' @@ -87,10 +87,10 @@ jobs: # Extract TZDATA_NEWS from file content TZDATA_NEWS=$(cat "$news_files") - echo "TZDATA_VERSION='$TZDATA_VERSION'" >> $GITHUB_ENV + echo "TZDATA_VERSION=$TZDATA_VERSION" >> $GITHUB_ENV { - echo 'TZDATA_NEWS<> "$GITHUB_ENV" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e8313df..3181eae 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,10 +18,15 @@ on: jobs: deploy: runs-on: ubuntu-latest + environment: + name: release + url: https://pypi.org/p/tzdata + permissions: + id-token: write steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v6 with: python-version: '3.x' - name: Install dependencies @@ -30,26 +35,21 @@ jobs: pip install -U tox - name: Create tox environments run: | - tox -p -e py,build,release --notest + tox -p -e py,build --notest - name: Run tests run: | tox -e py - name: Build package run: | tox -e build + - name: Publish package (TestPyPI) + if: github.event_name == 'push' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + verbose: true - name: Publish package - env: - TWINE_USERNAME: "__token__" - run: | - if [[ "$GITHUB_EVENT_NAME" == "push" ]]; then - export TWINE_REPOSITORY_URL="https://test.pypi.org/legacy/" - export TWINE_PASSWORD="${{ secrets.TEST_PYPI_UPLOAD_TOKEN }}" - elif [[ "$GITHUB_EVENT_NAME" == "release" ]]; then - export TWINE_REPOSITORY="pypi" - export TWINE_PASSWORD="${{ secrets.PYPI_UPLOAD_TOKEN }}" - else - echo "Unknown event name: ${GITHUB_EVENT_NAME}" - exit 1 - fi - - tox -e release + if: github.event_name == 'release' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + verbose: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 59921d8..af8e595 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,11 @@ name: tzdata contents -on: [push, pull_request, workflow_dispatch] +on: + push: + branches: + - master + pull_request: + workflow_dispatch: jobs: tests: @@ -9,31 +14,23 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["2.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["2.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"] os: ["ubuntu-latest", "windows-latest", "macos-latest"] exclude: - python-version: "2.7" - os: "windows-latest" - - python-version: "2.7" - os: "macos-latest" - - python-version: "2.7" - os: "ubuntu-latest" include: - python-version: "2.7" - os: "ubuntu-20.04" + os: "ubuntu-latest" + use-container: true env: TOXENV: py - + container: + image: ${{ matrix.use-container && format('python:{0}', matrix.python-version) || '' }} steps: - - uses: actions/checkout@v3 - - if: ${{ matrix.python-version == '2.7' }} - run: | - sudo apt-get install python-is-python2 - curl -sSL https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py - python get-pip.py - - if: ${{ matrix.python-version != '2.7' }} - name: ${{ matrix.python-version }} - ${{ matrix.os }} - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - if: ${{ !matrix.use-container }} + name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }} (non-containers) + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} allow-prereleases: true @@ -54,9 +51,9 @@ jobs: TOXENV: ${{ matrix.toxenv }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - name: ${{ matrix.toxenv }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v6 with: python-version: "3.x" - name: Install tox diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f30f6b7..1782fa1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,24 +1,24 @@ repos: - repo: https://github.com/psf/black - rev: 24.10.0 + rev: 25.9.0 hooks: - id: black language_version: "python3.12" - - repo: https://github.com/pre-commit/mirrors-isort - rev: v5.10.1 + - repo: https://github.com/pycqa/isort + rev: 7.0.0 hooks: - id: isort - additional_dependencies: [toml] + additional_dependencies: [ toml ] language_version: "python3.12" - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: debug-statements - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.7.0 + rev: v3.1.0 hooks: - id: setup-cfg-fmt diff --git a/NEWS.md b/NEWS.md index 40d8763..89cab0e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,51 @@ +# Version 2026.1 +Upstream version 2026a released 2026-03-02T06:59:49+00:00 + +## Briefly: + +Moldova has used EU transition times since 2022. The "right" TZif files are no +longer installed by default. -DTZ_RUNTIME_LEAPS=0 disables runtime support for +leap seconds. TZif files are no longer limited to 50 bytes of abbreviations. zic +is no longer limited to 50 leap seconds. Several integer overflow bugs have been +fixed. + +## Changes to past and future timestamps + +Since 2022 Moldova has observed EU transition times, that is, it has sprung +forward at 03:00, not 02:00, and has fallen back at 04:00, not 03:00. (Thanks +to Heitor David Pinto.) + +## Changes to data + +Remove Europe/Chisinau from zonenow.tab, as it now agrees with Europe/Athens for +future timestamps. + +--- + +# Version 2025.3 +Upstream version 2025c released 2025-12-10T22:42:37+00:00 + +## Briefly: + +Several code changes for compatibility with FreeBSD. + +## Changes to past timestamps + +Baja California agreed with California’s DST rules in 1953 and in 1961 through +1975, instead of observing standard time all year. (Thanks to Alois Treindl.) + +## Changes to commentary + +The leapseconds file contains commentary about the IERS and NIST last-modified +and expiration timestamps for leap second data. (Thanks to Judah Levine.) + +Commentary now also uses characters from the set –‘’“”•≤ as this can be useful +and should work with current applications. This also affects data in +iso3166.tab and zone1970.tab, which now contain strings like “Côte d’Ivoire” +instead of “Côte d'Ivoire”. + +--- + # Version 2025.2 Upstream version 2025b released 2025-03-22T20:40:46+00:00 diff --git a/README.rst b/README.rst index 948d7fa..8858ff7 100644 --- a/README.rst +++ b/README.rst @@ -9,4 +9,4 @@ location), as a part of `PEP 615 `_ This repository generates a ``pip``-installable package, published on PyPI as `tzdata `_. -For more information, see `the documentation `_. +For more information, see `the documentation `_. diff --git a/VERSION b/VERSION index 89c24c5..8468728 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.2 \ No newline at end of file +2026.1 \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 9908567..c064355 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,8 +4,6 @@ # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html -import sphinx_bootstrap_theme - import tzdata # -- Project information ----------------------------------------------------- @@ -37,11 +35,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = "bootstrap" -html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() -html_theme_options = { - "bootswatch_theme": "cosmo", -} +html_theme = "furo" # For cross-links to other documentation intersphinx_mapping = { diff --git a/docs/index.rst b/docs/index.rst index 3d64a1e..a32815f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,10 +18,8 @@ its backport `importlib_resources`_). Although ``importlib.resources`` or equivalent is recommended, it is also possible to access the data via :func:`pkgutil.get_data` as well. -.. TODO: Change ``zoneinfo`` to :mod:`zoneinfo` when 3.9 is released - -It is primarily intended to be used by standard library's ``zoneinfo`` -module (new in Python 3.9), but it is also available as a source for time zone +It is primarily intended to be used by standard library's :mod:`zoneinfo` +module, but it is also available as a source for time zone data for other time zone libraries. It is generally recommended that any time zone libraries should attempt to use the system data before using the ``tzdata`` package, but some systems (notably Windows) do not deploy zoneinfo diff --git a/docs/requirements.txt b/docs/requirements.txt index b5ae166..9d4d4e4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,2 @@ sphinx>=3.0.0 -sphinx_bootstrap_theme +furo diff --git a/news.d/2025c.md b/news.d/2025c.md new file mode 100644 index 0000000..774392c --- /dev/null +++ b/news.d/2025c.md @@ -0,0 +1,21 @@ +# Version 2025.3 +Upstream version 2025c released 2025-12-10T22:42:37+00:00 + +## Briefly: + +Several code changes for compatibility with FreeBSD. + +## Changes to past timestamps + +Baja California agreed with California’s DST rules in 1953 and in 1961 through +1975, instead of observing standard time all year. (Thanks to Alois Treindl.) + +## Changes to commentary + +The leapseconds file contains commentary about the IERS and NIST last-modified +and expiration timestamps for leap second data. (Thanks to Judah Levine.) + +Commentary now also uses characters from the set –‘’“”•≤ as this can be useful +and should work with current applications. This also affects data in +iso3166.tab and zone1970.tab, which now contain strings like “Côte d’Ivoire” +instead of “Côte d'Ivoire”. \ No newline at end of file diff --git a/news.d/2026a.md b/news.d/2026a.md new file mode 100644 index 0000000..0a0878c --- /dev/null +++ b/news.d/2026a.md @@ -0,0 +1,21 @@ +# Version 2026.1 +Upstream version 2026a released 2026-03-02T06:59:49+00:00 + +## Briefly: + +Moldova has used EU transition times since 2022. The "right" TZif files are no +longer installed by default. -DTZ_RUNTIME_LEAPS=0 disables runtime support for +leap seconds. TZif files are no longer limited to 50 bytes of abbreviations. zic +is no longer limited to 50 leap seconds. Several integer overflow bugs have been +fixed. + +## Changes to past and future timestamps + +Since 2022 Moldova has observed EU transition times, that is, it has sprung +forward at 03:00, not 02:00, and has fallen back at 04:00, not 03:00. (Thanks +to Heitor David Pinto.) + +## Changes to data + +Remove Europe/Chisinau from zonenow.tab, as it now agrees with Europe/Athens for +future timestamps. \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 463d7ec..977344b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,15 +12,14 @@ license_files = LICENSE licenses/LICENSE_APACHE classifiers = - Development Status :: 4 - Beta + Development Status :: 5 - Production/Stable Intended Audience :: Developers - License :: OSI Approved :: Apache Software License Programming Language :: Python :: 2 Programming Language :: Python :: 3 project_urls = Bug Reports = https://github.com/python/tzdata/issues Source = https://github.com/python/tzdata - Documentation = https://tzdata.readthedocs.io + Documentation = https://tzdata.python.org [options] packages = tzdata diff --git a/src/tzdata/__init__.py b/src/tzdata/__init__.py index d5adb25..497592c 100644 --- a/src/tzdata/__init__.py +++ b/src/tzdata/__init__.py @@ -1,6 +1,6 @@ # IANA versions like 2020a are not valid PEP 440 identifiers; the recommended # way to translate the version is to use YYYY.n where `n` is a 0-based index. -__version__ = "2025.2" +__version__ = "2026.1" # This exposes the original IANA version number. -IANA_VERSION = "2025b" +IANA_VERSION = "2026a" diff --git a/src/tzdata/zoneinfo/America/Ensenada b/src/tzdata/zoneinfo/America/Ensenada index 18d0d14..0d8c993 100644 Binary files a/src/tzdata/zoneinfo/America/Ensenada and b/src/tzdata/zoneinfo/America/Ensenada differ diff --git a/src/tzdata/zoneinfo/America/Santa_Isabel b/src/tzdata/zoneinfo/America/Santa_Isabel index 18d0d14..0d8c993 100644 Binary files a/src/tzdata/zoneinfo/America/Santa_Isabel and b/src/tzdata/zoneinfo/America/Santa_Isabel differ diff --git a/src/tzdata/zoneinfo/America/Tijuana b/src/tzdata/zoneinfo/America/Tijuana index 18d0d14..0d8c993 100644 Binary files a/src/tzdata/zoneinfo/America/Tijuana and b/src/tzdata/zoneinfo/America/Tijuana differ diff --git a/src/tzdata/zoneinfo/Asia/Tbilisi b/src/tzdata/zoneinfo/Asia/Tbilisi index 166e434..247caa6 100644 Binary files a/src/tzdata/zoneinfo/Asia/Tbilisi and b/src/tzdata/zoneinfo/Asia/Tbilisi differ diff --git a/src/tzdata/zoneinfo/Europe/Chisinau b/src/tzdata/zoneinfo/Europe/Chisinau index 9152e68..a60bddd 100644 Binary files a/src/tzdata/zoneinfo/Europe/Chisinau and b/src/tzdata/zoneinfo/Europe/Chisinau differ diff --git a/src/tzdata/zoneinfo/Europe/Tiraspol b/src/tzdata/zoneinfo/Europe/Tiraspol index 9152e68..a60bddd 100644 Binary files a/src/tzdata/zoneinfo/Europe/Tiraspol and b/src/tzdata/zoneinfo/Europe/Tiraspol differ diff --git a/src/tzdata/zoneinfo/Mexico/BajaNorte b/src/tzdata/zoneinfo/Mexico/BajaNorte index 18d0d14..0d8c993 100644 Binary files a/src/tzdata/zoneinfo/Mexico/BajaNorte and b/src/tzdata/zoneinfo/Mexico/BajaNorte differ diff --git a/src/tzdata/zoneinfo/iso3166.tab b/src/tzdata/zoneinfo/iso3166.tab index 402c015..4ae3523 100644 --- a/src/tzdata/zoneinfo/iso3166.tab +++ b/src/tzdata/zoneinfo/iso3166.tab @@ -3,22 +3,22 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. # -# From Paul Eggert (2023-09-06): +# From Paul Eggert (2025-07-01): # This file contains a table of two-letter country codes. Columns are -# separated by a single tab. Lines beginning with '#' are comments. +# separated by a single tab. Lines beginning with ‘#’ are comments. # All text uses UTF-8 encoding. The columns of the table are as follows: # # 1. ISO 3166-1 alpha-2 country code, current as of -# ISO/TC 46 N1108 (2023-04-05). See: ISO/TC 46 Documents +# ISO/TC 46 N1127 (2024-02-29). See: ISO/TC 46 Documents # https://www.iso.org/committee/48750.html?view=documents # 2. The usual English name for the coded region. This sometimes # departs from ISO-listed names, sometimes so that sorted subsets -# of names are useful (e.g., "Samoa (American)" and "Samoa -# (western)" rather than "American Samoa" and "Samoa"), +# of names are useful (e.g., “Samoa (American)” and “Samoa +# (western)” rather than “American Samoa” and “Samoa”), # sometimes to avoid confusion among non-experts (e.g., -# "Czech Republic" and "Turkey" rather than "Czechia" and "Türkiye"), -# and sometimes to omit needless detail or churn (e.g., "Netherlands" -# rather than "Netherlands (the)" or "Netherlands (Kingdom of the)"). +# “Czech Republic” and “Turkey” rather than “Czechia” and “Türkiye”), +# and sometimes to omit needless detail or churn (e.g., “Netherlands” +# rather than “Netherlands (the)” or “Netherlands (Kingdom of the)”). # # The table is sorted by country code. # @@ -71,7 +71,7 @@ CD Congo (Dem. Rep.) CF Central African Rep. CG Congo (Rep.) CH Switzerland -CI Côte d'Ivoire +CI Côte d’Ivoire CK Cook Islands CL Chile CM Cameroon diff --git a/src/tzdata/zoneinfo/leapseconds b/src/tzdata/zoneinfo/leapseconds index 76f7714..a796e4b 100644 --- a/src/tzdata/zoneinfo/leapseconds +++ b/src/tzdata/zoneinfo/leapseconds @@ -5,7 +5,8 @@ # This file is generated automatically from the data in the public-domain # NIST/IERS format leap-seconds.list file, which can be copied from # -# or, in a variant with different comments, from +# or via a less-secure protocol and with different comments and +# less volatile last-modified and expiration timestamps, from # . # For more about leap-seconds.list, please see # The NTP Timescale and Leap Seconds @@ -69,11 +70,17 @@ Leap 2016 Dec 31 23:59:60 + S # Any additional leap seconds will come after this. # This Expires line is commented out for now, # so that pre-2020a zic implementations do not reject this file. -#Expires 2025 Dec 28 00:00:00 +#Expires 2026 Dec 28 00:00:00 -# POSIX timestamps for the data in this file: -#updated 1736208000 (2025-01-07 00:00:00 UTC) -#expires 1766880000 (2025-12-28 00:00:00 UTC) +# Here are POSIX timestamps for the data in this file. +# "#updated" gives the last time the leap seconds data changed +# or, if this file was derived from the IERS leap-seconds.list, +# the last time that file changed in any way. +# "#expires" gives the first time this file might be wrong; +# if this file was derived from the IERS leap-seconds.list, +# this is typically a bit less than one year after "updated". +#updated 1767698058 (2026-01-06 11:14:18 UTC) +#expires 1798416000 (2026-12-28 00:00:00 UTC) # Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat) -# File expires on 28 December 2025 +# File expires on 28 December 2026 diff --git a/src/tzdata/zoneinfo/tzdata.zi b/src/tzdata/zoneinfo/tzdata.zi index a7fb52f..88f7d34 100644 --- a/src/tzdata/zoneinfo/tzdata.zi +++ b/src/tzdata/zoneinfo/tzdata.zi @@ -1,4 +1,5 @@ -# version 2025b +# version 2026a +# redo posix_only # This zic input file is in the public domain. R d 1916 o - Jun 14 23s 1 S R d 1916 1919 - O Su>=1 23s 0 - @@ -1304,8 +1305,8 @@ R MT 1974 o - S 16 0s 0 - R MT 1975 1979 - Ap Su>=15 2 1 S R MT 1975 1980 - S Su>=15 2 0 - R MT 1980 o - Mar 31 2 1 S -R MD 1997 ma - Mar lastSu 2 1 S -R MD 1997 ma - O lastSu 3 0 - +R MD 1997 2021 - Mar lastSu 2 1 S +R MD 1997 2021 - O lastSu 3 0 - R O 1918 1919 - S 16 2s 0 - R O 1919 o - Ap 15 2s 1 S R O 1944 o - Ap 3 2s 1 S @@ -2951,9 +2952,7 @@ Z America/Tijuana -7:48:4 - LMT 1922 Ja 1 7u -8 1 PDT 1951 S 30 2 -8 - PST 1952 Ap 27 2 -8 1 PDT 1952 S 28 2 --8 - PST 1954 --8 CA P%sT 1961 --8 - PST 1976 +-8 CA P%sT 1967 -8 u P%sT 1996 -8 m P%sT 2001 -8 u P%sT 2002 F 20 @@ -3668,7 +3667,8 @@ Z Europe/Chisinau 1:55:20 - LMT 1880 3 R MSK/MSD 1990 May 6 2 2 R EE%sT 1992 2 e EE%sT 1997 -2 MD EE%sT +2 MD EE%sT 2022 +2 E EE%sT Z Europe/Dublin -0:25:21 - LMT 1880 Au 2 -0:25:21 - DMT 1916 May 21 2s -0:25:21 1 IST 1916 O 1 2s diff --git a/src/tzdata/zoneinfo/zone1970.tab b/src/tzdata/zoneinfo/zone1970.tab index 36535bd..cd43e3d 100644 --- a/src/tzdata/zoneinfo/zone1970.tab +++ b/src/tzdata/zoneinfo/zone1970.tab @@ -2,15 +2,15 @@ # # This file is in the public domain. # -# From Paul Eggert (2018-06-27): +# From Paul Eggert (2025-05-15): # This file contains a table where each row stands for a timezone where # civil timestamps have agreed since 1970. Columns are separated by -# a single tab. Lines beginning with '#' are comments. All text uses +# a single tab. Lines beginning with ‘#’ are comments. All text uses # UTF-8 encoding. The columns of the table are as follows: # # 1. The countries that overlap the timezone, as a comma-separated list -# of ISO 3166 2-character country codes. See the file 'iso3166.tab'. -# 2. Latitude and longitude of the timezone's principal location +# of ISO 3166 2-character country codes. +# 2. Latitude and longitude of the timezone’s principal location # in ISO 6709 sign-degrees-minutes-seconds format, # either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS, # first latitude (+ is north), then longitude (+ is east). @@ -197,7 +197,7 @@ KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau -KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev +KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur’yev KZ +5113+05121 Asia/Oral West Kazakhstan LB +3353+03530 Asia/Beirut LK +0656+07951 Asia/Colombo @@ -245,7 +245,7 @@ PE -1203-07703 America/Lima PF -1732-14934 Pacific/Tahiti Society Islands PF -0900-13930 Pacific/Marquesas Marquesas Islands PF -2308-13457 Pacific/Gambier Gambier Islands -PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d'Urville +PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d’Urville PG -0613+15534 Pacific/Bougainville Bougainville PH +143512+1205804 Asia/Manila PK +2452+06703 Asia/Karachi @@ -265,7 +265,7 @@ RO +4426+02606 Europe/Bucharest RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area -# Mention RU and UA alphabetically. See "territorial claims" above. +# Mention RU and UA alphabetically. See “territorial claims” above. RU,UA +4457+03406 Europe/Simferopol Crimea RU +5836+04939 Europe/Kirov MSK+00 - Kirov RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd @@ -353,20 +353,20 @@ ZA,LS,SZ -2615+02800 Africa/Johannesburg # The next section contains experimental tab-separated comments for # use by user agents like tzselect that identify continents and oceans. # -# For example, the comment "#@AQAntarctica/" means the country code +# For example, the comment ‘#@AQAntarctica/’ means the country code # AQ is in the continent Antarctica regardless of the Zone name, # so Pacific/Auckland should be listed under Antarctica as well as -# under the Pacific because its line's country codes include AQ. +# under the Pacific because its line’s country codes include AQ. # # If more than one country code is affected each is listed separated -# by commas, e.g., #@IS,SHAtlantic/". If a country code is in +# by commas, e.g., ‘#@IS,SHAtlantic/’. If a country code is in # more than one continent or ocean, each is listed separated by -# commas, e.g., the second column of "#@CY,TRAsia/,Europe/". +# commas, e.g., the second column of ‘#@CY,TRAsia/,Europe/’. # # These experimental comments are present only for country codes where # the continent or ocean is not already obvious from the Zone name. # For example, there is no such comment for RU since it already -# corresponds to Zone names starting with both "Europe/" and "Asia/". +# corresponds to Zone names starting with both ‘Europe/’ and ‘Asia/’. # #@AQ Antarctica/ #@IS,SH Atlantic/ diff --git a/src/tzdata/zoneinfo/zonenow.tab b/src/tzdata/zoneinfo/zonenow.tab index 093f0a0..aa3a64f 100644 --- a/src/tzdata/zoneinfo/zonenow.tab +++ b/src/tzdata/zoneinfo/zonenow.tab @@ -5,12 +5,12 @@ # From Paul Eggert (2023-12-18): # This file contains a table where each row stands for a timezone # where civil timestamps are predicted to agree from now on. -# This file is like zone1970.tab (see zone1970.tab's comments), +# This file is like zone1970.tab (see zone1970.tab’s comments), # but with the following changes: # # 1. Each timezone corresponds to a set of clocks that are planned # to agree from now on. This is a larger set of clocks than in -# zone1970.tab, where each timezone's clocks must agree from 1970 on. +# zone1970.tab, where each timezone’s clocks must agree from 1970 on. # 2. The first column is irrelevant and ignored. # 3. The table is sorted in a different way: # first by standard time UTC offset; @@ -29,19 +29,19 @@ #XX coordinates TZ comments # # -11 - SST -XX -1416-17042 Pacific/Pago_Pago Midway; Samoa ("SST") +XX -1416-17042 Pacific/Pago_Pago Midway; Samoa (SST) # # -11 XX -1901-16955 Pacific/Niue Niue # # -10 - HST -XX +211825-1575130 Pacific/Honolulu Hawaii ("HST") +XX +211825-1575130 Pacific/Honolulu Hawaii (HST) # # -10 XX -1732-14934 Pacific/Tahiti Tahiti; Cook Islands # # -10/-09 - HST / HDT (North America DST) -XX +515248-1763929 America/Adak western Aleutians in Alaska ("HST/HDT") +XX +515248-1763929 America/Adak western Aleutians in Alaska (HST/HDT) # # -09:30 XX -0900-13930 Pacific/Marquesas Marquesas @@ -50,58 +50,58 @@ XX -0900-13930 Pacific/Marquesas Marquesas XX -2308-13457 Pacific/Gambier Gambier # # -09/-08 - AKST/AKDT (North America DST) -XX +611305-1495401 America/Anchorage most of Alaska ("AKST/AKDT") +XX +611305-1495401 America/Anchorage most of Alaska (AKST/AKDT) # # -08 XX -2504-13005 Pacific/Pitcairn Pitcairn # # -08/-07 - PST/PDT (North America DST) -XX +340308-1181434 America/Los_Angeles Pacific ("PST/PDT") - US & Canada; Mexico near US border +XX +340308-1181434 America/Los_Angeles Pacific (PST/PDT) - US & Canada; Mexico near US border # # -07 - MST -XX +332654-1120424 America/Phoenix Mountain Standard ("MST") - Arizona; western Mexico; Yukon +XX +332654-1120424 America/Phoenix Mountain Standard (MST) - Arizona; western Mexico; Yukon # # -07/-06 - MST/MDT (North America DST) -XX +394421-1045903 America/Denver Mountain ("MST/MDT") - US & Canada; Mexico near US border +XX +394421-1045903 America/Denver Mountain (MST/MDT) - US & Canada; Mexico near US border # # -06 XX -0054-08936 Pacific/Galapagos Galápagos # # -06 - CST -XX +1924-09909 America/Mexico_City Central Standard ("CST") - Saskatchewan; central Mexico; Central America +XX +1924-09909 America/Mexico_City Central Standard (CST) - Saskatchewan; central Mexico; Central America # # -06/-05 (Chile DST) XX -2709-10926 Pacific/Easter Easter Island # # -06/-05 - CST/CDT (North America DST) -XX +415100-0873900 America/Chicago Central ("CST/CDT") - US & Canada; Mexico near US border +XX +415100-0873900 America/Chicago Central (CST/CDT) - US & Canada; Mexico near US border # # -05 XX -1203-07703 America/Lima eastern South America # # -05 - EST -XX +175805-0764736 America/Jamaica Eastern Standard ("EST") - Caymans; Jamaica; eastern Mexico; Panama +XX +175805-0764736 America/Jamaica Eastern Standard (EST) - Caymans; Jamaica; eastern Mexico; Panama # # -05/-04 - CST/CDT (Cuba DST) XX +2308-08222 America/Havana Cuba # # -05/-04 - EST/EDT (North America DST) -XX +404251-0740023 America/New_York Eastern ("EST/EDT") - US & Canada +XX +404251-0740023 America/New_York Eastern (EST/EDT) - US & Canada # # -04 XX +1030-06656 America/Caracas western South America # # -04 - AST -XX +1828-06954 America/Santo_Domingo Atlantic Standard ("AST") - eastern Caribbean +XX +1828-06954 America/Santo_Domingo Atlantic Standard (AST) - eastern Caribbean # # -04/-03 (Chile DST) XX -3327-07040 America/Santiago most of Chile # # -04/-03 - AST/ADT (North America DST) -XX +4439-06336 America/Halifax Atlantic ("AST/ADT") - Canada; Bermuda +XX +4439-06336 America/Halifax Atlantic (AST/ADT) - Canada; Bermuda # # -03:30/-02:30 - NST/NDT (North America DST) -XX +4734-05243 America/St_Johns Newfoundland ("NST/NDT") +XX +4734-05243 America/St_Johns Newfoundland (NST/NDT) # # -03 XX -2332-04637 America/Sao_Paulo eastern and southern South America @@ -122,43 +122,43 @@ XX +1455-02331 Atlantic/Cape_Verde Cape Verde XX +3744-02540 Atlantic/Azores Azores # # +00 - GMT -XX +0519-00402 Africa/Abidjan far western Africa; Iceland ("GMT") +XX +0519-00402 Africa/Abidjan far western Africa; Iceland (GMT) # # +00/+01 - GMT/BST (EU DST) -XX +513030-0000731 Europe/London United Kingdom ("GMT/BST") +XX +513030-0000731 Europe/London United Kingdom (GMT/BST) # # +00/+01 - WET/WEST (EU DST) -XX +3843-00908 Europe/Lisbon western Europe ("WET/WEST") +XX +3843-00908 Europe/Lisbon western Europe (WET/WEST) # # +00/+02 - Troll DST XX -720041+0023206 Antarctica/Troll Troll Station in Antarctica # # +01 - CET -XX +3647+00303 Africa/Algiers Algeria, Tunisia ("CET") +XX +3647+00303 Africa/Algiers Algeria, Tunisia (CET) # # +01 - WAT -XX +0627+00324 Africa/Lagos western Africa ("WAT") +XX +0627+00324 Africa/Lagos western Africa (WAT) # # +01/+00 - IST/GMT (EU DST in reverse) -XX +5320-00615 Europe/Dublin Ireland ("IST/GMT") +XX +5320-00615 Europe/Dublin Ireland (IST/GMT) # # +01/+00 - (Morocco DST) XX +3339-00735 Africa/Casablanca Morocco # # +01/+02 - CET/CEST (EU DST) -XX +4852+00220 Europe/Paris central Europe ("CET/CEST") +XX +4852+00220 Europe/Paris central Europe (CET/CEST) # # +02 - CAT -XX -2558+03235 Africa/Maputo central Africa ("CAT") +XX -2558+03235 Africa/Maputo central Africa (CAT) # # +02 - EET -XX +3254+01311 Africa/Tripoli Libya; Kaliningrad ("EET") +XX +3254+01311 Africa/Tripoli Libya; Kaliningrad (EET) # # +02 - SAST -XX -2615+02800 Africa/Johannesburg southern Africa ("SAST") +XX -2615+02800 Africa/Johannesburg southern Africa (SAST) # # +02/+03 - EET/EEST (EU DST) -XX +3758+02343 Europe/Athens eastern Europe ("EET/EEST") +XX +3758+02343 Europe/Athens eastern Europe (EET/EEST) # # +02/+03 - EET/EEST (Egypt DST) XX +3003+03115 Africa/Cairo Egypt @@ -166,9 +166,6 @@ XX +3003+03115 Africa/Cairo Egypt # +02/+03 - EET/EEST (Lebanon DST) XX +3353+03530 Asia/Beirut Lebanon # -# +02/+03 - EET/EEST (Moldova DST) -XX +4700+02850 Europe/Chisinau Moldova -# # +02/+03 - EET/EEST (Palestine DST) XX +3130+03428 Asia/Gaza Palestine # @@ -179,10 +176,10 @@ XX +314650+0351326 Asia/Jerusalem Israel XX +4101+02858 Europe/Istanbul Near East; Belarus # # +03 - EAT -XX -0117+03649 Africa/Nairobi eastern Africa ("EAT") +XX -0117+03649 Africa/Nairobi eastern Africa (EAT) # # +03 - MSK -XX +554521+0373704 Europe/Moscow Moscow ("MSK") +XX +554521+0373704 Europe/Moscow Moscow (MSK) # # +03:30 XX +3540+05126 Asia/Tehran Iran @@ -197,13 +194,13 @@ XX +3431+06912 Asia/Kabul Afghanistan XX +4120+06918 Asia/Tashkent Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives # # +05 - PKT -XX +2452+06703 Asia/Karachi Pakistan ("PKT") +XX +2452+06703 Asia/Karachi Pakistan (PKT) # # +05:30 XX +0656+07951 Asia/Colombo Sri Lanka # # +05:30 - IST -XX +2232+08822 Asia/Kolkata India ("IST") +XX +2232+08822 Asia/Kolkata India (IST) # # +05:45 XX +2743+08519 Asia/Kathmandu Nepal @@ -218,25 +215,25 @@ XX +1647+09610 Asia/Yangon Myanmar; Cocos XX +1345+10031 Asia/Bangkok Russia; Indochina; Christmas Island # # +07 - WIB -XX -0610+10648 Asia/Jakarta Indonesia ("WIB") +XX -0610+10648 Asia/Jakarta Indonesia (WIB) # # +08 XX +0117+10351 Asia/Singapore Russia; Brunei; Malaysia; Singapore; Concordia # # +08 - AWST -XX -3157+11551 Australia/Perth Western Australia ("AWST") +XX -3157+11551 Australia/Perth Western Australia (AWST) # # +08 - CST -XX +3114+12128 Asia/Shanghai China ("CST") +XX +3114+12128 Asia/Shanghai China (CST) # # +08 - HKT -XX +2217+11409 Asia/Hong_Kong Hong Kong ("HKT") +XX +2217+11409 Asia/Hong_Kong Hong Kong (HKT) # # +08 - PHT -XX +143512+1205804 Asia/Manila Philippines ("PHT") +XX +143512+1205804 Asia/Manila Philippines (PHT) # # +08 - WITA -XX -0507+11924 Asia/Makassar Indonesia ("WITA") +XX -0507+11924 Asia/Makassar Indonesia (WITA) # # +08:45 XX -3143+12852 Australia/Eucla Eucla @@ -245,31 +242,31 @@ XX -3143+12852 Australia/Eucla Eucla XX +5203+11328 Asia/Chita Russia; Palau; East Timor # # +09 - JST -XX +353916+1394441 Asia/Tokyo Japan ("JST"); Eyre Bird Observatory +XX +353916+1394441 Asia/Tokyo Japan (JST); Eyre Bird Observatory # # +09 - KST -XX +3733+12658 Asia/Seoul Korea ("KST") +XX +3733+12658 Asia/Seoul Korea (KST) # # +09 - WIT -XX -0232+14042 Asia/Jayapura Indonesia ("WIT") +XX -0232+14042 Asia/Jayapura Indonesia (WIT) # # +09:30 - ACST -XX -1228+13050 Australia/Darwin Northern Territory ("ACST") +XX -1228+13050 Australia/Darwin Northern Territory (ACST) # # +09:30/+10:30 - ACST/ACDT (Australia DST) -XX -3455+13835 Australia/Adelaide South Australia ("ACST/ACDT") +XX -3455+13835 Australia/Adelaide South Australia (ACST/ACDT) # # +10 -XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d'Urville +XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d’Urville # # +10 - AEST -XX -2728+15302 Australia/Brisbane Queensland ("AEST") +XX -2728+15302 Australia/Brisbane Queensland (AEST) # # +10 - ChST -XX +1328+14445 Pacific/Guam Mariana Islands ("ChST") +XX +1328+14445 Pacific/Guam Mariana Islands (ChST) # # +10/+11 - AEST/AEDT (Australia DST) -XX -3352+15113 Australia/Sydney southeast Australia ("AEST/AEDT") +XX -3352+15113 Australia/Sydney southeast Australia (AEST/AEDT) # # +10:30/+11 XX -3133+15905 Australia/Lord_Howe Lord Howe Island @@ -284,7 +281,7 @@ XX -2903+16758 Pacific/Norfolk Norfolk Island XX +5301+15839 Asia/Kamchatka Russia; Tuvalu; Fiji; etc. # # +12/+13 (New Zealand DST) -XX -3652+17446 Pacific/Auckland New Zealand ("NZST/NZDT") +XX -3652+17446 Pacific/Auckland New Zealand (NZST/NZDT) # # +12:45/+13:45 (Chatham DST) XX -4357-17633 Pacific/Chatham Chatham Islands diff --git a/tox.ini b/tox.ini index e3f82b4..83e7708 100644 --- a/tox.ini +++ b/tox.ini @@ -6,8 +6,9 @@ skip_missing_interpreters = true [testenv] description = Test that the tzdata contents are accessible deps = - pytest - pytest-subtests; python_version>='3.6' + pytest >= 9; python_version >= '3.10' + pytest; python_version < '3.10' + pytest-subtests; python_version >= '3.6' and python_version <= '3.9' importlib_resources; python_version<'3.7' commands = pytest {toxinidir} {posargs} @@ -27,6 +28,7 @@ deps = requests click parver + python-gnupg commands = python update.py {posargs} @@ -80,17 +82,3 @@ commands = [x.unlink(missing_ok=True) for x in Path('{toxinidir}/dist').glob('*')]" python -m build -o {toxinidir}/dist {toxinidir} twine check {toxinidir}/dist/* - -[testenv:release] -description = Make a release; must be called after "build" -skip_install = True -deps = - twine -depends = - build -passenv = - TWINE_* -commands = - twine check {toxinidir}/dist/* - twine upload {toxinidir}/dist/* \ - {posargs:-r {env:TWINE_REPOSITORY:testpypi} --non-interactive} diff --git a/update.py b/update.py index aa760f3..5090cdc 100644 --- a/update.py +++ b/update.py @@ -15,6 +15,7 @@ from datetime import datetime, timezone import click +import gnupg # type: ignore import parver # type: ignore import requests @@ -37,13 +38,15 @@ def download_tzdb_tarballs( """Download the tzdata and tzcode tarballs.""" tzdata_file = f"tzdata{version}.tar.gz" tzcode_file = f"tzcode{version}.tar.gz" + tzdata_file_asc = tzdata_file + ".asc" + tzcode_file_asc = tzcode_file + ".asc" target_dir = working_dir / version / "download" # mkdir -p target_dir target_dir.mkdir(parents=True, exist_ok=True) download_locations = [] - for filename in [tzdata_file, tzcode_file]: + for filename in [tzdata_file, tzcode_file, tzdata_file_asc, tzcode_file_asc]: download_location = target_dir / filename download_locations.append(download_location) @@ -58,6 +61,25 @@ def download_tzdb_tarballs( with open(download_location, "wb") as f: f.write(r.content) + # Verify tarballs + gpg_home = tempfile.TemporaryDirectory() + gpg = gnupg.GPG(gnupghome=gpg_home.name) + gpg.recv_keys("hkps://keyserver.ubuntu.com", "ed97e90e62aa7e34") + + for tar, asc in [(tzdata_file, tzdata_file_asc), (tzcode_file, tzcode_file_asc)]: + tar_path = target_dir / tar + sig_path = target_dir / asc + + if not tar_path.exists() or not sig_path.exists(): + raise FileNotFoundError( + f"Missing file or signature: {tar_path}, {sig_path}" + ) + + with open(sig_path, "rb") as f: + check = gpg.verify_file(f, str(tar_path)) + if not check.valid: + raise RuntimeError(f"signature verification failed for {tar_path}") + return download_locations @@ -95,7 +117,7 @@ def retrieve_local_tarballs( def unpack_tzdb_tarballs( download_locations: Sequence[pathlib.Path], ) -> pathlib.Path: - assert len(download_locations) == 2 + assert len(download_locations) == 4 assert download_locations[0].parent == download_locations[1].parent base_dir = download_locations[0].parent.parent target_dir = base_dir / "tzdb" @@ -107,6 +129,8 @@ def unpack_tzdb_tarballs( target_dir.mkdir() for tarball in download_locations: + if tarball.suffix == ".asc": + continue logging.info("Unpacking %s to %s", tarball, target_dir) subprocess.run( ["tar", "-xf", os.fspath(tarball.absolute())], @@ -204,7 +228,7 @@ def find_latest_version() -> str: assert vfile is not None, "version file is not a regular file" version = vfile.read().decode("utf-8").strip() - assert re.match("\d{4}[a-z]$", version), version + assert re.match(r"\d{4}[a-z]$", version), version target_dir = WORKING_DIR / version / "download" target_dir.mkdir(parents=True, exist_ok=True) @@ -375,7 +399,7 @@ def parse_categories(news_block: Sequence[str]) -> Mapping[str, str]: def read_news(tzdb_loc: pathlib.Path, version: str | None = None) -> NewsEntry: - release_re = re.compile("^Release (?P\d{4}[a-z]) - (?P.*$)") + release_re = re.compile(r"^Release (?P\d{4}[a-z]) - (?P.*$)") with open(tzdb_loc / "NEWS", "rt") as f: f_lines = map(str.rstrip, f) for line in f_lines: