Date formatting without any libraries
You should only reach for a library if you truly need advanced parsing or complex time-zone arithmetic.
This is the simplest, most reliable format construction.
function formatMMDDYYYY(date) {
const mm = String(date.getMonth() + 1).padStart(2, '0');
const dd = String(date.getDate()).padStart(2, '0');
const yyyy = date.getFullYear();
return `${mm}/${dd}/${yyyy}`;
}
// → "12/24/2025"There are also different approaches:
Intl.DateTimeFormat
Another modern way to format is using Intl.DateTimeFormat
This is the correct tool for any UI formatting. It handles locale, numbering systems, calendars, and time zones out of the box.
const now = Date.now()
const formatted = new Intl.DateTimeFormat('en-US', {
month: '2-digit',
day: '2-digit',
year: 'numeric'
}).format(now);
// → MM/DD/YYYYFormat in a different locale
new Intl.DateTimeFormat('fr-FR').format(new Date());
// → "09/12/2025"Format time with options
new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}).format(new Date());
// → "08:38:44 AM"Format with timezone
new Intl.DateTimeFormat('en-US', {
timeZone: 'UTC',
hour: '2-digit',
minute: '2-digit'
}).format(new Date());
// → "01:39 PM"ISO Strings (Machine-Readable Formats)
JavaScript can also generate ISO timestamps.
new Date().toISOString();
// → "2025-12-08T03:14:25.123Z"Use cases
- APIs
- Databases
- Logs
- Server-client communication
Temporal (The Future of Date Handling)
Temporal is being added to the language and is available in some runtimes (and polyfills).
This will replace most remaining date libraries.
Temporal.Now.plainDateISO().toString();
// "2025-12-08"Custom formatting with toLocaleString:
Temporal.Now.plainDateTimeISO().toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
});Comparissons
Moment vs Native
Moment
moment().format('MM/DD/YYYY');Native
new Intl.DateTimeFormat('en-US', {
month: '2-digit',
day: '2-digit',
year: 'numeric'
}).format(new Date());Day.js vs Native
Day.js:
dayjs().format('MMMM D, YYYY');Native:
new Intl.DateTimeFormat('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric'
}).format(new Date());date-fns vs Native
Date-fns:
format(new Date(), 'yyyy/MM/dd');Native:
new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
}).format(new Date());Best Practices
- Always format with
Intl.DateTimeFormatin UI code. - Use ISO (
.toISOString()) for storage & API communication. - Avoid libraries unless doing heavy date arithmetic.
- Never rely on
date.toLocaleString()without specifying options, too much variability. - When building custom formats, construct them manually (e.g.,
MM/DD/YYYY). - Be explicit about time zones—ideally UTC for backend.
A Reusable Native Formatter Utility
A simple, production-ready date utility without dependencies:
export const DateFormat = {
iso: date => date.toISOString(),
usShort: date =>
new Intl.DateTimeFormat('en-US', {
month: '2-digit',
day: '2-digit',
year: 'numeric'
}).format(date),
long: date =>
new Intl.DateTimeFormat('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric'
}).format(date),
time: date =>
new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit'
}).format(date),
custom: (date, joiner = '/') => {
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
const y = date.getFullYear();
return [m, d, y].join(joiner);
}
};