Docs

README

15.2 Date Formatting & Calculations

Overview

Working with dates often involves formatting them for display and performing calculations like finding differences or adding/subtracting time. This section covers formatting options, date arithmetic, and common date manipulation patterns.

Date Formatting

Built-in Formatting Methods

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                  Built-in Date Formatting                        │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  Method                  │  Example Output                      │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  toString()              │  "Wed Dec 25 2024 10:30:00 GMT-0500" │
│  toDateString()          │  "Wed Dec 25 2024"                   │
│  toTimeString()          │  "10:30:00 GMT-0500"                 │
│  toISOString()           │  "2024-12-25T15:30:00.000Z"          │
│  toUTCString()           │  "Wed, 25 Dec 2024 15:30:00 GMT"     │
│  toLocaleString()        │  "12/25/2024, 10:30:00 AM"           │
│  toLocaleDateString()    │  "12/25/2024"                        │
│  toLocaleTimeString()    │  "10:30:00 AM"                       │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Intl.DateTimeFormat

The Intl.DateTimeFormat object provides powerful locale-aware date formatting:

const date = new Date('2024-12-25T10:30:00');

// Basic usage
new Intl.DateTimeFormat('en-US').format(date); // "12/25/2024"
new Intl.DateTimeFormat('de-DE').format(date); // "25.12.2024"
new Intl.DateTimeFormat('ja-JP').format(date); // "2024/12/25"

// With options
const formatter = new Intl.DateTimeFormat('en-US', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
});
formatter.format(date); // "Wednesday, December 25, 2024"

Format Options

OptionValues
weekday'narrow', 'short', 'long'
year'numeric', '2-digit'
month'numeric', '2-digit', 'narrow', 'short', 'long'
day'numeric', '2-digit'
hour'numeric', '2-digit'
minute'numeric', '2-digit'
second'numeric', '2-digit'
hour12true, false
timeZone'UTC', 'America/New_York', etc.
timeZoneName'short', 'long'
const date = new Date('2024-12-25T10:30:00');

// Different weekday formats
const options = { weekday: 'narrow' }; // "W"
const options = { weekday: 'short' }; // "Wed"
const options = { weekday: 'long' }; // "Wednesday"

// Different month formats
const options = { month: 'numeric' }; // "12"
const options = { month: '2-digit' }; // "12"
const options = { month: 'narrow' }; // "D"
const options = { month: 'short' }; // "Dec"
const options = { month: 'long' }; // "December"

// Time formatting
const options = {
  hour: '2-digit',
  minute: '2-digit',
  hour12: true,
}; // "10:30 AM"

const options = {
  hour: '2-digit',
  minute: '2-digit',
  hour12: false,
}; // "10:30"

Custom Format Function

function formatDate(date, format) {
  const map = {
    YYYY: date.getFullYear(),
    YY: String(date.getFullYear()).slice(-2),
    MM: String(date.getMonth() + 1).padStart(2, '0'),
    M: date.getMonth() + 1,
    DD: String(date.getDate()).padStart(2, '0'),
    D: date.getDate(),
    HH: String(date.getHours()).padStart(2, '0'),
    H: date.getHours(),
    mm: String(date.getMinutes()).padStart(2, '0'),
    m: date.getMinutes(),
    ss: String(date.getSeconds()).padStart(2, '0'),
    s: date.getSeconds(),
  };

  return format.replace(
    /YYYY|YY|MM|M|DD|D|HH|H|mm|m|ss|s/g,
    (match) => map[match]
  );
}

formatDate(new Date(), 'YYYY-MM-DD'); // "2024-12-25"
formatDate(new Date(), 'DD/MM/YYYY'); // "25/12/2024"
formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss'); // "2024-12-25 10:30:00"

Date Arithmetic

Adding and Subtracting Time

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                    Date Arithmetic                               │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│                                                                  │
│   Using setX() methods:                                         │
│   ─────────────────────                                         │
│   date.setDate(date.getDate() + 7)    // Add 7 days            │
│   date.setMonth(date.getMonth() - 1)  // Subtract 1 month      │
│   date.setFullYear(date.getFullYear() + 1) // Add 1 year       │
│                                                                  │
│   Using milliseconds:                                           │
│   ───────────────────                                           │
│   new Date(date.getTime() + (days * 24 * 60 * 60 * 1000))      │
│                                                                  │
│   Time units in milliseconds:                                   │
│   ─────────────────────────                                     │
│   1 second = 1,000 ms                                           │
│   1 minute = 60,000 ms                                          │
│   1 hour   = 3,600,000 ms                                       │
│   1 day    = 86,400,000 ms                                      │
│                                                                  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
// Add/subtract using setters
function addDays(date, days) {
  const result = new Date(date);
  result.setDate(result.getDate() + days);
  return result;
}

