Skip to content

Commit 619cb73

Browse files
committed
Give British Columbia, Alberta and Manitoba their own timezones
British Columbia, Alberta and Manitoba stop changing their clocks in November 2026 and stay on UTC-7, UTC-6 and UTC-5 all year. The "US & Canada" entries they use today go back an hour in winter, so each province gets its own entry: Vancouver, Edmonton and Winnipeg. `Canada/Central` follows Manitoba's rules, so it can no longer stand in for US Central time or for Central America, which stays on UTC-6; "Central America" moves to `America/Guatemala`. `ubuntu-latest` now resolves to Ubuntu 26.04, whose system zone files leave out the legacy `US/*` names, so the suite failed at collection with "Invalid timezone US/Hawaii". tox now installs `tzdata`, which `zoneinfo` falls back to for names the system does not have.
1 parent 94e7733 commit 619cb73

4 files changed

Lines changed: 93 additions & 2 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Added
9+
- Add `America/Vancouver`, since British Columbia stays on UTC-7 all year from November 2026.
10+
- Add `America/Edmonton` and `America/Winnipeg`, since Alberta and Manitoba stay on UTC-6 and UTC-5 all year from November 2026.
11+
12+
### Changed
13+
- "Central America" uses `America/Guatemala` instead of `Canada/Central`, which follows Manitoba's rules.
14+
15+
### Removed
16+
- Drop the `Canada/Central` entry labeled "Central Time (US & Canada)". `US/Central` covers the US, and `America/Winnipeg` covers Manitoba.
817

918
## [3.0.0] - 2024-11-15
1019
### Changed

‎timezones/_defs.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@
3131
("US/Arizona", "Arizona"),
3232
("America/Mazatlan", "Mazatlan"),
3333
("US/Mountain", "Mountain Time (US & Canada)"),
34+
("America/Vancouver", "Vancouver"),
3435
# -06
3536
("America/Chihuahua", "Chihuahua"),
3637
("US/Central", "Central Time (US & Canada)"),
37-
("Canada/Central", "Central America"),
38-
("Canada/Central", "Central Time (US & Canada)"),
38+
("America/Guatemala", "Central America"),
39+
("America/Edmonton", "Edmonton"),
3940
("Mexico/General", "Guadalajara"),
4041
("Mexico/General", "Mexico City"),
4142
("America/Monterrey", "Monterrey"),
@@ -47,6 +48,7 @@
4748
("America/Lima", "Lima"),
4849
("America/Rio_Branco", "Rio Branco"),
4950
("Etc/GMT+5", "Quito"), # "plus" value is correct!
51+
("America/Winnipeg", "Winnipeg"),
5052
# -04
5153
("America/Caracas", "Caracas"),
5254
("Canada/Atlantic", "Atlantic Time (Canada)"),

‎timezones/test_timezones.py‎

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from datetime import datetime, timedelta
2+
13
import pytest
24

35
from . import _defs, tz_rendering, tz_utils, zones
@@ -74,3 +76,80 @@ def test_aliases(tzname):
7476
_, name, formatted = tz_utils.format_tz_by_name(tzname)
7577
assert name == tzname
7678
assert tzname in formatted
79+
80+
81+
def test_get_timezones_lists_vancouver():
82+
# Given British Columbia has its own timezone from November 2026
83+
vancouver_labels = []
84+
85+
# When the supported timezones are listed
86+
all_timezones = zones.get_timezones()
87+
88+
# Then America/Vancouver is offered under its own name
89+
for offset_str, tzname, verbose_name in all_timezones:
90+
if tzname == "America/Vancouver":
91+
vancouver_labels.append(verbose_name)
92+
assert len(vancouver_labels) == 1
93+
assert vancouver_labels[0].endswith(") Vancouver")
94+
95+
96+
def test_get_timezones_lists_edmonton():
97+
# Given Alberta has its own timezone from November 2026
98+
edmonton_labels = []
99+
100+
# When the supported timezones are listed
101+
all_timezones = zones.get_timezones()
102+
103+
# Then America/Edmonton is offered under its own name
104+
for offset_str, tzname, verbose_name in all_timezones:
105+
if tzname == "America/Edmonton":
106+
edmonton_labels.append(verbose_name)
107+
assert len(edmonton_labels) == 1
108+
assert edmonton_labels[0].endswith(") Edmonton")
109+
110+
111+
def test_get_timezones_lists_winnipeg():
112+
# Given Manitoba has its own timezone from November 2026
113+
winnipeg_labels = []
114+
115+
# When the supported timezones are listed
116+
all_timezones = zones.get_timezones()
117+
118+
# Then America/Winnipeg is offered under its own name
119+
for offset_str, tzname, verbose_name in all_timezones:
120+
if tzname == "America/Winnipeg":
121+
winnipeg_labels.append(verbose_name)
122+
assert len(winnipeg_labels) == 1
123+
assert winnipeg_labels[0].endswith(") Winnipeg")
124+
125+
126+
def test_get_timezones_offers_us_central_time_only_for_us_central():
127+
# Given Manitoba no longer follows US Central time from November 2026
128+
central_time_zone_names = []
129+
130+
# When the supported timezones are listed
131+
all_timezones = zones.get_timezones()
132+
133+
# Then "Central Time (US & Canada)" is offered only for US/Central
134+
for offset_str, tzname, verbose_name in all_timezones:
135+
if verbose_name.endswith(") Central Time (US & Canada)"):
136+
central_time_zone_names.append(tzname)
137+
assert central_time_zone_names == ["US/Central"]
138+
139+
140+
def test_get_timezones_keeps_central_america_on_utc_minus_6():
141+
# Given a date in December 2026, after Manitoba stops changing its clocks
142+
december_2026 = datetime(2026, 12, 1, 12, 0)
143+
central_america_zone_names = []
144+
145+
# When the supported timezones are listed
146+
all_timezones = zones.get_timezones()
147+
148+
# Then "Central America" is offered once, on a zone that is at UTC-6 then
149+
for offset_str, tzname, verbose_name in all_timezones:
150+
if verbose_name.endswith(") Central America"):
151+
central_america_zone_names.append(tzname)
152+
assert len(central_america_zone_names) == 1
153+
central_america_zone = tz_utils.get_timezone(central_america_zone_names[0])
154+
assert central_america_zone is not None
155+
assert central_america_zone.utcoffset(december_2026) == timedelta(hours=-6)

‎tox.ini‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ python =
1111
[testenv]
1212
deps =
1313
pytest
14+
tzdata
1415
commands =
1516
pytest {posargs}
1617

0 commit comments

Comments
 (0)