Skip to content

Incorrectly applying Morocco 2026c update before official cutover #177

Description

@dyl-sv

Summary
When tzdata is loaded with the 2026c database (tested via auto-update functionality), datetimes created with the Africa/Casablanca or Africa/El_Aaiun timezones within 2026-03-22T02:00:00Z -> 2026-09-20T01:00:00Z incorrectly apply UTC+0 offset instead of UTC+1.

This means consumers who don't auto-update (and are on 2026b) have incorrect dates from the 20th of Sept this year onwards and consumers who do auto-update have incorrect dates now and have done since 2026c was released a month ago.

The 2026c release (announcement) sets the above two timezones to switch to UTC+0 permanently from 2026-09-20. Currently Morocco is normally UTC+1 and shifts to UTC+0 to transition in and out of Ramadan, which this year ran 2026-02-15 -> 2026-03-22.

Expected: dates between the end of Ramadan and 2026-09-20 apply UTC+1, dates on and after 2026-09-20 apply UTC+0 'forever'

Actual: dates after the end of Ramadan apply UTC+0 'forever'

Repro: https://github.com/dyl-sv/tzdata_morocco_test

Analysis:

In 2026b, the tzdata rules for Morocco were generated until 2087 in the following pattern:

Rule  Morocco 2025    only    -       Feb     23       3:00   -1:00   -
Rule  Morocco 2025    only    -       Apr      6       2:00   0       -
Rule  Morocco 2026    only    -       Feb     15       3:00   -1:00   -
Rule  Morocco 2026    only    -       Mar     22       2:00   0       -
# Rule Morocco 2027 only ... etc etc, 126 rules follow that were based on lunar year projections

That second-to-last column being the offset against the 'standard' Morocco time of UTC+1.

In 2026c, all rules past 2026 were deleted - all 'Rule Morocco 2027', '2028', ... '2087' are deleted.

Additionally the zone lines are changed (diff 2026b -> 2026c):

--- a/africa
+++ b/africa
@@ -1070,11 +1070,12 @@
 # Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
 			 0:00	Morocco	%z	1984 Mar 16
 			 1:00	-	%z	1986
 			 0:00	Morocco	%z	2018 Oct 28  3:00
-			 1:00	Morocco	%z
+			 1:00	Morocco	%z	2026 Sep 20  2:00
+			 0:00	-	%z
 
 # Western Sahara
 #
 # From Gwillim Law (2013-10-22):
 # A correspondent who is usually well informed about time zone matters
@@ -1086,11 +1087,12 @@
 # since most of it was then controlled by Morocco.
 
 Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan # El Aaiún
 			-1:00	-	%z	1976 Apr 14
 			 0:00	Morocco	%z	2018 Oct 28  3:00
-			 1:00	Morocco	%z
+			 1:00	Morocco	%z	2026 Sep 20  2:00
+			 0:00	-	%z
 
 # Botswana
 # Burundi
 # Democratic Republic of the Congo (eastern)
 # Malawi

Hypothesis
In PeriodBuilder, calc_periods_for_year/10 makes an incorrect assumption that because there are no rule years beyond 2026 that the zone line has also ended, when the two are independent: rule exhaustion shouldn't terminate a zone line that still has an UNTIL ahead of it.

Editing 2026c to move the zone line's UNTIL field from 2026 to 2027 resolves the issue and to me partially confirms the hypothesis.

Versions: tzdata 1.1.4, IANA 2026c, Elixir 1.20.2, OTP 29

Disclaimer: I used an LLM to create the reproduction and stress-test my assertions, however I am completely confident in the correctness of these findings. I wrote this issue text myself. The analysis and hypothesis are also based on a mix of LLM generated output and self-research.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions