Date, Time Formats, and Timezones in JSON APIs

2022-08-23 - 6 min read

When designing APIs, the data format must be clear and unambiguous. This is especially true for date, time and timezone formats. History brought complexity to the concept of time, which we'll explore in the article.

The Unix Epoch

The most straightforward representation (at least technically) of the date and time is the UNIX timestamp, which is the number of seconds since the UNIX epoch on the 1st of January in 1970, at 00:00 UTC. It's cheap in terms of storage and sortable, but it isn't very user-friendly. An example is 1661176010. Can you tell me what time it is?

Date and Time Calculations

You might be tempted to use the UNIX timestamp for simple date calculations. We can add an hour by adding 3600 to it. It couldn't be much easier. However, what would you do when you need to add one day? That leads to another question: how many seconds are there in one day? Most days have 86400 seconds, but there are, in fact, six possibilities due to daylight saving time (DST) and leap seconds (although a 23/25 hour day with a leap second is unlikely).

A Legacy of War and Oil Shortage

While leap seconds have a scientific origin, daylight saving time has been introduced and canceled for various political reasons. The first country to adopt DST was Germany in 1916, during the first world war. Many European countries followed quickly after that. In North America, it started with the Uniform Time Act of 1966. At the time of writing, 74 countries have adopted daylight saving time, mainly in Europe and North America. Each continent has at least one country with and one country without DST. Even the United States isn't consistent because Hawaii and Arizona do not observe DST. The adoption worldwide was subject to many changes. Most European countries abandoned DST after the second world war but reintroduced it during the oil crisis in the late 1970s. In 2018, the European Union decided to scrap DST in 2021, but that didn't happen to date cause of Brexit and ongoing debate.

What Railroads Have to Say

A few centuries back, you shouldn't be surprised that each city had its own timezone. The railroad services are often credited for the introduction of a standard time. The U.S. introduced standard time in 1883 because the railroads demanded more uniformity.

Nowadays, at least most territories use timezones that are whole hours before or after UTC. Still, there are some exceptions. For example, India is at +5:30, while Nepal is at +5:45 only to differentiate from India.

The API and the Data of a Date

What does all this chaos have to do with APIs? Well, the date and time formats specified in an API can profoundly impact how that API is used and how compatible it is with other systems. We need a format for dates and times that can be accepted globally, is resistant to the political effects described above, and is technically universal.

We've discussed the concepts of DST and timezones. That brings us to the question of what data we want to store. Let's consider the following dates:


All dates refer to the same moment, but are they all in the evening? To answer that question, you need the timezone of the question's context. Three of the four dates clearly contain a time zone. The first uses the "Z”, sometimes called "Zulu time”, which is UTC. This notation is often used to indicate a time without a time zone.

Many systems save all dates in UTC, which has the advantage that you can use lexical ordering to sort the dates. However, the timezone of the user can be a valuable detail. In the example above, precisely that detail allows us to answer which dates are in the evening. Not every use case requires a timezone or even a time. Therefore, the timezone and time are optional, and maybe the date too.

The ISO8601 standard

The most well-known standard nowadays is ISO8601. The examples above are in this format. However, this standard caters to much more use cases, such as specifying a week ("2022W34”) or specifying a date without a year (" — 08–22”). Many APIs, however, cannot (and should not) accept " — 08–22” as a valid date. Therefore, mandating ISO8601 is not enough because we likely only support a subset of it.

Date and Time on the Internet

RFC 3339, titled "Date and Time on the Internet: Timestamps”, defines a subset of ISO8601 in section 5.6. The formats they named full-date, full-time, and date-time are widely accepted and adopted by JSON Schema formats as date, time, and date-time, respectively. Likewise in XML Schema, these are known as xs:date, xs:time, and xs:dateTime. So, RFC 3339 is highly recommended for APIs, especially given their adoption in both XML and JSON standards.


The ISO8601 format starts with the most significant units. That avoids the confusion between date formats commonly used in the U.S. (month/day/year) and Europe (day/month/year). For example, the date 01–02–2022 will be interpreted differently and hence must be considered an anti-pattern. For dates in APIs, it's best to avoid local formatting and stick with a global standard.

Another anti-pattern is to use more detail than needed. For example, some APIs return dates as a full date-string, where "T00:00:00Z” is always appended to the date. It only adds confusion if it, in fact, only contains a date and not a time.

Quick Overview of Date and Time standards

The table below briefly references the date and time standards, with some examples.

Date that complies with ISO8601, RFC3339, JSON Schema date, and XML Schema xs:date:


Date and time that complies with ISO8601, RFC3339, JSON Schema date-time, and XML Schema xs:dateTime:


Date and time that complies with ISO8601, RFC3339, JSON Schema date-time, and XML Schema xs:dateTime:


Time that complies with ISO8601, RFC3339, JSON Schema time, and XML Schema xs:time:


Notations that comply with ISO8601 but not with RFC3339:

 — 12–31

RFC 2822 (e-mail) dates:

2 Jan 2022
2 Jan 2022 23:59
2 Jan 2022 23:59:59
2 Jan 2022 23:59:59 +0200
2 Jan 2022 23:59 +0200
Sun, 2 Jan 2022 23:39:39

Handling dates in Flowlet

In Flowlet, we adopted the Luxon library for handling dates. This library makes it easy to compute a date without the hassle of handling daylight saving yourself. To get the timestamp of tomorrow in ISO8601 / RFC3339 date-time format, you can use:
 .plus({day: 1})

Want to solve your API integration issues using Flowlet?