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.DateTimeFormat with timeZone: "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

  1. 8 March 2026, 01:59 EST → 03:00 EDT (spring-forward)
  2. 1 November 2026, 01:59 EDT → 01:00 EST (fall-back)
  3. A date in January (EST)
  4. 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