Skip to content(if available)orjump to list(if available)

RFC 3339 vs. ISO 8601

RFC 3339 vs. ISO 8601

152 comments

·September 7, 2025

mg

My favorite datetime format is "YYYY-MM-DD hh:mm:ss".

I consider it the "Markdown for time". It is human-friendly and computer-friendly at the same time. It is supported by many languages and databases. It is so elegant and common that even though it is not part of a standard, LLMs started to use it when writing answers:

Me: SQLite: Add 1 day and 3 hours to a date.

Perplexity: SELECT DATETIME('2025-09-07 07:51:00', '+1 day', '+3 hours');

progval

It is not computer-friendly because the timezone is unspecified. And in some timezones, it is ambiguous during changes from DST to winter time.

aaronbrethorst

Slap a Zulu on there for a little more safety and consistency. https://www.noaa.gov/jetstream/time

fauigerzigerk

Why is it not computer friendly? It's just a local time. This is something we need to be able to express in computers and in brains.

Things like opening hours or appointment times are always local time, and even if Apple disagrees I very strongly believe that alarm clocks should use local time as well.

danlitt

If local time is qualified with where "local" is then it is identical to using a time with a locale, like Europe/London or whatever. Unqualified local time is wrong/confusing the moment you have any requirement which crosses a time zone (which happens when you wouldn't expect it, that's the whole reason people care about this problem).

Even your example of alarms is not obvious. If you set a timer, or a daily alarm to wake up by, then yes. But if you set an alarm for some event, like sunrise for example, then you would need a zone.

pasc1878

Well is it a local time or not. If it is a local time where is it a local time?

You need a timezone as well.

Ekaros

Local time to where?

There is even more fun corner cases. Say you live at border of timezone. First have a meeting at 12:00 for 45 minutes in one zone, then move westward and now have an other meeting at 12:00. How do you mark these in calendar? Communicate them? Make historical log?

rini17

But if there's local DST change between today and tomorrow? Then naive calculation of "Add 1 day and 3 hours to a date." is wrong.

twelvedogs

If you put times in a database without timezone you will regret it

hdgvhicv

2025-11-02 01:30:00 in New York.

When does that happen.

SideburnsOfDoom

> It's just a local time.

It's potentially a local time, potentially not. It's unspecified and that will cause trouble.

If you want to model "stores open at 8:30am, worldwide" then there are data types for that "time only". They are not "date and time".

nine_k

Fair. But the point is that it follows the only reasonable order, consistently from larger units to smaller.

A datetime can be seen as a number written in a positional notation, just with varying base: divmod by 60, 60, 24, 12. When you pick a normal decimal / hex / binary number, you expect that the digits in it come in the order of magnitude changing: thousands, hundreds, tens, ones. Mixing them would feel crazy. By the same token, formats like dd-mm-yyyy HH:MM or mm-dd-yyyy are crazy; sadly they are traditional.

rocqua

Looking through the original article, this date format is only available in the RFC, and then only with the Z (which makes it UTC).

Is there a timezoned version of this that is standardized?

dijit

the number after the Z is the offset to UTC.

2025-09-07 10:57:00Z+2 would be CEST for example. (+2 hours ahead).

2025-09-07 04:57:00Z-4 would be EDT (4 hours behind UTC)

lmm

Specifying an offset, as certain datetime formats do, is worse than not specifying any timezone information at all. I'm not aware of a standardised computer date format that includes the symbolic timezone, sadly.

zarzavat

Agreed, offsets are an anti-pattern. Any time you have a nonzero offset you almost certainly want either a tz name (e.g. Europe/Paris), a local datetime, an instant, or a formatted string.

Datetime + tz name: a point in time and space that is responsive to time zone changes. E.g. Our zoom meeting is on 3 Feb 2026 17:40 in Moscow time.

Local date time: a calendar date that is independent of time zones.

Instant: an exact point in time. e.g. the rocket will launch at 123456789 seconds from the Unix Epoch TAI.

