New York’s clocks jump twice a year and your code breaks both times
From the second Sunday of March to the first Sunday of November the offset is UTC−4 (EDT). The rest of the year it is UTC−5 (EST). A developer who writes offset = -5 creates timestamps that are off by one hour for eight months. The error is invisible in logs that show only the time, until someone compares that time against a UTC event.
The US Department of Transportation sets the rules. The IANA tz database (zoneinfo) encodes them for software. Your code should never guess the offset.
Always use America/New_York
The IANA time zone name America/New_York covers the entire US Eastern Time region. It knows when DST starts and ends. It knows the historical rules (Indiana did not always observe DST). It knows future changes if the Sunshine Protection Act ever passes.
Use the name, not the offset. Every major language has a library for it:
- Python:
zoneinfo.ZoneInfo("America/New_York") - JavaScript:
Intl.DateTimeFormatwithtimeZone: "America/New_York" - Java:
ZoneId.of("America/New_York") - Ruby:
ActiveSupport::TimeZone["America/New_York"] - .NET:
TimeZone.getTimeZone("America/New_York")
The name works across regions. Toronto is America/Toronto. Port-au-Prince is America/Port-au-Prince. Cancún is America/Cancun. All share the same CLDR metazone as America/New_York, but using the correct city name avoids confusion if a region changes policy.
Never hardcode EST or EDT offsets
Hardcoding UTC−5 or UTC−4 breaks when DST transitions occur. Many systems default to "EST" when they mean "ET" or local time, propagating errors in logs. A server in July that logs "EST" is lying.
The fix: store the IANA name. Display the offset only at the moment of conversion. Let the library decide whether it is EST or EDT.
What goes wrong
A cron job runs at 02:30 local time every day. In March, that hour does not exist. If the job was scheduled with a hardcoded UTC−5 offset, it either runs at the wrong UTC time or fails. A library using America/New_York knows that 02:30 on 8 March 2026 is skipped.
Store UTC. Convert for display
Store everything in UTC. Convert to Eastern Time only for display. This rule prevents half of all time zone bugs.
NTP synchronizes computer clocks to UTC. Local time display is a conversion. If your database stores 2026-01-15T14:30:00-05:00, you have baked in the offset. If it stores 2026-01-15T19:30:00Z, you can display that instant in any zone without ambiguity.
The exception
Some systems must store local time: alarm clocks, calendar events for a specific location. In those cases, store the local time and the IANA zone name. Never store local time without the zone.
Converting UTC to Eastern Time
Take a UTC timestamp. Apply the IANA zone. Format.
Python example:
```python from datetime import datetime, timezone from zoneinfo import ZoneInfo
utc_dt = datetime(2026, 7, 15, 18, 0, 0, tzinfo=timezone.utc) et_tz = ZoneInfo("America/New_York") local_dt = utc_dt.astimezone(et_tz) print(local_dt) # 2026-07-15 14:00:00-04:00 ```
The library handles the offset. You do not check whether it is EDT or EST.
JavaScript example:
javascript
const date = new Date('2026-07-15T18:00:00Z');
const options = { timeZone: 'America/New_York', hour12: false };
console.log(new Intl.DateTimeFormat('en-CA', options).format(date));
// July 15, 2026 at 14:00:00
The missing hour: 8 March 2026
At 02:00 EST, clocks jump to 03:00 EDT. The hour 02:00 to 02:59 does not exist. If a user schedules a task for 02:30 on that day, what should happen?
- Some libraries throw an error.
- Some shift the time to 03:00.
- Some silently keep the time as 02:30 standard time (which is now 03:30 in EDT).
Your code must decide. The safest behavior: reject the time or shift forward. Never assume the user meant a time that does not exist.
The repeated hour: 1 November 2026
At 02:00 EDT, clocks fall back to 01:00 EST. The hour 01:00 to 01:59 occurs twice. Which one did the user mean?
- The first occurrence (EDT, UTC−4).
- The second occurrence (EST, UTC−5).
Most libraries use the first occurrence by default. If your application needs the second, specify fold=1 (Python) or use a disambiguation flag.
Unix timestamps are zone-free
Unix timestamps are UTC-based and time zone-independent. A timestamp is the same instant whether you are in New York, Tokyo, or London. Convert it to Eastern Time for display only.
Never store timestamps in Eastern Time. Never convert a timestamp to Eastern Time and store the result as a string. If you must store local time, store the UTC timestamp alongside it.
ISO 8601 with Eastern Time offsets
ISO 8601 format includes the offset. For 15 January 2026 at 14:30 in New York:
2026-01-15T14:30:00-05:00(EST)
For 15 July 2026 at 14:30:
2026-07-15T14:30:00-04:00(EDT)
The offset changes. The IANA zone name does not. When you serialize a timestamp, include the offset. When you parse it, use the offset to reconstruct the instant, then apply the zone.
Test these four points every year
- 8 March 2026, 01:59 EST → 03:00 EDT (spring-forward)
- 1 November 2026, 01:59 EDT → 01:00 EST (fall-back)
- A date in January (EST)
- A date in July (EDT)
Check that scheduled jobs run at the correct UTC time. Check that displayed times show the correct offset label (EST or EDT). Check that the repeated hour on fall-back is handled without data loss.
Common bugs and the fix
| Bug | Cause | Fix |
|---|---|---|
| Timestamps off by one hour in summer | Hardcoded UTC−5 instead of IANA zone | Use America/New_York |
| Scheduled job fails in March | Code unaware of missing hour | Use library that throws or shifts |
| Log shows "EST" in July | String literal for time zone name | Derive label from library |
| Repeated hour data overwritten | No fold disambiguation | Use fold flag or store UTC |
| Comparison across zones | Stored local time without zone | Store UTC + IANA zone name |