Time zone databases, and how permanent daylight savings changed event times
By: Peter Keung | September 28, 2026 | Tales from a Developer and development
In Canada and the US, the vast majority of provinces, states, and territories observe daylight savings time. We are scheduled to change our clocks on Sunday, November 1, 2026, falling back by 1 hour at 2:00am.
However, on March 2 of this year, the province of British Columbia decided not to observe any more time changes starting on November 1, staying on permanent daylight savings time. On June 18, Alberta made the same decision. And most recently, on September 17th, Manitoba decided to follow this precedent and will likewise stay on daylight savings permanently, starting this November.
This created some work for content editors and website developers in those provinces, and what should have been a simple update ended up requiring some investigation. Here's the story of why event calendars started to display the wrong time for events, and how we fixed it.
tzdata: the time zone database
Most of our clients' websites run on Ubuntu. This means that our servers use tzdata, otherwise known as the time zone database. If you run this command on the server, you'll see an output of all scheduled time zone changes in Alberta:
$ zdump -v America/Edmonton
Sun Nov 2 07:59:59 2025 UT = Sun Nov 2 01:59:59 2025 MDT isdst=1 gmtoff=-21600
Sun Nov 2 08:00:00 2025 UT = Sun Nov 2 01:00:00 2025 MST isdst=0 gmtoff=-25200
Sun Mar 8 08:59:59 2026 UT = Sun Mar 8 01:59:59 2026 MST isdst=0 gmtoff=-25200
Sun Mar 8 09:00:00 2026 UT = Sun Mar 8 03:00:00 2026 MDT isdst=1 gmtoff=-21600
Sun Nov 1 07:59:59 2026 UT = Sun Nov 1 01:59:59 2026 MDT isdst=1 gmtoff=-21600
Sun Nov 1 08:00:00 2026 UT = Sun Nov 1 01:00:00 2026 MST isdst=0 gmtoff=-25200
Sun Mar 14 08:59:59 2027 UT = Sun Mar 14 01:59:59 2027 MST isdst=0 gmtoff=-25200
Sun Mar 14 09:00:00 2027 UT = Sun Mar 14 03:00:00 2027 MDT isdst=1 gmtoff=-21600
[...]
Sun Mar 8 08:59:59 2499 UT = Sun Mar 8 01:59:59 2499 MST isdst=0 gmtoff=-25200
Sun Mar 8 09:00:00 2499 UT = Sun Mar 8 03:00:00 2499 MDT isdst=1 gmtoff=-21600
Sun Nov 1 07:59:59 2499 UT = Sun Nov 1 01:59:59 2499 MDT isdst=1 gmtoff=-21600
Sun Nov 1 08:00:00 2499 UT = Sun Nov 1 01:00:00 2499 MST isdst=0 gmtoff=-25200
The above output was from before the time zone database was updated, and you can see that the schedule goes all the way to the year 2499!
If you run that command now, you should see the following, indicating that the time zone offset (relative to UTC) will no longer change in November.
$ zdump -v America/Edmonton
Sun Nov 2 07:59:59 2025 UT = Sun Nov 2 01:59:59 2025 MDT isdst=1 gmtoff=-21600
Sun Nov 2 08:00:00 2025 UT = Sun Nov 2 01:00:00 2025 MST isdst=0 gmtoff=-25200
Sun Mar 8 08:59:59 2026 UT = Sun Mar 8 01:59:59 2026 MST isdst=0 gmtoff=-25200
Sun Mar 8 09:00:00 2026 UT = Sun Mar 8 03:00:00 2026 MDT isdst=1 gmtoff=-21600
Sun Nov 1 07:59:59 2026 UT = Sun Nov 1 01:59:59 2026 MDT isdst=1 gmtoff=-21600
Sun Nov 1 08:00:00 2026 UT = Sun Nov 1 02:00:00 2026 CST isdst=0 gmtoff=-21600
A quick side note: if you were using the America/Los_Angeles or America/Denver identifier in your code for a BC or Alberta time zone, you'd better update your settings!
The problem: unwanted event time changes
Consider the following event poster, handed out to potential attendees at your Alberta-based library or posted on a bulletin board:
This event, Teddy Bear Yoga, takes place on November 15 at 1:00pm. Whether or not the time zone is about to change in November by 1 hour or not at all, people expect the event to happen that day at 1:00pm.
Teddy Bear Yoga was planned well in advance, so you entered it into your website content management system in early June:
This date and time is stored as a UNIX timestamp, which in early June, would have been calculated as 1794772800:
# Before the tzdata update
$ php -r "print strtotime( 'November 15, 2026 1:00pm' );"
1794772800
But something shocking happened when you loaded the event in July: the time changed!
Despite the province deciding there would be no more time changes, you now have an unexplained time change on your hands! If you output that timestamp now, you'll see that it shows as 2:00pm, even though nobody had edited the event:
<?php
print "\n";
$ts = 1794772800;
print "tzdata:\n";
print (new DateTimeImmutable('@'.$ts))
->setTimezone(new DateTimeZone('America/Edmonton'))
->format('Y-m-d H:i:s P T');
print "\n\n";
tzdata:
2026-11-15 14:00:00 -06:00 CST
On the front-end of the website, we had something even more confusing. The events calendar was displaying the wrong time:
… but the event page itself was displaying the correct time:
We'll get to the event page problem in the next section, but why was the back-end and events calendar showing the wrong time? A computer's logic considers this the right time, because the timestamp 1794772800 used to mean 1:00pm according to the old timezone rules, but it now means 2:00pm according to the new timezone rules. 1:00pm in the new timezone rules is actually represented by a different timestamp:
# After the tzdata update
$ php -r "print strtotime( 'November 15, 2026 1:00pm' );"
1794769200
Extra headache: another time zone database
Let's come back to the event page, which was still showing 1:00pm:
This appears to be correct, but is actually incorrect. Our Twig template code on that page uses the format_datetime() function:
{{ event.start.timestamp|format_datetime(locale=app.request.locale, pattern="h:mm aaa") }}
… and that function uses the ICU (International Components for Unicode) library, which has its own time zone database! That database has not been updated in a stock install of Ubuntu 24.
You can compare the output of a tzdata-formatted time and an ICU-formatted time as follows:
<?php
print "\n";
$ts = 1794772800;
print "tzdata:\n";
print (new DateTimeImmutable('@'.$ts))
->setTimezone(new DateTimeZone('America/Edmonton'))
->format('Y-m-d H:i:s P T');
print "\n\n";
print "ICU:\n";
print (new IntlDateFormatter( 'en_CA', IntlDateFormatter::NONE, IntlDateFormatter::NONE, 'America/Edmonton', IntlDateFormatter::GREGORIAN, 'yyyy-MM-dd HH:mm:ss Z z'
))->format($ts);
print "\n\n";
This confirms our problem:
tzdata:
2026-11-15 14:00:00 -06:00 CST
ICU:
2026-11-15 13:00:00 -0700 MST
The fix: what appears wrong is right, and what appears right is wrong
Our fix consisted of 2 parts: updating the code and manually reviewing all events that occurred after November 1, 2026.
Regarding the code, we created a new Twig function format_php_datetime() that is backwards compatible with format_datetime():
{{ event.start.timestamp|format_php_datetime(locale=app.request.locale, pattern="h:mm aaa") }}
… but it manually calculates the time zone offset:
// Express wall-clock as a UTC timestamp so ICU cannot re-apply zone rules
$wallClockUtcTs = $dt->getTimestamp() + $dt->getOffset();
$formatter = new IntlDateFormatter(
Locale::getDefault(),
IntlDateFormatter::NONE,
IntlDateFormatter::NONE,
'UTC',
IntlDateFormatter::GREGORIAN,
$pattern
);
$formatted = $formatter->format( $wallClockUtcTs );
We could have alternatively installed the "tzdata-icu" package, which tells ICU to source its time zone database from tzdata:
sudo apt install tzdata-icu
Now that the events were displaying consistent times across the different parts of the site, Teddy Bear Yoga was now universally displaying the wrong time of 2:00pm. We thought of creating a script to update all affected events. Such a script would have to consider at least the following:
- The boundary of dates for the affected events since only "standard time" time periods would be affected: between Nov X? 2026 and Mar X? 2027, between Nov X? 2027 and Mar X? 2028, between Nov X? 2028 and Mar X? 2029, and so on.
- Which events to update. Events published before the time zone database was updated would be affected, but is that reliable? What if an editor had noticed the difference and already made the fix? We could exclude events that had since been modified, but what if an editor had edited something else about the event and not the time?
- Event recurrence rules. Our system stores recurring event occurrences as time rules, not individual timestamps. So only recurring events with their first occurrence within "standard time" time periods would be affected.
Since a script's results would still have to be manually and carefully reviewed by editors, we decided that it was most reliable to not involve a script at all, and just have editors review all events occurring after November 1.
It's coming for us all
With the problem solved for affected BC and Alberta websites, it's a good time to start preparing in advance for other websites. After all, the USA is working towards permanent daylight savings time, which will likely spur other provinces like Ontario to do the same. Ontario already passed such an Act contingent on Quebec and New York joining in.
(A last note: digital skeptics might notice that no change is required to the printed event posters. Analog has its benefits!)

