Use Cases

Handling Date and Time Correctly with Claude Code

Learn about handling date and time correctly using Claude Code. Includes practical code examples.

Implement Date and Time Handling Correctly With Claude Code

Date and time handling is full of unexpected pitfalls: time zones, formatting, locale support, and more. With Claude Code, you can efficiently implement robust date handling that follows best practices.

Choosing a Library

> Build a date/time utility.
> Use day.js, and implement timezone conversion, relative time display,
> formatting, and business day calculations.
  • day.js: Lightweight (2KB), with a Moment.js-compatible API
  • date-fns: Function-based, ideal for tree-shaking
  • Temporal API: A future standard API (still in proposal stage)

Implementing a Date Utility

// src/lib/date-utils.ts
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/en';

dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(relativeTime);
dayjs.locale('en');

// Default timezone
const DEFAULT_TZ = 'America/New_York';

// Format presets
export const DATE_FORMATS = {
  full: 'MMMM D, YYYY (ddd) HH:mm',
  date: 'MMMM D, YYYY',
  dateShort: 'M/D',
  time: 'HH:mm',
  iso: 'YYYY-MM-DDTHH:mm:ssZ',
  api: 'YYYY-MM-DD',
} as const;

/**
 * Format a UTC date string in the target timezone.
 */
export function formatDate(
  date: string | Date,
  format: keyof typeof DATE_FORMATS = 'date'
): string {
  return dayjs(date).tz(DEFAULT_TZ).format(DATE_FORMATS[format]);
}

/**
 * Return relative time ("3 minutes ago", "2 hours ago", "yesterday", etc.)
 */
export function timeAgo(date: string | Date): string {
  const d = dayjs(date);
  const now = dayjs();
  const diffHours = now.diff(d, 'hour');

  if (diffHours < 1) {
    const diffMinutes = now.diff(d, 'minute');
    if (diffMinutes < 1) return 'just now';
    return `${diffMinutes} min ago`;
  }
  if (diffHours < 24) return `${diffHours} hours ago`;
  if (diffHours < 48) return 'yesterday';
  if (diffHours < 168) return `${Math.floor(diffHours / 24)} days ago`;

  return formatDate(date, 'date');
}

/**
 * Timezone conversion
 */
export function convertTimezone(
  date: string | Date,
  fromTz: string,
  toTz: string
): dayjs.Dayjs {
  return dayjs.tz(date, fromTz).tz(toTz);
}

/**
 * Check whether a given date is a business day.
 */
export function isBusinessDay(date: string | Date): boolean {
  const d = dayjs(date);
  const dayOfWeek = d.day();
  return dayOfWeek !== 0 && dayOfWeek !== 6; // Sunday=0, Saturday=6
}

/**
 * Add N business days to a date.
 */
export function addBusinessDays(date: string | Date, days: number): dayjs.Dayjs {
  let current = dayjs(date);
  let remaining = days;

  while (remaining > 0) {
    current = current.add(1, 'day');
    if (isBusinessDay(current.toDate())) {
      remaining--;
    }
  }

  return current;
}

Native Formatting With the Intl API

You can achieve many of these formats without a library, using the browser’s Intl API.

// src/lib/intl-date.ts

/**
 * Format a date using Intl.DateTimeFormat.
 */
export function formatDateIntl(date: Date, style: 'long' | 'short' = 'long'): string {
  return new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: style === 'long' ? 'long' : 'numeric',
    day: 'numeric',
    weekday: style === 'long' ? 'short' : undefined,
  }).format(date);
}

/**
 * Format the difference between two dates in a human-readable form.
 */
export function formatDateRange(start: Date, end: Date): string {
  return new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
  }).formatRange(start, end);
}

/**
 * Format relative time.
 */
export function formatRelative(date: Date): string {
  const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
  const now = new Date();
  const diffMs = date.getTime() - now.getTime();
  const diffSec = Math.round(diffMs / 1000);
  const diffMin = Math.round(diffSec / 60);
  const diffHour = Math.round(diffMin / 60);
  const diffDay = Math.round(diffHour / 24);

  if (Math.abs(diffSec) < 60) return rtf.format(diffSec, 'second');
  if (Math.abs(diffMin) < 60) return rtf.format(diffMin, 'minute');
  if (Math.abs(diffHour) < 24) return rtf.format(diffHour, 'hour');
  return rtf.format(diffDay, 'day');
}

Usage in a React Component

// src/components/TimeDisplay.tsx
'use client';
import { useState, useEffect } from 'react';
import { timeAgo } from '@/lib/date-utils';

export function TimeDisplay({ date }: { date: string }) {
  const [display, setDisplay] = useState(timeAgo(date));

  useEffect(() => {
    const interval = setInterval(() => {
      setDisplay(timeAgo(date));
    }, 60000); // Update every minute
    return () => clearInterval(interval);
  }, [date]);

  return (
    <time dateTime={date} title={new Date(date).toLocaleString('en-US')}>
      {display}
    </time>
  );
}

Common Pitfalls

  • Ignoring time zones: When the server and client are in different time zones, always store UTC and convert on the client.
  • Daylight saving time: Be careful when supporting users in regions that observe DST.
  • Date.parse() quirks: Behavior varies between browsers, so use dayjs or similar to parse dates.

For internationalization in general, see the i18n implementation guide, and for currency formatting, see implementing currency formatting.

See the official day.js documentation (day.js.org) for the plugin list.

#Claude Code #date #timezone #day.js #Intl

Level up your Claude Code workflow

50 battle-tested prompt templates you can copy-paste into Claude Code right now.

Free

Free PDF: Claude Code Cheatsheet in 5 Minutes

Key commands, shortcuts, and prompt examples on a single printable page.

Download PDF
M

About the Author

Masa

Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.