Seems the most foolproof way to start with a UTC date is to create a new Date object and use the setUTC… methods to set it to the date/time you want.
Then the various toLocale…String methods will provide localized output.
Example:
// This would come from the server.
// Also, this whole block could probably be made into an mktime function.
// All very bare here for quick grasping.
d = new Date();
d.setUTCFullYear(2004);
d.setUTCMonth(1);
d.setUTCDate(29);
d.setUTCHours(2);
d.setUTCMinutes(45);
d.setUTCSeconds(26);
console.log(d); // -> Sat Feb 28 2004 23:45:26 GMT-0300 (BRT)
console.log(d.toLocaleString()); // -> Sat Feb 28 23:45:26 2004
console.log(d.toLocaleDateString()); // -> 02/28/2004
console.log(d.toLocaleTimeString()); // -> 23:45:26
Some references:
- toLocaleString
- toLocaleDateString
- toLocaleTimeString
- getTimezoneOffset
Seems the most foolproof way to start with a UTC date is to create a new Date object and use the setUTC… methods to set it to the date/time you want.
Then the various toLocale…String methods will provide localized output.
Example:
// This would come from the server.
// Also, this whole block could probably be made into an mktime function.
// All very bare here for quick grasping.
d = new Date();
d.setUTCFullYear(2004);
d.setUTCMonth(1);
d.setUTCDate(29);
d.setUTCHours(2);
d.setUTCMinutes(45);
d.setUTCSeconds(26);
console.log(d); // -> Sat Feb 28 2004 23:45:26 GMT-0300 (BRT)
console.log(d.toLocaleString()); // -> Sat Feb 28 23:45:26 2004
console.log(d.toLocaleDateString()); // -> 02/28/2004
console.log(d.toLocaleTimeString()); // -> 23:45:26
Some references:
- toLocaleString
- toLocaleDateString
- toLocaleTimeString
- getTimezoneOffset
You can do it with moment.js (deprecated in 2021)
It's best to parse your date string from UTC as follows (create an ISO-8601 compatible string on the server to get consistent results across all browsers):
var m = moment("2013-02-08T09:30:26Z");
Now just use m in your application, moment.js defaults to the local timezone for display operations. There are many ways to format the date and time values or extract portions of it.
You can even format a moment object in the users locale like this:
m.format('LLL') // Returns "February 8 2013 8:30 AM" on en-us
To transform a moment.js object into a different timezone (i.e. neither the local one nor UTC), you'll need the moment.js timezone extension. That page has also some examples, it's pretty simple to use.
Note: Moment JS recommends more modern alternatives, so it is probably not a good choice for new projects.
It's the same as those for the Intl.DateTimeFormat() constructor, whose MDN documentation provides a list of each valid property and an explanation.
The possible properties are as follows:
dateStyletimeStylecalendardayPeriodnumberingSystemlocaleMatchertimeZonehour12hourCycleformatMatcherweekdayerayearmonthdayhourminutesecondfractionalSecondDigitstimeZoneName
See the MDN documentation for the possible values of each property and the behavior.
interface DateTimeFormatOptions {
formatMatcher?: "basic" | "best fit" | "best fit" | undefined;
dateStyle?: "full" | "long" | "medium" | "short" | undefined;
timeStyle?: "full" | "long" | "medium" | "short" | undefined;
dayPeriod?: "narrow" | "short" | "long" | undefined;
fractionalSecondDigits?: 1 | 2 | 3 | undefined;
}
It looks like Chrome does not use the Windows regional settings, but its own settings instead. These are available via Settings > Advanced Settings > Language. However the date format is not explicitly defined, it is inferred from the language + country choice, for instance:
- English (US) sets date format to mm/dd/yyyy
- English (UK) sets date format to dd/mm/yyyy
(For anyone trying to change these, don't forget - like I did - to restart Chrome for the settings to take effect)
Back to the original question, it looks like it was legit to use toLocaleDateString() as long as the idea is to present the information in a format the human user understands. But this would be an ideal world, where every user has his/her browser properly configured. Instead, Chrome is set by default to English(US) as long as people leave it be in English, and it takes some googling (which most users won't do) to change these settings.
This makes it risky to use toLocaleDateString() even when not "relying on a particular format or locale". It looks like the only "serious" option for any cross-browser web application is to manage its own date format preferences (per user, of course...)
From the MDN:
"The exact format depends on the platform, locale and user's settings."
And,
"You shouldn't use this method in contexts where you rely on a particular format or locale."
Basically, "Why" is because that's how Chrome does it. If you need a specific format, you're going to have to specify it yourself.