function addMonths(date, months) {
  const result = new Date(date);
  result.setMonth(result.getMonth() + months);
  return result;
}

function addYears(date, years) {
  const result = new Date(date);
  result.setFullYear(result.getFullYear() + years);
  return result;
}

// Examples
const today = new Date('2024-12-25');
addDays(today, 7); // 2025-01-01
addDays(today, -7); // 2024-12-18
addMonths(today, 1); // 2025-01-25
addMonths(today, -6); // 2024-06-25
addYears(today, 1); // 2025-12-25

Time Constants

const MS_PER_SECOND = 1000;
const MS_PER_MINUTE = 60 * MS_PER_SECOND;
const MS_PER_HOUR = 60 * MS_PER_MINUTE;
const MS_PER_DAY = 24 * MS_PER_HOUR;
const MS_PER_WEEK = 7 * MS_PER_DAY;

// Add 2 hours using milliseconds
function addHours(date, hours) {
  return new Date(date.getTime() + hours * MS_PER_HOUR);
}

// Add 30 minutes
function addMinutes(date, minutes) {
  return new Date(date.getTime() + minutes * MS_PER_MINUTE);
}

Calculating Differences

Difference Between Dates

function dateDiff(date1, date2) {
  const ms = Math.abs(date2 - date1);

  return {
    milliseconds: ms,
    seconds: Math.floor(ms / 1000),
    minutes: Math.floor(ms / (1000 * 60)),
    hours: Math.floor(ms / (1000 * 60 * 60)),
    days: Math.floor(ms / (1000 * 60 * 60 * 24)),
    weeks: Math.floor(ms / (1000 * 60 * 60 * 24 * 7)),
  };
}

const start = new Date('2024-01-01');
const end = new Date('2024-12-31');
const diff = dateDiff(start, end);
// { days: 365, weeks: 52, hours: 8760, ... }

Difference in Specific Units

function diffInDays(date1, date2) {
  const oneDay = 24 * 60 * 60 * 1000;
  return Math.round((date2 - date1) / oneDay);
}

function diffInMonths(date1, date2) {
  let months = (date2.getFullYear() - date1.getFullYear()) * 12;
  months += date2.getMonth() - date1.getMonth();
  return months;
}

function diffInYears(date1, date2) {
  return date2.getFullYear() - date1.getFullYear();
}

Relative Time

Relative Time Formatter

function getRelativeTime(date, baseDate = new Date()) {
  const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
  const diff = date - baseDate;
  const absDiff = Math.abs(diff);

  const seconds = absDiff / 1000;
  const minutes = seconds / 60;
  const hours = minutes / 60;
  const days = hours / 24;
  const weeks = days / 7;
  const months = days / 30;
  const years = days / 365;

  const sign = diff < 0 ? -1 : 1;

  if (seconds < 60) {
    return rtf.format(Math.round(seconds) * sign, 'second');
  } else if (minutes < 60) {
    return rtf.format(Math.round(minutes) * sign, 'minute');
  } else if (hours < 24) {
    return rtf.format(Math.round(hours) * sign, 'hour');
  } else if (days < 7) {
    return rtf.format(Math.round(days) * sign, 'day');
  } else if (weeks < 4) {
    return rtf.format(Math.round(weeks) * sign, 'week');
  } else if (months < 12) {
    return rtf.format(Math.round(months) * sign, 'month');
  } else {
    return rtf.format(Math.round(years) * sign, 'year');
  }
}

getRelativeTime(new Date(Date.now() - 5000)); // "5 seconds ago"
getRelativeTime(new Date(Date.now() + 86400000)); // "tomorrow"

Simple Relative Time

function timeAgo(date) {
  const seconds = Math.floor((new Date() - date) / 1000);

  const intervals = {
    year: 31536000,
    month: 2592000,
    week: 604800,
    day: 86400,
    hour: 3600,
    minute: 60,
    second: 1,
  };

  for (const [unit, secondsInUnit] of Object.entries(intervals)) {
    const interval = Math.floor(seconds / secondsInUnit);
    if (interval >= 1) {
      return `${interval} ${unit}${interval === 1 ? '' : 's'} ago`;
    }
  }

  return 'just now';
}

