After spending something like ten years building systems which tracked and planned physical operations I had an insight that finally allowed me to understand date/time problems:
Time is relative to somewhere on Earth. To know when something happens, you have to know where. There is no such thing as time in the abstract
Metaphysical philosophy might take issue with this, but I am not a metaphysicist, just a software engineer. Following this rule, in my experience, helps to solve the many follow-on problems with datetimes, especially regarding time zones, duration calculations, and daylight savings time. More importantly, it helps me to simply think through the thorny datetime issues that arise while building applications that leverage datetimes (which is practically every application).
There are some other helpful rules of thumb that I follow:
Storing and Transmitting Datetime:
- Report events in the location where they happened
- Store and transmit datetime in ISO 8601 format with a consistent UTC timezone offset relative to the location or Zulu time (but choose one) e.g.,
2025-02-06T15:57:52.737-07:00
or2025-02-06T22:57:52.737Z
(these are the same datetime) - If the datastore cannot support ISO 8601, convert to Unix-epoch timestamps for the data store (but see below for TZ calculation rules)
- For timezone, use the location of the event you are tracking (if it happened in a physical place), otherwise choose a city (usually the HQ of the business) and convert all datetimes to the timezone of that city
- Don’t use ‘server time’, since this does not make sense in a distributed system and servers are often set to Zulu (zero-offset UTC)
These rules are for the human programmers trying to debug and maintain systems, not necessarily for the systems themselves. If all datetimes are in ISO 8601 with a consistent TZ offset, then it is much easier to understand traces and logs and answer questions bugs.
Displaying Datetime:
- Leverage your languages’ datetime libraries. Don’t roll your own
- Either display datetimes in a localized timezone or in the system timezone (e.g., the TZ of the business)
- Most importantly, always display datetimes with a timezone…
- and ideally a location too
- Localize the datetime display to the user’s location (but not necessarily the timezone)
Timezone calculations:
While thinking about timezones, use the general timezone identifier, e.g., “Eastern Time” instead of “Eastern Daylight Time” or “Eastern Standard Time”. Or even better, use the location-based identifier e.g., “America/New_York” (again, time is relative to location). Good datetime libs will correctly handle daylight savings time conversions depending on the time of year. Updates to daylight savings time do happen, and it’s important to keep libraries up-to-date to support this.
ICANN maintains the “tz database” which is should be the official source for timezone information for applications and contains the official location names. Any good datetime library should be up-to-date with this database.
Summary
To summarize, time is relative to location. Storing datetime in ISO 8601 with a consistent tz offset helps programmers understand the system and makes writing business logic, writing test cases, and reading logs much easier. Always display datetimes with a timezone. Leverage datetime libraries for conversions. If you store datetimes consistently and use general tz identifiers or location tz identifiers while using off-the-shelf library duration calculation functions, you don’t need to think about daylight savings or even leap days.