Javascript -- Detect if user's locale are set to use 12-hour or 24-hour time format
As long as Chromium doesn't fix toLocaleString()
there is no way to do that in chromium.
For Firefox and IE parsing toLocaleString()
will give that information.
EDIT
Apparently toLocalString()
is now fixed in Chrome. The parsing of toLocaleString()
is therefore a solution.
You should never search for local pattern this way. toLocaleString()
is clearly a mistake (derived from Java) and should not be used. As you mentioned, this method is not well supported in various browsers (Chrome is just one of them).
In fact the only web browser (from popular ones) which get it about right (but not 100% right) is IE.
To correctly format date depending on Locale, please use Globalize. It contains localized patterns dumped out of .Net.
You may alternatively want to use Dojo which also allows Locale-aware formatting, but based on CLDR.
Edit, new facts exist
There is a new standard for I18n in JavaScript - ECMA-402. This standard in fact allows for using JS Date
's object. However, one should always pass a language tag:
var date = new Date();
var formatted = date.toLocaleString('de-DE');
The only problem with this is, the only web browser I am aware of that currently implements ECMA-402 is Google Chrome.
For now it seems that still the way to go is to use something along the lines of iLib.
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(undefined).resolvedOptions().hour12);
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);
The output from that should look like (for your browser's current locale; 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);
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);
It would be easy enough to wrap this in a function:
function localeUses24HourTime(locale) {
return new Intl.DateTimeFormat(locale, {
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 locale
console.log(localeUses24HourTime('en-US')); // a specific locale known to be false
console.log(localeUses24HourTime('ja-JP')); // a specific locale known to be true
You may find this more or less complicated than parsing the output of toLocaleString()
.