toLocaleDateString()

ES1+

Returns just the date portion of a Date as a language-sensitive string, using the given locale and options; time components are omitted. It accepts the same locales and options machinery as Intl.DateTimeFormat, restricted by default to day-level fields.

Syntax

date.toLocaleDateString(locales, options)

Parameters

locales string | Array optional

A string with a BCP 47 language tag

options Object optional

An object with configuration properties

Return Value

string

A string representing the date portion

Examples

JavaScript
const date = new Date('2024-01-15');
console.log(date.toLocaleDateString('ko-KR'));
console.log(date.toLocaleDateString('en-US', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
}));
Output:
// '2024. 1. 15.' 'Monday, January 15, 2024'

📌 When to Use

Use toLocaleDateString() when the day matters but the clock does not: article and comment publication dates, birthdays, invoice and statement dates, deadlines, and list columns where full timestamps would be noise. It renders the calendar day in the viewer's conventions, September 3 order differences, month-name spelling, and script all handled by locale data, which is exactly what hand-rolled MM/DD/YYYY strings get wrong for most of the world. Two decisions deserve explicit thought at each call site. First, whose calendar day? By default the method uses the runtime's local zone, so an instant near midnight UTC renders as different days in Seoul and San Francisco; when the product means a specific day (an event in a venue's city, a market close in New York), pass the timeZone option so every viewer sees the same date. Second, which fields? Explicit options like { year: "numeric", month: "long", day: "numeric" } or dateStyle presets make output deterministic and reviewable, rather than whatever the environment default happens to be. For values that are conceptually date-only from birth (a birthday stored as "1990-06-15"), be careful constructing the Date: parse to a local date deliberately or format with timeZone: "UTC" so the displayed day matches the stored one everywhere.

⚠️ Common Mistakes

Relying on default locale and options and expecting consistent output. Defaults differ across browsers, operating systems, and server containers, so the same code renders 7/2/2026, 02/07/2026, or 2026. 7. 2. depending on where it runs; tests then pass locally and fail in CI.

The midnight-UTC shift: formatting new Date("1990-06-15") shows June 14 for users in the Americas, because the date-only string parses as UTC midnight while formatting uses the local zone. Pair UTC-parsed date-only values with { timeZone: "UTC" }, or construct from numeric parts.

Using formatted date strings as data, as sort keys, map keys, or values POSTed to APIs. Locale output is neither sortable nor parseable ("2 July 2026" versus "7/2/26"); keep ISO YYYY-MM-DD for machines and localize only at render.

Assuming the Gregorian calendar and Latin digits everywhere: locales like th-TH default to the Buddhist era (year 2569), ja-JP-u-ca-japanese uses era years, and ar-EG renders Eastern Arabic numerals. Layouts and validation that assume ASCII digits or 4-digit years break in exactly the markets localization was meant to serve.

Formatting inside sort comparators or filters, doing ICU work O(n log n) times to answer questions raw timestamps answer with one subtraction. Sort by getTime(), then format the visible rows only.

✅ Best Practices

Specify locale and options at every call: toLocaleDateString(locale, { dateStyle: "medium" }) or explicit component options. Deterministic formatting is the difference between a UI decision and an environment accident.

Cache Intl.DateTimeFormat per locale-options pair for lists and tables; formatter.format(date) in a loop is roughly an order of magnitude cheaper than repeated toLocaleDateString(options) calls.

Decide the reference zone consciously: viewer-local for "when did this happen for me", explicit timeZone for "what day is this event where it happens", and timeZone: "UTC" for date-only values stored as ISO days.

Handle relative freshness with Intl.RelativeTimeFormat ("2 days ago") and switch to toLocaleDateString() beyond a threshold, the pattern users now expect from feeds and inboxes; both APIs share locale plumbing.

For date-only domain values, keep the canonical form as a YYYY-MM-DD string or Temporal.PlainDate and format only for display; Temporal.PlainDate.prototype.toLocaleString() accepts these same options without any midnight or zone ambiguity.

⚡ Performance Notes

toLocaleDateString() shares its cost profile with toLocaleString(): each optioned call implicitly builds an Intl.DateTimeFormat, negotiates the locale, and formats via ICU, making it hundreds of times costlier than component getters, though still only microseconds each. The standard mitigation applies, hoist and reuse formatters keyed by locale and options, which turns a 1,000-row table's formatting from a measurable main-thread chunk into noise. Since only day-level fields are produced, output strings are short and allocation-light; the dominant cost is formatter construction, not string assembly. In virtualized lists, format lazily for rendered rows rather than eagerly for the whole dataset. On the server, formatting thousands of rows per request is usually better replaced by shipping ISO dates and formatting client-side, which also sidesteps server-versus-client locale drift.

🌍 Real World Example

Blog Post Date Display

Blog and news platforms localize publication dates as a matter of credibility: "July 2, 2026" for English readers, "2026년 7월 2일" for Korean ones, from the same stored ISO timestamp. The example formats with an explicit locale and options and demonstrates the feed pattern of pairing absolute dates with relative labels for recent posts. Centralizing this in one utility ensures article cards, detail pages, and RSS-driven widgets never disagree about a post's date, and it gives a single place to add the timeZone decision when editorial "publication day" policy requires it.

function formatPostDate(dateString, locale = 'en-US') {
  const date = new Date(dateString);
  const now = new Date();
  const diffDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));

  if (diffDays === 0) return 'Today';
  if (diffDays === 1) return 'Yesterday';
  if (diffDays < 7) return `${diffDays} days ago`;

  return date.toLocaleDateString(locale, {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  });
}

console.log(formatPostDate('2024-03-14')); // "Yesterday" or "March 14, 2024"

Related Methods