Skip to main content

JavaScript: Formatting ISO 8601 Complete Date-Time to a Readable One

Greetings!

The complete ISO 8601 date-time format is:

Breaking that down:

  • YYYY

    Four-digit year.

  • -MM

    Two-digit month (01–12).

  • -DD

    Two-digit day (01–31).

  • T

    Literal separator between date and time.

  • HH

    Two-digit hour (00–23, 24-hour clock).

  • :mm

    Two-digit minute (00–59).

  • :ss

    Two-digit second (00–59).

  • .sss

    three-digit millisecond.

  • Z

    Indicates UTC ("Zulu time").

    If you're using a specific offset instead, it'd be +HH:mm or -HH:mm in place of Z.

    "Zulu":

    UTC used to be referred to by the letter Z in navigation and military contexts, meaning "zero offset" from Greenwich. So Z for zero-offset time, spoken aloud as "Zulu" per the phonetic alphabet. Hence, "Zulu time" as an old military / aviation term for UTC, which is where the Z suffix in ISO 8601 timestamps ultimately traces back to.

    "Zulu" here has nothing to do with the Philippines, or even the Zulu people of Southern Africa, really.

    They could always use "zero", but nay, that was too mathematical. — We don't do that sort of jargon! Can't have anyone thinking too hard, best just borrow an entire nation's name instead of typing two syllables of maths.

    ðŸĪ” Yes, yes.

For example:

We can use toLocaleDateString to achieve that. "That" is the readable date format, I mean.

The syntax goes as such:

Let's break it down:

  • date

    That's a variable. We may name it other than that.

    The data type is Date instance. As in the output of new Date().

  • "BCP 47"

    BCP 47 is used as a locale identifier for toLocaleDateString.

    BCP stands for Best Current Practice, a persistent label used by the IETF (Internet Engineering Task Force) for a specific set of technical recommendations and guidelines.

    Some of them:

    1. en — English (generic)
    2. en-GB — English (UK)
    3. en-US — English (US)
    4. en-AU — English (Australia)
    5. en-CA — English (Canada)
    6. en-IE — English (Ireland)
    7. en-IN — English (India)
    8. en-NZ — English (New Zealand)
    9. en-ZA — English (South Africa)
    10. fr / fr-FR / fr-CA — French
    11. de / de-DE / de-AT / de-CH — German
    12. it — Italian
    13. es / es-ES / es-MX — Spanish
    14. pt / pt-PT / pt-BR — Portuguese
    15. nl / nl-NL / nl-BE — Dutch
    16. ja — Japanese
    17. zh / zh-CN / zh-TW / zh-HK — Chinese
    18. ko — Korean
    19. ru — Russian
    20. ar — Arabic
    21. hi — Hindi
    22. pl — Polish
    23. sv — Swedish
    24. da — Danish
    25. nb / no — Norwegian
    26. fi — Finnish
    27. tr — Turkish
    28. el — Greek
    29. he — Hebrew

    The 47 in BCP 47 is simply the sequential document number in the IETF's "Best Current Practice" series, NOTHING to do with a count of language tags at all.

    This is the IANA Language Subtag Registry. THOUSANDS of entries!

  • options

    It is an object to adjust the output of toLocaleDateString.

    Complete list:

    The weekday is the name of the day of the week. For example, Sunday, Monday, Tuesday, etc.

    While day is the numeric date of a particular month. 1, 2, 3, etc.

    The "long" value will output the complete word for that particular option. For instance, Tuesday (weekday) and September (month).

    The "short" value will output the locale's own commonly abbreviated form for a particular option. For instance using "en-GB", Tuesday = Tue (weekday), September = Sep (month), and 2026 = 26 (year).

    The "narrow" value will output the compact form for a particular option. For instance, Tuesday = T (weekday), and September = S (month). Though worth noting the clash there too: May, March, and several others could just as easily be M, and we'd get more than one month starting with the same letter (J for January, June, and July, for instance). So it is COMPACT but NOT unique. Just how it goes.

    The "numeric" value will output the numeric form for that particular option. For instance, 1, 2, 3, etc.

    The "2-digit" value will output the 0-padded numeric form for that particular option. For instance, 01, 02, 03, etc.

    Specifically for timeZoneName:

    • "long" — e.g. Greenwich Mean Time
    • "short" — e.g. GMT
    • "shortOffset" — e.g. GMT+1
    • "longOffset" — e.g. GMT+01:00
    • "shortGeneric" — e.g. UK Time
    • "longGeneric" — e.g. United Kingdom Time

    The timeZone:

    "Asia/Tokyo" / "Australia/Sydney" / "Europe/Paris" is IANA time zone identifier.

    IANA = Internet Assigned Numbers Authority.

    The list on Wikipedia.

    The others:

    • hour12

      true | false, forces 12-hour or 24-hour clock display.

    • hourCycle

      "h11" | "h12" | "h23" | "h24", finer control over hour cycling than hour12.

    • era

      "long" | "short" | "narrow", shows things like Anno Domini, AD, or A. Only works for certain calendar / locale combinations, often needs year set alongside it.

    • dayPeriod

      "long" | "short" | "narrow", shows AM/PM-style labels (e.g. "in the morning" for "long").

    • calendar

      Sets which calendar system to use ➡️ "gregory" | "buddhist" | "islamic" | "japanese", and so on.

    • numberingSystem

      For example, "latn" | "arab" | "hans", controls which digit characters get used.

      Indeed, latn — the shortened ISO 15924 script code for Latin, not the full word.

    • dateStyle

      "full" | "long" | "medium" | "short", a shorthand that auto-formats date parts. CANNOT be mixed with individual options like year/month/day.

    • timeStyle

      Same idea but for time parts, CANNOT mix with hour/minute/second either.

    Worth flagging: dateStyle / timeStyle are mutually exclusive with the individual field options (weekday, year, month, day, hour, minute, second) — we use ONE approach or the other, NOT both together.