Formatted string: an exact point in time rendered for the human user in their local timezone and calendar, taking into account leap seconds. E.g. The rocket will launch on 7 Ramadan 1447 AH, Saudi time.

mg

Do you really need the timezone for each entry in the storage layer?

The application knows how it stores data, so it can just use UTC or whatever it likes. One timezone for all entries.

The interface then can display it in a way the user likes.

procaryote

Depends on what you need.

If you specifically only care about moments in time, throwing away the input time zone might be fine.

If the application is more human centric, timezones are often very useful as humans move around but often think about time as timezone-relative. A log of your daily activities would be confusing if a past event logged as 09:16:01 suddenly showed up as 07:16:01 because you're travelling when viewing it.

NAR8789

This sounds like a footgun.

At some point some application developer will introduce a bug where they're not sending utc.

Without the time zone, the wrong times will end up in the database, bad data mixed in with good. This will be a nightmare to fix.

With the time zone, I don't think this class of bugs is possible. Most application developers will wrap the time in an object that allows them to do time operations without needing to directly handle time zone in most cases.

creatonez

For timestamps/instants, sure you can just use UTC. But you cannot do human calendar math on instants, else you will ruin someone's entire day once you inevitably hit relatively common edge cases where civil time matters.

nine_k

From bitter experience: yes, having TZ-aware dates and times everywhere is helpful, and saves you more in (lack of) trouble than it costs in storage and "hassle".

isbvhodnvemrwvn

And then your country ditches/adopts the DST and you have angry customers because your app has messed up their future appointments.

GoblinSlayer

You need time zone to parse time.

zarzavat

Not all datetimes need a timezone. My next birthday is on November 17 2025 at 00:00 (it's not really). It's on that date regardless of where I am in the world, it follows me!

So yes, I agree a local datetime format is necessary but not sufficient.

xeonmc

It's also the Swedish time format I believe[0]

[0] https://stackoverflow.com/a/58633651

setopt

That and the metric system is why en_SE is my preferred locale even though I’m not Swedish or in Sweden

Kwpolska

Which decimal separator does it use? Windows’ "English (Sweden)" locale uses commas.

LukeShu

Except for not including a timezone offset, that's one of the RFC 3339 formats.

jolmg

> "YYYY-MM-DD hh:mm:ss"

> It is human-friendly and computer-friendly at the same time.

It's not shell-friendly, because of the space. The shell being an interface between humans and the computer, this takes a chunk out of it being human-friendly and computer-friendly. You'll have to worry about quoting the thing, involve messing with IFS when making arrays of the things, extract both pieces out of text columns aligned with spaces, awk's NF wouldn't correspond with number of fields anymore, etc. Would make timestamps unnecessarily annoying to interact with. Better to at least make it an underscore. Still quite readable.

magnio

Not exactly computer friendly, since filenames cannot contain ":" on Windows.

integralid

And cannot be longer than 8 characters on DOS.

afiori

Then replace it with _ or anything else it is going to be equally understandable

eadmund

Not all computers are Windows!

And not all computer-users worry even a little bit about compatibility with Windows.

theandrewbailey

Considering that most normie non-tech people use Windows, compatibility with Windows is important.

karambahh

Others point out missing tz.

It's also not that "user friendly": depending on their locale, users will usually expect for instance DD/MM/YYYY. Sorting by YYYY-MM-DD won't feel natural to them.

reacweb

I am french. Everydays, we use DD/MM/YYYY or DD/MM/YY. Sometimes, I encounter YYYY-MM-DD, for example at the beginning of a document reference or in a file name. For me, it feels natural and I have no issue to make this switch mentally. The only problem I encounter is in english: MM/DD/YYYY. Hopefully less and less people are using this insane order.

jolmg

> Sorting by YYYY-MM-DD won't feel natural to them.

It's dictionary sorting.

anfogoat

> It is so elegant and common that even though it is not part of a standard ...

YYYY-MM-DD hh:mm:ss seems valid ISO 8601 to me, isn't it? Neither the "T" nor the timezone are required as far as I recall.

EDIT: The site says ISO 8601-1:2019 requires a T for datetimes, and that even though previous editions allowed for no T, a space was never allowed. This is shocking news to me.

burntsushi

It's not elegant at all. This is a horrible idea because it doesn't account for time zone transitions. You could even end up with a time that will never appear on your clock.

For example, what is the answer to in New York?

    SELECT DATETIME('2025-03-07 23:30:00', '+1 day', '+3 hours');
If you said `2025-03-09 02:30:00`, then that would just be wrong. Because that time never appeared on clocks in New York.

mrinterweb

I don't think I realized how many alternative formats there are for both 3339 and 8601. Most of those alternative formats are redundant. I like that this chart shows the venn diagram of where these standards intersect.

drob518

Every programmer starts off thinking that dates and times are easy. “Just do …,” they’ll say. And then you realize that ISO 8601 has more than a few ways just to write down the time, let alone manipulate it. Dates and times are a very, very deep rabbit hole. Fortunately most of the time you can get by with just local dates and times or zoned dates and times.

mesrik

Anyone else find it odd that C99 strftime() %F and %T equivalents did not make it later revisions ISO 8601 and RFC 3339 ?

https://en.cppreference.com/w/c/chrono/strftime

Man page strftime shows,

%F Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99) %T The time in 24-hour notation (%H:%M:%S). (SU)

