Date.prototype.toLocaleString()
Formats both date and time using a locale's conventions, with optional time zone control.
toLocaleString()
toLocaleString(locales)
toLocaleString(locales, options)- Added in JavaScript ES1 (1997); locales and options added in ECMA-402 (2012)
Parameters
| Parameter | Type | Description |
|---|---|---|
$localesoptional | string | string[]= undefined | A BCP 47 language tag, or an array of such tags, matching the locales parameter of the Intl.DateTimeFormat() constructor. In implementations without Intl.DateTimeFormat support this parameter is ignored and the host's locale is usually used. |
$optionsoptional | object= undefined | An object adjusting the output format, matching the options parameter of the Intl.DateTimeFormat() constructor. If weekday, year, month, day, dayPeriod, hour, minute, second and fractionalSecondDigits are all undefined, then year, month, day, hour, minute and second are set to "numeric". Ignored in implementations without Intl.DateTimeFormat support. |
Return value
stringA string representing the given date according to language-specific conventions. In implementations with Intl.DateTimeFormat, equivalent to new Intl.DateTimeFormat(locales, options).format(date).
Errors
Throws a RangeError if locales contains a malformed language tag or an option is given an unsupported value.
Changelog
- PHP ECMA-402 (2012)The locales and options parameters were added; before that the output was entirely implementation-defined.
- PHP ECMA-402 2020dateStyle and timeStyle shorthands were added; they cannot be combined with individual component options such as hour or month, which raises a TypeError.
toLocaleString() is toLocaleDateString() plus the clock: it renders date and time together in a locale's conventions, choosing 12- or 24-hour format, field order and separators for you. It is the right default for any timestamp shown to a user.
Pass a locale and a timeZone
With no arguments the result depends on the host's settings, which makes it unusable in tests and unpredictable on a server. Be explicit:
d.toLocaleString("en-US", {
timeZone: "UTC",
dateStyle: "medium",
timeStyle: "short",
});The timeZone option is how you convert a stored UTC instant into an office's or user's wall-clock time for display. It does not change the Date — only how this call renders it.
Styles and components do not mix
dateStyle and timeStyle are shorthands for a whole preset. Combining either with individual options such as hour, month or weekday throws a TypeError. Pick one approach per call.
Never compare the output
The specification permits engines to differ within the same locale, and current ICU separates the time from the day period with a narrow no-break space (U+202F), not an ordinary space. Equality checks against a hand-typed string will fail in ways that are invisible in a diff. Compare timestamps, not formatted text.
Example
When to use it
- Displaying a stored UTC timestamp in the viewer's local wall-clock time
- Rendering an event time in a fixed office time zone regardless of the viewer
- Building a locale-aware log or activity feed line
Frequently asked questions
How do I display a UTC timestamp in the user's local time?
Call toLocaleString() with no timeZone option — it defaults to the host time zone, which for a browser is the user's. Pass an explicit timeZone only when you want a fixed zone rather than the viewer's.
What is the difference between toLocaleString and toLocaleDateString?
toLocaleString() includes both date and time by default, while toLocaleDateString() formats only the date and throws a TypeError if you pass timeStyle.
Why can't I use dateStyle together with hour and minute?
dateStyle and timeStyle are presets that already choose every field, so combining them with individual component options throws a TypeError. Use one approach or the other in a single call.
More examples
One instant across offices
The underlying Date never changes; only the rendering does. Kolkata's half-hour offset shows why storing wall-clock strings instead of instants goes wrong.
const meeting = new Date("2024-11-05T16:00:00Z");
for (const zone of ["UTC", "America/Los_Angeles", "Europe/Berlin", "Asia/Kolkata"]) {
console.log(
zone,
meeting.toLocaleString("en-GB", { timeZone: zone, timeStyle: "short", dateStyle: "short" }),
);
}Styles cannot be mixed with components
Naming individual fields gives precise control — here a 24-hour time with no date at all — but combining that with dateStyle throws, because the shorthand already decides every field.
const d = new Date("2024-03-01T09:05:00Z");
const z = { timeZone: "UTC" };
console.log(d.toLocaleString("en-US", { ...z, hour: "2-digit", minute: "2-digit", hour12: false }));
try {
d.toLocaleString("en-US", { ...z, dateStyle: "full", hour: "numeric" });
} catch (err) {
console.log(err.constructor.name);
}Why equality checks fail
The comparison fails and the code point list reveals the culprit: a non-ASCII space character the engine inserted. Compare Date values or ISO strings in tests instead.
const d = new Date("2011-10-05T14:48:00Z");
const out = d.toLocaleString("en-US", { timeZone: "UTC", timeStyle: "short", dateStyle: "medium" });
console.log(out === "Oct 5, 2011, 2:48 PM");
console.log([...out].map((c) => c.codePointAt(0)).filter((c) => c > 127));
Discussion