DateTime Programming Tips: Common Pitfalls and Solutions

May 27, 20266 min read

DateTime Bugs Are Silent Killers

DateTime errors rarely crash your app. Instead, they produce wrong data — scheduled emails sent at the wrong hour, expired tokens that still work, reports covering the wrong date range. These bugs are hard to catch in testing and expensive to fix in production.

Here are the most common pitfalls and how to avoid them.

Time Zone Pitfalls

Pitfall: Storing Local Time

# BAD — what timezone is this?
event_time = "2025-05-26 14:00:00"

# GOOD — always store in UTC
event_time = "2025-05-26T18:00:00Z"  # 2 PM EDT = 6 PM UTC

Rule: Store every timestamp in UTC. Convert to local time only when rendering to users. This eliminates ambiguity and makes arithmetic consistent.

Pitfall: Ignoring Offset in Parsing

// BAD — interprets as local time
new Date("2025-05-26T14:00:00")
// In New York: May 26, 10:00 AM EDT
// In Tokyo: May 26, 11:00 PM JST

// GOOD — explicit UTC
new Date("2025-05-26T14:00:00Z")
// Everywhere: May 26, 2:00 PM UTC

A timestamp string without a timezone offset means different things in different environments. Always include Z or an offset like +05:30.

Daylight Saving Time Issues

The Ambiguous Hour

When clocks fall back (e.g., 2:00 AM → 1:00 AM in autumn), the same local time occurs twice. Which one did the user mean?

2025-11-02 01:30:00 (first occurrence, EDT)
2025-11-02 01:30:00 (second occurrence, EST)

Solution: Use UTC internally. If you must accept local time, ask for the offset or use a timezone-aware library.

The Missing Hour

When clocks spring forward (e.g., 2:00 AM → 3:00 AM in spring), 2:30 AM never exists.

// In EDT→EST transition zones:
new Date("2025-03-09T02:30:00")  // jumps to 3:30 AM

Solution: Validate user-provided local times against DST transitions. Alert the user when a time does not exist.

Duration Calculations Across DST

Nov 1, 2025 1:00 AM EDT → Nov 2, 2025 1:00 AM EST
Elapsed: 25 hours (not 24)

Solution: Calculate durations in UTC or use wall-clock libraries that account for DST.

Leap Seconds

Leap seconds add or remove one second from UTC to keep it aligned with Earth's rotation. There have been 27 leap seconds since 1972.

2016-12-31T23:59:60Z  ← a valid UTC time

Most software ignores leap seconds. Unix timestamps skip them — each day is always 86400 seconds. This means:

  • Sub-second-precision applications may drift
  • High-frequency trading and scientific software must handle them explicitly
  • Web applications can usually ignore leap seconds safely

Serialization Best Practices

GuidelineDoDon't
API payloadsUse ISO 8601 with offsetSend local time without offset
DatabasesStore as UTC timestamp or timestamptzStore as local time without zone
JSON"2025-05-26T18:00:00Z""05/26/2025 6:00 PM"
Filenames & logs2025-05-26T18-00-00Z.logMay 26th.log
User-facingConvert to local format at renderShow raw UTC to users

Consistency wins. Pick one format, document it, and enforce it across your entire stack.

Testing Strategies

Freeze Time in Tests

// Use a mock or library to set a fixed "now"
vi.setSystemTime(new Date("2025-05-26T12:00:00Z"))

Test DST Boundaries

Write tests for:

  • Times during the spring-forward gap
  • Times during the fall-back overlap
  • Midnight crossing in different time zones
  • Week-long calculations that span a DST change

Test Edge Cases

  • February 29 (leap year)
  • December 31 → January 1 (year boundary)
  • Timestamp 0 (Unix epoch)
  • Very large timestamps (beyond 2038)
  • Negative timestamps (before 1970)
LanguageLibraryWhy
JavaScriptdate-fnsModular, tree-shakable, immutable
JavaScriptdayjsLightweight, moment-compatible API
Pythonzoneinfo + datetimeBuilt-in, no extra dependency
Gotime packageStdlib, handles zones and parsing
Javajava.time (JSR 310)Modern, immutable, timezone-aware
RubyTZInfo + TimeFull IANA timezone database
PHPDateTimeImmutableBuilt-in, handles DST correctly

Avoid: moment.js (deprecated), Python pytz (replaced by zoneinfo), any library that mutates objects in place.

Quick Checklist

  • All timestamps stored in UTC
  • API responses include timezone offsets
  • DST transitions handled in scheduling logic
  • Duration calculations use UTC, not local time
  • Tests cover timezone boundaries and leap years
  • No deprecated datetime libraries in dependencies

Try It Yourself

Use our free Timestamp Converter to verify your timestamp conversions and catch timezone issues before they reach production.