DEV Community

Alex Chen
Alex Chen

Posted on

Working with Dates and Times in JavaScript (2026)

Working with Dates and Times in JavaScript (2026)

Dates in JS are painful. Here's how to make them less so.

The Problem

const d = new Date('2026-05-16');
// Works on your machine, fails on others
// Timezone issues everywhere
// Month is 0-indexed (January = 0)
// Year before 100 = 1900 + year
Enter fullscreen mode Exit fullscreen mode

Modern Solution: Use a Library

npm install dayjs  # 2KB, immutable, chainable
# or: npm install date-fns  # Tree-shakeable, functional
Enter fullscreen mode Exit fullscreen mode

Day.js — My Go-To

import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import relativeTime from 'dayjs/plugin/relativeTime';

dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(relativeTime);

// Parse
dayjs('2026-05-16');                    // May 16, 2026
dayjs.unix(1715840000);                 // From Unix timestamp
dayjs();                                // Now

// Format
dayjs().format('YYYY-MM-DD');           // "2026-05-16"
dayjs().format('YYYY-MM-DD HH:mm:ss');  // "2026-05-16 07:20:00"
dayjs().format('ddd, MMM D, YYYY');     // "Sat, May 16, 2026"

// Manipulate
dayjs().add(7, 'day');                  // Next week
dayjs().subtract(1, 'month');           // Last month
dayjs().startOf('week');                // Monday of this week
dayjs().endOf('month');                // Last day of this month

// Query
dayjs().isBefore(dayjs('2027-01-01'));  // true
dayjs().isAfter(dayjs('2026-01-01'));   // true
dayjs().isSame(dayjs(), 'day');         // true

// Relative time
dayjs().fromNow();                      // "a few seconds ago"
dayjs('2026-06-01').fromNow();          // "in 2 weeks"

// Timezone
dayjs().tz('America/New_York').format(); // Eastern time
dayjs().tz('Asia/Shanghai').format();    // Beijing time
dayjs().utc().format();                  // UTC

// Difference
dayjs('2026-12-31').diff(dayjs(), 'day'); // Days until New Year's Eve
Enter fullscreen mode Exit fullscreen mode

date-fns — When You Need Tree-Shaking

import { format, addDays, subMonths, isAfter, parseISO } from 'date-fns';

const now = new Date();
format(now, 'yyyy-MM-dd');              // "2026-05-16"
addDays(now, 30);                       // 30 days from now
subMonths(now, 3);                      // 3 months ago
isAfter(new Date('2027-01-01'), now);   // true
parseISO('2026-05-16T07:20:00Z');       // Date object
Enter fullscreen mode Exit fullscreen mode

Vanilla JS: What You Need to Know

const now = new Date();

// Get components
now.getFullYear();      // 2026
now.getMonth();         // 4 (May! 0-indexed!)
now.getDate();          // 16
now.getDay();           // 6 (Saturday, 0=Sunday)
now.getHours();         // 7
now.getMinutes();       // 20
now.getSeconds();       // 0
now.getTime();          // Unix timestamp in ms

// Set components
const d = new Date();
d.setFullYear(2026);
d.setMonth(11);         // December (0-indexed!)
d.setDate(25);          // Christmas!

// Format (vanilla is ugly)
d.toISOString();        // "2026-12-25T00:00:00.000Z"
d.toLocaleDateString('en-US', { 
  weekday: 'long', 
  year: 'numeric', 
  month: 'long', 
  day: 'numeric' 
});                      // "Friday, December 25, 2026"

// Parse (careful with formats)
new Date('2026-05-16');            // OK (ISO format)
new Date('05/16/2026');             // Depends on locale!
new Date(2026, 4, 16);             // Reliable (month is 0-indexed!)

// Compare
const d1 = new Date('2026-01-01');
const d2 = new Date('2026-12-31');
d1 < d2;                           // true
Math.abs(d2 - d1) / (1000 * 60 * 60 * 24); // Days between dates
Enter fullscreen mode Exit fullscreen mode

Common Patterns

Format Duration (Human Readable)

function formatDuration(ms) {
  const seconds = Math.floor(ms / 1000);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);

  if (days > 0) return `${days}d ${hours % 24}h`;
  if (hours > 0) return `${hours}h ${minutes % 60}m`;
  if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
  return `${seconds}s`;
}

formatDuration(3661000);    // "1h 1m"
formatDuration(90061000);   // "1d 1h"
Enter fullscreen mode Exit fullscreen mode

Is Today Between Two Dates?

function isBetween(date, start, end) {
  const d = new Date(date).setHours(0, 0, 0, 0);
  const s = new Date(start).setHours(0, 0, 0, 0);
  const e = new Date(end).setHours(0, 0, 0, 0);
  return d >= s && d <= e;
}

isBetween(new Date(), '2026-05-01', '2026-05-31'); // true
Enter fullscreen mode Exit fullscreen mode

Get All Dates in a Range

function getDateRange(start, end) {
  const dates = [];
  let current = new Date(start);
  const stop = new Date(end);

  while (current <= stop) {
    dates.push(new Date(current));
    current.setDate(current.getDate() + 1);
  }

  return dates;
}

getDateRange('2026-05-01', '2026-05-05');
// [May 1, May 2, May 3, May 4, May 5]
Enter fullscreen mode Exit fullscreen mode

Countdown Timer

function countdown(targetDate) {
  const update = () => {
    const now = new Date();
    const diff = new Date(targetDate) - now;

    if (diff <= 0) return { done: true };

    const days = Math.floor(diff / (1000 * 60 * 60 * 24));
    const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
    const seconds = Math.floor((diff % (1000 * 60)) / 1000);

    return { days, hours, minutes, seconds };
  };

  return update();
}
Enter fullscreen mode Exit fullscreen mode

Timezone Gotchas

// ❌ Don't do this:
new Date().toString(); // "Sat May 16 2026 07:20:00 GMT+0800..."

// ✅ Do this instead:
new Date().toISOString(); // Always UTC
Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York' }).format(now);

// Get user's timezone
Intl.DateTimeFormat().resolvedOptions().timeZone; // "Asia/Shanghai"

// Convert timezone
function convertTZ(date, tz) {
  return new Date(date.toLocaleString('en-US', { timeZone: tz }));
}
Enter fullscreen mode Exit fullscreen mode

What's your favorite date library? Or do you suffer through vanilla JS?

Follow @armorbreak for more JavaScript content.

Top comments (0)