Daylight Saving Time: A Developer's Guide
How DST works, why it creates bugs, and the patterns that protect your software from time change chaos.
Why DST Is a Developer's Problem
Daylight Saving Time (DST) is the practice of advancing clocks by one hour during warmer months to extend evening daylight. For most people, DST means adjusting a clock twice a year. For developers, it means a category of bugs that are intermittent, hard to reproduce, and affect every system that touches dates and times.
Every DST transition creates two anomalies: a skipped hour in spring and a repeated hour in fall. If your code assumes that every day has 24 hours, that local times are unique, or that the difference between two timezones is constant, DST will eventually prove you wrong. This guide covers what happens during DST transitions and how to write code that handles them correctly.
What Happens During a DST Transition
Spring Forward (Gaining DST)
When DST begins (typically in March for the Northern Hemisphere), clocks jump forward by one hour. In the US, at 2:00 AM local time, clocks advance to 3:00 AM. The times between 2:00 AM and 2:59 AM never happen on that day. The day has only 23 hours.
This creates invalid local times. If a user schedules a meeting for 2:30 AM on the spring transition date, that time does not exist. Your software needs to detect this and either reject the input, shift it to the next valid time (3:00 AM), or warn the user.
Fall Back (Losing DST)
When DST ends (typically in November for the Northern Hemisphere), clocks fall back by one hour. At 2:00 AM, clocks go back to 1:00 AM. The times between 1:00 AM and 1:59 AM occur twice on that day. The day has 25 hours.
This creates ambiguous local times. A log entry timestamped "1:30 AM" on the fall transition date could refer to either the first or second occurrence. Without storing the UTC offset or using UTC timestamps, you cannot distinguish between them.
DST Transition Dates Vary by Region
There is no universal DST date. Different countries and even regions within countries transition on different dates:
- United States and Canada: Second Sunday of March (spring forward), first Sunday of November (fall back)
- European Union: Last Sunday of March, last Sunday of October
- Australia: First Sunday of October (spring forward), first Sunday of April (fall back) -- remember, seasons are reversed
- Brazil: Abolished DST in 2019
- Russia: Abolished DST in 2011 (stayed on "permanent summer time" until 2014, then switched to permanent standard time)
- China, Japan, India, South Korea: Do not observe DST
This means the UTC offset difference between two cities changes depending on the date. New York and London are 5 hours apart in winter but only 4 hours apart during the period when the US has switched to DST but the UK has not yet. For 2-3 weeks each spring and fall, the offset between many city pairs is different from its "usual" value. Our Meeting Planner accounts for this automatically.
Common DST Bugs and How to Avoid Them
Bug: Adding 24 Hours Instead of 1 Day
If you compute "tomorrow" by adding 86,400 seconds (24 hours) to the current time, you will be off by one hour on DST transition days. On a 23-hour day, adding 24 hours pushes you into the day after tomorrow. On a 25-hour day, you land at 11 PM the same day.
Fix: Use calendar-aware date arithmetic. In JavaScript, set the date component directly:
// Wrong: adding 24 hours
const tomorrow = new Date(now.getTime() + 86400000);
// Right: incrementing the date
const tomorrow = new Date(now);
tomorrow.setDate(tomorrow.getDate() + 1);Bug: Assuming Fixed Offset Between Timezones
Hardcoding const NYC_TO_LONDON_OFFSET = 5 works most of the year but breaks during the transition gap. London and New York switch DST on different dates, creating weeks where the offset is 4 or 6 instead of 5.
Fix: Always convert through UTC. Store timestamps in UTC, convert to local time for display using the IANA timezone database, and let the library handle the offset calculation for the specific date.
Bug: Cron Jobs That Run Twice or Not at All
A cron job scheduled for 2:30 AM will not run on the spring transition day (that time does not exist) and will run twice on the fall transition day (that time occurs twice). This is one of the most common DST bugs in production systems.
Fix: Schedule critical jobs in UTC. If the job must run at a local time, choose a time that is not affected by DST transitions (e.g., noon). Use cron implementations that are DST-aware. See our Cron Builder for scheduling help.
Bug: Duration Calculations Across DST
If you calculate the duration between two local times that span a DST transition, the result will be off by one hour unless your date library is DST-aware. "From 1:00 AM to 3:00 AM on the spring transition" is 1 hour, not 2.
Fix: Convert both timestamps to UTC before computing the duration. In UTC, the difference is always correct.
DST in JavaScript
JavaScript's Date object is always internally UTC but displays in the browser's local timezone. The Intl.DateTimeFormat API handles DST correctly when given an IANA timezone:
// Get the UTC offset for a specific date and timezone
function getUTCOffset(date, timezone) {
const formatter = new Intl.DateTimeFormat('en', {
timeZone: timezone,
timeZoneName: 'longOffset',
});
const parts = formatter.formatToParts(date);
const offsetPart = parts.find(p => p.type === 'timeZoneName');
return offsetPart?.value; // e.g., "GMT-05:00" or "GMT-04:00"
}
// Check if DST is in effect
function isDST(date, timezone) {
const jan = new Date(date.getFullYear(), 0, 1);
const jul = new Date(date.getFullYear(), 6, 1);
const janOffset = getUTCOffset(jan, timezone);
const julOffset = getUTCOffset(jul, timezone);
const currentOffset = getUTCOffset(date, timezone);
// In Northern Hemisphere, summer offset is greater (less negative)
return currentOffset !== janOffset && currentOffset === julOffset;
}The Future of DST
There is growing momentum to abolish DST. The European Union proposed ending seasonal clock changes starting in 2021 (delayed indefinitely). The US Senate passed the Sunshine Protection Act in 2022 to make DST permanent (it stalled in the House). Several US states have passed legislation to adopt permanent DST pending federal approval.
If DST is abolished, it will not simplify timezone handling overnight. The IANA database will still need historical DST data for past dates, and different regions may choose different "permanent" offsets. The fundamental advice remains the same: store UTC, convert at display time, and use IANA timezone identifiers.
Try It Yourself
Use our Timezone Converter to see how DST affects conversions. Try converting a time on March 10, 2024 (US spring forward) vs March 9, 2024 and observe how the offset changes. The Meeting Planner shows this visually by highlighting hours where DST transitions affect overlap.
Further Reading
- Daylight Saving Time — Wikipedia
Comprehensive history and current status of DST worldwide.
- Falsehoods Programmers Believe About Time
Classic list of incorrect assumptions about time that lead to bugs.
- IANA Time Zone Database
The authoritative database encoding all DST transition rules for every timezone.
- DST Worldwide — timeanddate.com
Interactive map and per-country reference for current DST transition dates worldwide.
- W3C Date and Time Formats
W3C note on ISO 8601 date/time profiles for web standards, including offset representation.