Working with Ranges

Date Range Generator

function* dateRange(start, end, step = 1) {
  const current = new Date(start);
  while (current <= end) {
    yield new Date(current);
    current.setDate(current.getDate() + step);
  }
}

// Usage
const start = new Date('2024-01-01');
const end = new Date('2024-01-07');

for (const date of dateRange(start, end)) {
  console.log(date.toDateString());
}

Get All Days in Month

function getDaysInMonth(year, month) {
  const date = new Date(year, month, 1);
  const days = [];

  while (date.getMonth() === month) {
    days.push(new Date(date));
    date.setDate(date.getDate() + 1);
  }

  return days;
}

const december2024 = getDaysInMonth(2024, 11); // Array of 31 dates

Business Day Calculations

function isWeekend(date) {
  const day = date.getDay();
  return day === 0 || day === 6;
}

function addBusinessDays(date, days) {
  const result = new Date(date);
  let added = 0;

  while (added < days) {
    result.setDate(result.getDate() + 1);
    if (!isWeekend(result)) {
      added++;
    }
  }

  return result;
}

function getBusinessDaysBetween(start, end) {
  let count = 0;
  const current = new Date(start);

  while (current < end) {
    current.setDate(current.getDate() + 1);
    if (!isWeekend(current)) {
      count++;
    }
  }

  return count;
}

Common Calculations

Age Calculator

function calculateAge(birthDate) {
  const today = new Date();
  let age = today.getFullYear() - birthDate.getFullYear();
  const monthDiff = today.getMonth() - birthDate.getMonth();

  if (
    monthDiff < 0 ||
    (monthDiff === 0 && today.getDate() < birthDate.getDate())
  ) {
    age--;
  }

  return age;
}

calculateAge(new Date('1990-05-15')); // Returns current age

Days Until/Since

function daysUntil(targetDate) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const target = new Date(targetDate);
  target.setHours(0, 0, 0, 0);

  return Math.ceil((target - today) / (1000 * 60 * 60 * 24));
}

function daysSince(pastDate) {
  return -daysUntil(pastDate);
}

daysUntil(new Date('2024-12-25')); // Days until Christmas
daysSince(new Date('2024-01-01')); // Days since New Year

Next Occurrence

function getNextWeekday(dayOfWeek) {
  // dayOfWeek: 0 = Sunday, 1 = Monday, etc.
  const today = new Date();
  const currentDay = today.getDay();
  const daysUntil = (dayOfWeek - currentDay + 7) % 7 || 7;

  const next = new Date(today);
  next.setDate(today.getDate() + daysUntil);
  return next;
}

getNextWeekday(1); // Next Monday
getNextWeekday(5); // Next Friday

Calendar Helpers

Get Calendar Month Grid

function getCalendarMonth(year, month) {
  const firstDay = new Date(year, month, 1);
  const lastDay = new Date(year, month + 1, 0);

  const calendar = [];
  let week = [];

  // Pad the beginning with nulls
  for (let i = 0; i < firstDay.getDay(); i++) {
    week.push(null);
  }

  // Add all days
  for (let day = 1; day <= lastDay.getDate(); day++) {
    week.push(day);
    if (week.length === 7) {
      calendar.push(week);
      week = [];
    }
  }

  // Pad the end with nulls
  while (week.length > 0 && week.length < 7) {
    week.push(null);
  }
  if (week.length) calendar.push(week);

  return calendar;
}

// Returns 2D array for calendar display
// [[null, null, null, null, null, 1, 2], [3, 4, 5, 6, 7, 8, 9], ...]

Key Takeaways

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                Date Formatting & Calculations                    │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  1. Use Intl.DateTimeFormat for locale-aware formatting         │
│  2. toISOString() for storage/APIs, toLocale* for display       │
│  3. Date math: use setters (auto-rollover) or milliseconds      │
│  4. Difference: subtract dates to get milliseconds              │
│  5. Intl.RelativeTimeFormat for "2 days ago" style              │
│  6. Always clone dates before modifying                         │
│  7. Consider business days for work-related calculations        │
│  8. Month calculations need special care (varying days)         │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
README - JavaScript Tutorial | DeepML