X Xerobit

JavaScript Date Formatting — Intl.DateTimeFormat, date-fns, and Custom Formats

Format dates in JavaScript using the built-in Intl.DateTimeFormat API, date-fns format(), or manual formatting. Covers ISO 8601, locale-aware formatting, relative time (3 days...

Mian Ali Khalid · · 5 min read
Use the tool
Timestamp Converter
Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.
Open Timestamp Converter →

JavaScript’s built-in Intl.DateTimeFormat API handles locale-aware date formatting without dependencies. For complex date manipulation, date-fns is the modern alternative to Moment.js.

Convert between timestamps and dates with the Timestamp Converter.

Intl.DateTimeFormat (built-in, no dependencies)

const date = new Date('2026-05-12T14:30:00Z');

// Locale-aware formatting:
const us = new Intl.DateTimeFormat('en-US', {
  year: 'numeric', month: 'long', day: 'numeric'
}).format(date);
// "May 12, 2026"

const uk = new Intl.DateTimeFormat('en-GB', {
  year: 'numeric', month: 'long', day: 'numeric'
}).format(date);
// "12 May 2026"

const de = new Intl.DateTimeFormat('de-DE', {
  year: 'numeric', month: 'long', day: 'numeric'
}).format(date);
// "12. Mai 2026"

// With time:
const withTime = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'medium',
  timeStyle: 'short',
  timeZone: 'America/New_York',
}).format(date);
// "May 12, 2026, 10:30 AM"

Common format patterns with Intl

// Short date: "5/12/26"
new Intl.DateTimeFormat('en-US', { dateStyle: 'short' }).format(date);

// Medium date: "May 12, 2026"
new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }).format(date);

// Long date: "May 12, 2026"
new Intl.DateTimeFormat('en-US', { dateStyle: 'long' }).format(date);

// Full date: "Tuesday, May 12, 2026"
new Intl.DateTimeFormat('en-US', { dateStyle: 'full' }).format(date);

// ISO-like: "2026-05-12"
const isoDate = date.toISOString().split('T')[0];

// Time only: "2:30 PM"
new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(date);

Manual formatting (zero-dependency)

function formatDate(date, format) {
  const d = new Date(date);
  const pad = (n) => String(n).padStart(2, '0');
  
  const parts = {
    YYYY: d.getFullYear(),
    MM: pad(d.getMonth() + 1),
    DD: pad(d.getDate()),
    HH: pad(d.getHours()),
    mm: pad(d.getMinutes()),
    ss: pad(d.getSeconds()),
    M: d.getMonth() + 1,
    D: d.getDate(),
  };
  
  return format.replace(/YYYY|MM|DD|HH|mm|ss|M|D/g, (match) => parts[match]);
}

formatDate(new Date(), 'YYYY-MM-DD');          // "2026-05-12"
formatDate(new Date(), 'DD/MM/YYYY');          // "12/05/2026"
formatDate(new Date(), 'MM/DD/YYYY HH:mm');    // "05/12/2026 14:30"

date-fns (best npm library for formatting)

npm install date-fns
import { format, formatDistance, formatRelative, parseISO } from 'date-fns';
import { toZonedTime } from 'date-fns-tz'; // npm install date-fns-tz

const date = new Date('2026-05-12T14:30:00Z');

// Format tokens (similar to strftime):
format(date, 'yyyy-MM-dd');                 // "2026-05-12"
format(date, 'MM/dd/yyyy');                 // "05/12/2026"
format(date, 'MMMM d, yyyy');              // "May 12, 2026"
format(date, "MMMM d, yyyy 'at' h:mm a"); // "May 12, 2026 at 2:30 PM"
format(date, 'EEE, MMM d');               // "Tue, May 12"
format(date, 'HH:mm:ss');                  // "14:30:00"

// Relative time:
const threeDaysAgo = new Date(Date.now() - 3 * 86400000);
formatDistance(threeDaysAgo, new Date(), { addSuffix: true }); // "3 days ago"

// With timezone:
const ny = toZonedTime(date, 'America/New_York');
format(ny, 'yyyy-MM-dd HH:mm zzz');  // "2026-05-12 10:30 EDT"

Relative time: “3 days ago” (Intl.RelativeTimeFormat)

function timeAgo(date) {
  const seconds = Math.floor((Date.now() - new Date(date)) / 1000);
  const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
  
  const thresholds = [
    { unit: 'year',   seconds: 31536000 },
    { unit: 'month',  seconds: 2592000 },
    { unit: 'week',   seconds: 604800 },
    { unit: 'day',    seconds: 86400 },
    { unit: 'hour',   seconds: 3600 },
    { unit: 'minute', seconds: 60 },
    { unit: 'second', seconds: 1 },
  ];
  
  for (const { unit, seconds: threshold } of thresholds) {
    const delta = Math.floor(seconds / threshold);
    if (delta >= 1) return rtf.format(-delta, unit);
  }
  
  return 'just now';
}

timeAgo(new Date(Date.now() - 3600000));  // "1 hour ago"
timeAgo(new Date(Date.now() - 86400000)); // "yesterday"
timeAgo(new Date(Date.now() - 604800000)); // "last week"

Parse date strings safely

// ISO 8601 — always safe to parse:
new Date('2026-05-12T14:30:00Z');         // UTC
new Date('2026-05-12T14:30:00+05:30');    // IST

// Date-only strings: behavior is timezone-dependent!
new Date('2026-05-12');    // Parsed as UTC midnight (not local midnight)
new Date('2026/05/12');    // Local time — avoid this inconsistency

// Safe cross-browser parsing with date-fns:
import { parseISO, parse } from 'date-fns';
parseISO('2026-05-12');                   // Consistent UTC
parse('12/05/2026', 'dd/MM/yyyy', new Date()); // Non-ISO format

React: formatted date component

function FormattedDate({ date, format = 'medium' }) {
  const formatter = new Intl.DateTimeFormat('en-US', { dateStyle: format });
  return (
    <time dateTime={new Date(date).toISOString()}>
      {formatter.format(new Date(date))}
    </time>
  );
}

// Usage:
<FormattedDate date="2026-05-12T14:30:00Z" />          // "May 12, 2026"
<FormattedDate date="2026-05-12T14:30:00Z" format="full" /> // "Tuesday, May 12, 2026"

Related posts

Related tool

Timestamp Converter

Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.