Right. That's the introduction. Moving on with the JS snippets.


Simple Format

We may wrap the method in a function as such:

I'm using en-GB language tag. You can swap it to your own locale.

That function above only outputs: day month year.

Usage:

Snapshot from my console:

Simple format output

Or we can use the birthdate of Kublai Khan converted to a complete ISO date form — using Date object, which uses Gregorian calendar: 1215-09-23T00:01:15.000Z.

Birthdate of Kublai Khan with simple date output

Well, Kublai Khan's ghost would certainly:

What's Gregorian? Plonker?


Extended Format

Let's use more options. Something like so:

The usage is similar to the simple version but with the extended output.

Snapshot:

Birthdate of Kublai Khan with extended output

A Note for timeZoneName and timeZone

In summary:

  • timeZoneName set to "long" / "short" / "shortOffset" / etc. — controls how the zone's name gets displayed, and without an explicit timeZone set alongside it, that zone follows the OS's (or server's) own default.
  • timeZone set to an IANA identifier (e.g. "Europe/Paris") — overrides that default entirely, forcing the date to follow whatever zone you've specified instead.

What will happen if I use BOTH timeZoneName and timeZone?

Then they work together, mate. Just like the extended snippet above.

timeZone picks WHICH zone the date's calculated in, and timeZoneName decides how that zone's label gets DISPLAYED alongside it.


Great Leaders

Let's derail a bit since I brought Kublai Khan into this. To name a few others like Caesar, Alexander, Genghis, Gajah Mada, Napoleon.

I look at it as a force of nature. It's triggered or happened because of large populations, competing states, and the right conditions for one ambitious bloke to seize the moment. So essentially, the number of population.

It wouldn't happen if there were only three people existed.

Tim: Oi, Geoff. Get the woods.

Geoff: You're not the leader!

Sasha: Oi! Geoff, get some meat too!

Geoff: Oh, you melons!

⬆️ We can't be a "great conqueror" with a headcount of three, we're just the annoying one bossing Geoff about firewood. Empire-building requires scale, enough people that hierarchy, delegation, and "who's actually in charge here" becomes a genuine structural problem rather than just Tim being a bit much.


Thanks for visiting! ðŸŧ

Monkey Raptor uses cookies for analytics, advertisements, and functionality. Privacy Policy