So I couldn't find a good answer for how to get a numeric date format in client-side JavaScript specific to the users locale. E.g. if your language is 'en-US' I would like to get 'MM/DD/YYYY'.
Asked
Active
Viewed 491 times
0
-
FYI, this question is specifically about getting the format _with_ placeholders as a string, not formatting dates. – Oscar Apr 12 '21 at 13:09
2 Answers
0
Date.toLocaleDateString
can be passed the options {year: 'numeric', month: '2-digit', day: '2-digit',}
to format a date in a numeric format that nearest matches the user's locale.
To get a date format with "YYYY", "MM" and "DD" placeholders, you can replace a specific year, month and day with the respective placeholder string.
// Replace with date format e.g. 'MM/DD/YYYY'
const FALLBACK_DATE_FORMAT = 'your fallback date format';
// Memoize return value
let cachedNumericFixedWidthDateFormat = null;
function getNumericFixedWidthDateFormat() {
if (cachedNumericFixedWidthDateFormat !== null) {
return cachedNumericFixedWidthDateFormat;
}
let dateFormat;
try {
const dummyDate = new Date();
dummyDate.setFullYear(1984);
dummyDate.setMonth(0);
dummyDate.setDate(23);
dateFormat = dummyDate.toLocaleDateString(undefined, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}).replace('1984', 'YYYY').replace('01', 'MM').replace('23', 'DD');
} catch (err) {
// TODO: Monitor errors!
return FALLBACK_DATE_FORMAT;
}
if (checkIsValidDateFormat(dateFormat)) {
cachedNumericFixedWidthDateFormat = dateFormat;
return dateFormat;
} else {
// TODO: Add monitoring!
return FALLBACK_DATE_FORMAT;
}
}
function checkIsValidDateFormat(dateFormat) {
const yearCharsMatches = dateFormat.match(/YYYY/g);
const monthCharsMatches = dateFormat.match(/MM/g);
const dayCharsMatches = dateFormat.match(/DD/g);
const digitCharMatches = dateFormat.match(/[0-9]/g);
return yearCharsMatches !== null && yearCharsMatches.length === 1
&& monthCharsMatches !== null && monthCharsMatches.length === 1
&& dayCharsMatches !== null && dayCharsMatches.length === 1
&& digitCharMatches === null;
}
// Output for Mozilla Firefox 87.0 on Ubuntu 20.04:
// en-US: 'MM/DD/YYYY'
// de-DE: 'DD.MM.YYYY'
// es-ES, es-AR, en-GB: 'DD/MM/YYYY'
console.log(getNumericFixedWidthDateFormat());

Oscar
- 11
- 3
-
*navigator.language* may or may not return the user's preferred language, and users may expect a format other than that associated with the returned language. Far better to use an unambiguous format. – RobG Apr 11 '21 at 20:45
-
Thanks for the info. Seems like a fair assessment :) It kind of sucks that there isn't any way of getting a format that is better tailored to the user's settings though – Oscar Apr 12 '21 at 12:30
-
@RobG I just found out that you can directly pass options to `Date.toLocaleDateString` eliminating the use of `navigator.language`. I haven't done enough research to tell you whether `toLocaleDateString` is reliable - it may have the same problems as `navigator.language` – Oscar Apr 12 '21 at 14:25
0
While it is very hard to determine the the locale of the user, we can determine the user's preferred languages and pass these to a Intl.DateTimeFormat()
constructor to create a date formatter.
Pass a Date
object to the format
function of the formatter to format the date to the pre-specified conditions.
// Function that returns an instance of the DateTimeFormat constructor.
const createDateFormatter = () => new Intl.DateTimeFormat([], {
year: '2-digit',
month: '2-digit',
day: '2-digit'
});
// Current date of today.
const date = new Date();
// Create a new formatter.
const dateFormatter = createDateFormatter();
// Format the date.
const formattedDate = dateFormatter.format(date);
console.log(formattedDate);

Emiel Zuurbier
- 19,095
- 3
- 17
- 32
-
-
Hmm, no not really. I've overlooked the empty array possibility. Though, because of your question I did find out about [locale negotiation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locale_negotiation), which is something new I've learned today. Though it doesn't apply to this situation as the `navigator.languages` might be the same as *the locales it has available* in the browser. – Emiel Zuurbier Apr 11 '21 at 21:13
-
Noting that the use of "locale" in regard to the Intl object is unfortunately confused with "language and culture" in [ECMA-402](https://www.ecma-international.org/publications-and-standards/standards/ecma-402/), it actually represents a language (and ignoring the common coexistence of more than one culture per language and place). I think the only reasonable use of *Intl.DateTimeFormat* is to get date parts in an appropriate language and calendar, then format them in an unambiguous order. Relying on the language with extensions to do that is fraught. – RobG Apr 12 '21 at 02:17
-
@RobG I was also initially hoping that the default would work. For some reason it didn't for me... it choose en-US even though I have en-GB set in my preferences – Oscar Apr 12 '21 at 12:28
-
i think if you just need a date formatted in the users preferred format then `toLocaleString` is the best solution. In this case I specifically needed the format with placeholders – Oscar Apr 12 '21 at 12:41