The Op linked page did not recognise these. I tried with the "%FT%T%z" which works fine with date and strftime().

I've probably used %F and %T about 20 years with no issues linux, bsd and mac that I wrote code over the years.

BTW, It would be nice to see some reference or comparison how systems stdlib implementations match with these standards if there is one.

One gripe I've got with RFC3999 and it's not nice to have the semicolon in filename if you intend to use it file or directory name. As it conflicts and easily becoome issue when not quoted while using rsync or any command that thinks colon (:) separates and indicates host name. I'm not sure if colon would cause issues with windows but there is chance it could as it's used indicating device name.

ps. I had to implement many stdlib time.h defined functions my own between -89 - 92 for my then work as Turbo C 2.0 and 3.0/3.1 did not implement these. I recall that last time I touched these and fixed issues was when I got P.J. Plaugers The Standard C Library book when it was brand new -92. When earlier proprietary C-compliers libraries sources had not been available, that Plaugers book was was great help for many :)

tliltocatl

Everything that isn't MDY is ok. MDY - burn in hell.

mceachen

You need to scroll that table: 8601 has so so many formats that are just as worthless without context as MDY. %C or %h%m are egregious.

tliltocatl

What makes MDY special is that it is worthless even with its normal context yet still widely used.

Those you mention make perfect sense in context: %C is usefull for historians (would you rather be parsing roman numbers?) and %h%m is good for voice radio transmission. Ideally you want to tag a format so that you have context, but I guess that's a bit difficult to do without introducing localization. It's somewhat akin to the issues with less common script in Unicode - yes, those are somewhat weird, but they do have a purpose. The standard tries to encompass every usecase rather than take a YAGNI approach, which is a sensible (if opinionated) thing to do.

On the contrary, MDY would appear in the same context you would expect DMY or YMD. It's only supposed advantage is that it maps English word order. But it is unsortable without parsing.

thayne

My main complaint about RFC 3339 is it doesn't have anything for specifying a duration/period or ranges.

bpavuk

fun fact - ATProto requires you to store all the datetime strings in a format that's compliant with both RFC 3339 and ISO 8601 plus you cannot specify time without date.

when I worked on datetime portion of Katproto, I had this link pinned for quite some time as a reference! ah, nostalgia...

also, post factum, I find this technical decision actually good - instead of supporting all possible variations of ISO 8601 or all the variations of RFC 3339, why not just support the intersection? that way, the format will be parseable by anything compliant with any standard of these two, and you only need to handle a very small set of branches.

01HNNWZ0MV43FF

The difference is that `date`, the command, and `chrono` the Rust crate implement RFC 3339, so we don't need to worry about ISO :)