Greetings!
The complete ISO 8601 date-time format is:
Breaking that down:
-
YYYYFour-digit year.
-
-MMTwo-digit month (01–12).
-
-DDTwo-digit day (01–31).
-
TLiteral separator between date and time.
-
HHTwo-digit hour (00–23, 24-hour clock).
-
:mmTwo-digit minute (00–59).
-
:ssTwo-digit second (00–59).
-
.sssthree-digit millisecond.
-
ZIndicates UTC ("Zulu time").
If we're using a specific offset instead, it'd be
+HH:mmor-HH:mmin place ofZ."Zulu":
UTC used to be referred to by the letter
Zin navigation and military contexts, meaning "zero offset" from Greenwich. SoZfor 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 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:
Now, the formatting method.
We can do either:
- the JS string
.split()and such, - or directly employ
.toLocaleDateString().
Let's simply use toLocaleDateString to achieve that. "That" is the readable date / date-time format, I mean. Option number two. Since option number one would seem like we were taking a long scenic detour.
Right. toLocaleDateString, the syntax goes as such:
Let's break it down:
-
dateThat's a variable. We may name it other than that.
The data type is
Dateinstance. As in the output ofnew 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:
en— English (generic)en-GB— English (UK)en-US— English (US)en-AU— English (Australia)en-CA— English (Canada)en-IE— English (Ireland)en-IN— English (India)en-NZ— English (New Zealand)en-ZA— English (South Africa)fr/fr-FR/fr-CA— Frenchde/de-DE/de-AT/de-CH— Germanit— Italianes/es-ES/es-MX— Spanishpt/pt-PT/pt-BR— Portuguesenl/nl-NL/nl-BE— Dutchja— Japanesezh/zh-CN/zh-TW/zh-HK— Chineseko— Koreanru— Russianar— Arabichi— Hindipl— Polishsv— Swedishda— Danishnb/no— Norwegianfi— Finnishtr— Turkishel— Greekhe— 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!
-
optionsIt is an object to adjust the output of
toLocaleDateString.Complete list:
The
weekdayis the name of the day of the week. For example, Sunday, Monday, Tuesday, etc.While
dayis 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, usingen-GBlanguage tag — Tuesday = Tue (weekday), September = Sept (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 example. 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.The
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 (tz identifier or TZ identifier).IANA = Internet Assigned Numbers Authority.
The list on Wikipedia.
Or we can use the latest database release from IANA.
The others:
-
hour12true | false, forces 12-hour or 24-hour clock display. -
hourCycle"h11" | "h12" | "h23" | "h24", finer control over hour cycling thanhour12. -
era"long" | "short" | "narrow", shows things likeAnno Domini,AD, orA. Only works for certain calendar / locale combinations, often needsyearset alongside it. -
dayPeriod"long" | "short" | "narrow", shows AM/PM-style labels (e.g."in the morning"for"long"). -
calendarSets which calendar system to use ➡️
"gregory" | "buddhist" | "islamic" | "japanese", and so on. -
numberingSystemFor 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 likeyear/month/day. -
timeStyleSame idea with
dateStylebut for time parts. CANNOT mix withhour/minute/secondeither.
Specifically for
dateStyleandtimeStyle. Worth flagging: they 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 to 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 the readable date string: "day month year".
Usage:
Snapshot from my console:
Or we can use the birthdate of Kublai Khan converted to a complete ISO date-time string — using new Date() and .toISOString().
His birthdate is 23 September 1215 in Gregorian calendar. But we flip it first so it adheres ISO 8601 format: YYYY-MM-DD — to avoid the funny business JS has.
And so: 1215-09-23. Thus:
So let's use 1215-09-23T00:01:15.000Z.
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:
About that GMT-0:01:15 offset or the 00:01:15.000Z part. As you can see, it has the minute-and-second precision.
In general — every location recorded in the IANA tz (timezone) database carries its own pre-standardisation LMT (Local Mean Time) offset, derived precisely from that location's longitude, producing odd minute-and-second precision rather than clean hours. Each place then transitions to a standardised, rounder offset at its own historical cutover date, whenever that particular region formally adopted standard time — dates that vary from place to place, not a single global year.
Britain's railway companies began adopting a standardised time in the 1840s, informally converging on it over that decade, though the change was not made law nationwide until the Statutes (Definition of Time) Act in 1880.
Kublai Khan's birthyear — 1215 — is prior to that standardisation year — 1880...ish — thus any date calculation involving London's timezone for that year falls back to the pre-standardisation LMT offset recorded in the tz database, rather than the clean, modern UTC+0.
Note: the tz database itself openly states that most of its pre-1970 timestamps — including LMT offsets like London's — may be wrong or misleading, being best-effort reconstructions rather than verified historical fact.
⬆️ Is it confusing? I hope not. But it is confusing. Right. Moving on.
A Note for timeZoneName and timeZone
In summary:
-
timeZoneNameis set to"long"/"short"/"shortOffset"/ etc.It controls how the zone's name gets displayed.
Without an explicit
timeZoneset alongside it, that zone follows the OS's (or server's) own default. -
timeZoneis set to an IANA identifier / tz identifier (e.g."Europe/Paris").It overrides the default entirely, forcing the date to follow whatever zone we have specified instead.
ð What will happen if I use both timeZoneName and timeZone?
Didn't I just show you that?
ð AGAIN! Please.
Very well. Then they work together.
timeZone picks which zone the date's calculated in, and timeZoneName decides how that zone's label gets displayed alongside it.
ð Ah.
Quite.
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 it naturally happens because of large populations, competing states, and the right conditions for one ambitious bloke to seize the moment. So first, 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.
ðĪ
Here's the thing — one afternoon of being bossed about firewood is just mild annoyance, but give it a decade of Geoff quietly becoming the only one who actually knows where the good hunting grounds are, how to track, how to build a proper shelter, while Tim and Sasha never learnt a thing beyond barking orders... that's when the power genuinely inverts.
Knowledge and skill, compounded over time, is precisely how the "underling" becomes the "indispensable one" — though it takes one more ingredient, ambition, to turn that into the one giving orders instead of taking them.
And the cycle carries on.
Geoff: Oi, Tim. Get the water!
And I just contradict myself.
Meet Geoff, the Conqueror of the Three-Person Woodland Commune.
Thanks for visiting! ðŧ


