Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if user's locale is set to 12-hour or 24-hour timeformat using javascript

how to check whether the user is using 12hr or 24hr time format using Javascript with or without using 3rd party library like moment.js I also tried new Date().toLocaleString() but it is not working tested in firefox and google chrome. firefox always shows 12hr format and chrome always shows 24hrs time format

like image 401
JAGAN Avatar asked Oct 13 '25 09:10

JAGAN


2 Answers

@Marko Bonaci's answer was helpful. I researched his comment "I'm not sure whether AM/PM designation (whichever characters are used) is at the end of the output for all locales." A Google search listed this link stating a user's comment:

The Latin abbreviations a.m. and p.m. (often written "am" and "pm", "AM" and "PM", or "A.M." and "P.M.") are used in English, Portuguese (Brazilian) and Spanish. The equivalents in Greek are π.µ. and µ.µ. respectively.

This can be verified from the browser's console using the two letter ISO 639-1 code "el" or the three letter ISO 639-2 code "ell":

new Intl.DateTimeFormat(["el"], { hour: "numeric" }).format();
// or
new Intl.DateTimeFormat("ell", { hour: "numeric" }).format();

These lines will return a value with the localized "AM"/"PM" string:

'7 π.μ.'
'7 μ.μ.'

I ended up using his suggestion using the built-in 'Number' object in JavaScript.

// UK english
Number.isInteger(Number(new Intl.DateTimeFormat("en-UK", { hour: "numeric" }).format()));
// Returns 'true'

// Greek
Number.isInteger(Number(new Intl.DateTimeFormat("el", { hour: "numeric" }).format()));
// Returns 'false'

// U.S.
Number.isInteger(Number(new Intl.DateTimeFormat("en-US", { hour: "numeric" }).format()));
// Returns 'false'

Here's my function with comments:

const isBrowserLocaleClockType24h = (languages) => {
    // "In basic use without specifying a locale, DateTimeFormat
    // uses the default locale and default options."
    // Ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_datetimeformat
    // To be sure of the browser's language (set by the user
    // and may be different than the operating system's default language)
    // set the 'languages' parameter to 'navigator.language'.
    // E.g. isBrowserLocaleClockType24h(navigator.language);
    if (!languages) { languages = []; }

    // The value of 'hr' will be in the format '0', '1', ... up to '24'
    // for a 24-hour clock type (depending on a clock type of
    // 'h23' or 'h24'. See:
    // developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale
    // Intl.Locale.prototype.hourCycles
    // Returns an Array of hour cycle identifiers, indicating either
    // the 12-hour format ("h11", "h12") or
    // the 24-hour format ("h23", "h24").

    // A 12-hour clock type value has the format '7 AM', '10 PM', or
    // '7 π.μ.' (if the locale language is Greek as specified
    // by the two letter ISO 639-1 code "el" or 
    // three letter ISO 639-2 code "ell").

    const hr = new Intl.DateTimeFormat(languages, { hour: "numeric" }).format();

    // If there's no space in the value of the 'hr' variable then
    // the value is a string representing a number between and
    // can include '0' and '24'. See comment above regarding "hourCycles".
    // Return 'true' if a space exists.
    //if (!hr.match(/\s/)) { return true; }
    // Or simply:
    // return !hr.match(/\s/);

    // Alternatively, check if the value of 'hr' is an integer.
    // E.g. Number.isInteger(Number('10 AM')) returns 'false'
    // E.g. Number.isInteger(Number('7 π.μ.')) returns 'false'
    // E.g. Number.isInteger(Number('10')) returns 'true'
    return Number.isInteger(Number(hr));
};

Usage:

const isBrowserLocaleClock24h = isBrowserLocaleClockType24h();
// or
const isBrowserLocaleClock24h = isBrowserLocaleClockType24h(navigator.language);

Using Intl.Locale().hourCycles

Lastly, for much newer browser's (except Firefox as of Dec 2022), there's new Intl.Locale(navigator.language).hourCycles listed on MDN.

// developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some#checking_whether_a_value_exists_in_an_array
const hourCycles = new Intl.Locale(navigator.language).hourCycles;
const isBrowserLocale24h = ["h23", "h24"].some(hourCycle => hourCycles.includes(hourCycle));

From

The Intl.Locale.prototype.hourCycle property is an accessor property that returns the time keeping format convention used by the locale.

There are 2 main types of time keeping conventions (clocks) used around the world: the 12 hour clock and the 24 hour clock. The hourCycle property makes it easier for JavaScript programmers to access the clock type used by a particular locale.

like image 191
Dave B Avatar answered Oct 15 '25 00:10

Dave B


Mario Bonaci's answer didn't work as expected for me though it pointed me to the right direction. Here's what I tried at first:

/*
 * Detects navigator locale 24h time preference
 * It works by checking whether hour output contains AM ('1 AM' or '01 h')
 */
const isBrowserLocale24h = () =>
  !new Intl.DateTimeFormat(undefined, { hour: "numeric" })
    .format(0)
    .match(/AM/);

It didn't work as expected as it apparently takes the browser's install language and not the user preferred language. Changing the undefined to navigator.language did the trick. Here, we're checking the time format based on the user's preferred language:

/*
 * Detects navigator locale 24h time preference
 * It works by checking whether hour output contains AM ('1 AM' or '01 h')
 * based on the user's preferred language
 */
const isBrowserLocale24h = () =>
  !new Intl.DateTimeFormat(navigator.language, { hour: "numeric" })
    .format(0)
    .match(/AM/);
like image 22
Yassine Doghri Avatar answered Oct 15 '25 00:10

Yassine Doghri