It's been a few years since this was last answered and a few technologies have been introduced to solve the issue. One such technology is Intl.DateTimeFormat
, which provides a wealth of information about date formats for various locales.
console.log(new Intl.DateTimeFormat().resolvedOptions());
console.log(new Intl.DateTimeFormat().resolvedOptions().hour12);
.as-console-wrapper { max-height: 100% !important; }
However, most locales don't define a default for the hour12
option. So, if this returns undefined
, I'd look at the formatToParts
function.
const hourParts = new Intl.DateTimeFormat(undefined, { hour: 'numeric' }).formatToParts(new Date(2020, 0, 1, 13));
console.log(hourParts);
.as-console-wrapper { max-height: 100% !important; }
The output from that should look like (for your browser's current language; in my case, "en-US"):
[
{
"type": "hour",
"value": "1"
},
{
"type": "literal",
"value": " "
},
{
"type": "dayPeriod",
"value": "PM"
}
]
Getting the length of the value
of the part with type
equal to "hour"
will tell you whether it was formatted with twelve or twenty-four hour time.
For instance, I happen to know that in Japan, they use twenty four hour time, so I can check that:
const hourParts = new Intl.DateTimeFormat('ja-JP', {
hour: 'numeric'
}).formatToParts(new Date(2020, 0, 1, 13));
console.log(hourParts.find(part => part.type === 'hour').value.length);
.as-console-wrapper { max-height: 100% !important; }
And I know the the US defaults to twelve hour time:
const hourParts = new Intl.DateTimeFormat('en-US', {
hour: 'numeric'
}).formatToParts(new Date(2020, 0, 1, 13));
console.log(hourParts.find(part => part.type === 'hour').value.length);
.as-console-wrapper { max-height: 100% !important; }
It would be easy enough to wrap this in a function:
function localeUses24HourTime(langCode) {
return new Intl.DateTimeFormat(langCode, {
hour: 'numeric'
}).formatToParts(new Date(2020, 0, 1, 13)).find(part => part.type === 'hour').value.length === 2;
}
console.log(localeUses24HourTime()); // undefined means current user's language
console.log(localeUses24HourTime('en-US')); // a specific language known to be false
console.log(localeUses24HourTime('ja-JP')); // a specific language known to be true
.as-console-wrapper { max-height: 100% !important; }
You may find this more or less complicated than parsing the output of toLocaleString()
.
Note: I switched from using the term "locale" to "language" midway through my answer. This is due to how the specification is written and how information is specified. en-US
and ja-JP
are BCP language codes, passed to the constructor of Intl.DateTimeFormat
to look up date and time formatting rules. The specification uses the term locale
to refer to this piece of information but indeed it is a language identifier, which, while it may contain a region (the US
and JP
in the mentioned codes), does not require them, nor does that region necessarily indicate the user's locale (consider a person who speaks Spanish and learned it in Spain [and therefore would use the language code 'es-ES'], but lives in the United States, where the dates are formatted differently than in Spain).