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.
Related Articles
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.
Level up your Claude Code workflow
50 battle-tested prompt templates you can copy-paste into Claude Code right now.
Free PDF: Claude Code Cheatsheet in 5 Minutes
Key commands, shortcuts, and prompt examples on a single printable page.
About the Author
Masa
Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.
Related Posts
How to Supercharge Your Side Projects with Claude Code [With Examples]
How to Supercharge Your Side Projects with Claude Code [With Examples]. A practical guide with code examples.
How to Automate Refactoring with Claude Code
Learn how to automate refactoring using Claude Code. Includes practical code examples and step-by-step guidance.
Complete CORS Configuration Guide with Claude Code
A complete CORS configuration guide using Claude Code. Practical tips and code examples included.