Guides
Formatting
clockworktz has a built-in, dependency-free formatter that supports a date-fns-compatible subset of tokens. It formats an instant as seen in a zone, using that zone's offset at that instant.
import { format } from 'clockworktz'
format('2024-07-15T14:00:00Z', 'Pacific/Chatham', 'yyyy-MM-dd HH:mm xxx')
// '2024-07-16 02:45 +12:45'
format(instant, zone, pattern?, locale?)
| Parameter | Type | Default |
|---|---|---|
instant |
Date | number | string |
required |
zone |
string |
required |
pattern |
string |
'yyyy-MM-dd HH:mm:ss zzz' |
locale |
string |
'en' |
locale controls month names, weekday names and the AM/PM marker. Digits and token layout always follow the pattern.
format('2024-07-05T09:05:07Z', 'Europe/Berlin', 'EEEE d. MMMM yyyy', 'de')
// 'Freitag 5. Juli 2024'
The same patterns work anywhere a format option is accepted, such as fromUTC, interpretLocal and convert:
import { convert } from 'clockworktz'
convert('2024-09-12T10:00:00', 'Europe/London', 'Asia/Kolkata', { format: 'EEE HH:mm' }).local
// 'Thu 14:30'
Tokens
The examples below format 2024-07-05T09:05:07.123Z in Asia/Kathmandu (UTC+05:45), where it's 14:50:07.123 on Friday.
| Token | Output | Example |
|---|---|---|
yyyy yy y |
Year | 2024 24 2024 |
M MM |
Month number | 7 07 |
MMM MMMM |
Month name | Jul July |
d dd |
Day of month | 5 05 |
EEE EEEE |
Weekday | Fri Friday |
H HH |
Hour, 0–23 | 14 14 |
h hh |
Hour, 1–12 | 2 02 |
a |
Day period | PM |
m mm |
Minute | 50 50 |
s ss |
Second | 7 07 |
S SS SSS |
Fraction of a second | 1 12 123 |
zzz |
Abbreviation | +0545 (EDT in New York) |
zzzz |
Long zone name | Nepal Time |
x xx |
Offset, basic | +0545 |
xxx |
Offset, extended | +05:45 |
xxxx xxxxx |
As xx / xxx, plus seconds when non-zero |
+0545 +05:45 |
X XX … XXXXX |
As x, but Z for UTC |
+0545, or Z in UTC |
O |
GMT offset, short | GMT+5:45 |
OOOO |
GMT offset, long | GMT+05:45 |
'text' |
Literal text | 'at' → at |
'' |
A literal single quote | ' |
Any ASCII letter outside a quoted section is treated as a token, so quote words: "HH:mm 'Uhr'". An unsupported token (such as Q, w or D) throws TimezoneError rather than producing silently wrong output.
format('2024-07-05T09:05:07Z', 'UTC', 'Q')
// throws TimezoneError: Unsupported format token "Q" in Q
isValidFormatPattern('yyyy-MM-dd') // true
isValidFormatPattern('yyyy-Q') // false
Offsets with seconds
Before standard time, zones used local mean time with offsets that aren't whole minutes. The 4- and 5-letter x forms include seconds when they're non-zero:
format('1880-01-01T00:00:00Z', 'Europe/Amsterdam', 'xxxxx')
// '+00:17:30'
Predefined patterns
FORMAT_PATTERNS holds common patterns, and formatWithPattern formats with one by name. These examples format 2024-03-15T14:30:00Z in America/Los_Angeles:
| Name | Pattern | Output |
|---|---|---|
default |
yyyy-MM-dd HH:mm:ss zzz |
2024-03-15 07:30:00 PDT |
dateOnly |
yyyy-MM-dd |
2024-03-15 |
timeOnly |
HH:mm:ss |
07:30:00 |
dateTime |
yyyy-MM-dd HH:mm:ss |
2024-03-15 07:30:00 |
dateTimeMs |
yyyy-MM-dd HH:mm:ss.SSS |
2024-03-15 07:30:00.000 |
amPm |
yyyy-MM-dd h:mm:ss a zzz |
2024-03-15 7:30:00 AM PDT |
human |
MMMM d, yyyy 'at' h:mm a zzz |
March 15, 2024 at 7:30 AM PDT |
short |
M/d/yy h:mm a |
3/15/24 7:30 AM |
long |
EEEE, MMMM d, yyyy 'at' h:mm:ss a zzzz |
Friday, March 15, 2024 at 7:30:00 AM Pacific Daylight Time |
rfc2822 |
EEE, d MMM yyyy HH:mm:ss xx |
Fri, 15 Mar 2024 07:30:00 -0700 |
iso8601 |
yyyy-MM-dd'T'HH:mm:ssxxx |
2024-03-15T07:30:00-07:00 |
import { formatWithPattern, FORMAT_PATTERNS, DEFAULT_FORMAT_PATTERN } from 'clockworktz'
formatWithPattern('2024-03-15T14:30:00Z', 'America/Los_Angeles', 'human')
// 'March 15, 2024 at 7:30 AM PDT'
FORMAT_PATTERNS.iso8601 // "yyyy-MM-dd'T'HH:mm:ssxxx"
DEFAULT_FORMAT_PATTERN // 'yyyy-MM-dd HH:mm:ss zzz'
Helpers
formatFor(instant, zone, useCase)
Formats for a common purpose. In Europe/London, 2024-03-15T14:30:00Z gives:
useCase |
Output |
|---|---|
display |
2024-03-15 14:30:00 GMT |
log |
2024-03-15T14:30:00+00:00 |
api |
2024-03-15T14:30:00+00:00 |
filename |
2024-03-15_14-30-00 |
human |
March 15, 2024 at 2:30 PM GMT |
formatRange(start, end, zone, options?)
Formats a range. When both ends fall on the same local day, the date is shown once:
import { formatRange } from 'clockworktz'
formatRange('2024-03-15T14:30:00Z', '2024-03-15T16:00:00Z', 'Europe/London')
// '2024-03-15 14:30 – 16:00 GMT'
formatRange('2024-03-15T14:30:00Z', '2024-03-17T16:00:00Z', 'Europe/London', {
pattern: 'MMM d HH:mm',
})
// 'Mar 15 14:30 – Mar 17 16:00'
| Option | Default | Description |
|---|---|---|
pattern |
FORMAT_PATTERNS.default |
Pattern for each end when the days differ |
separator |
' – ' |
Text between the two ends |
sameDay |
true |
Collapse same-day ranges; false always uses pattern |
formatDuration(start, end, options?)
The absolute time between two instants in words:
import { formatDuration } from 'clockworktz'
formatDuration('2024-03-15T14:30:00Z', '2024-03-17T16:45:30Z')
// '2 days, 2 hours'
formatDuration('2024-03-15T14:30:00Z', '2024-03-17T16:45:30Z', {
units: ['hours', 'minutes', 'seconds'],
precision: 3,
})
// '50 hours, 15 minutes, 30 seconds'
| Option | Default | Description |
|---|---|---|
units |
['days', 'hours', 'minutes'] |
Units to use, largest first |
precision |
2 |
Maximum number of units in the output |
Durations measure elapsed time, so a "day" is always 24 hours, even across a DST change.
formatRelative(instant, zone, relativeTo?)
"2 hours ago" or "in 3 days" for anything within a week; beyond that, the date in zone:
import { formatRelative } from 'clockworktz'
const now = '2024-03-15T14:30:00Z'
formatRelative('2024-03-15T12:30:00Z', 'UTC', now) // '2 hours ago'
formatRelative('2024-03-18T14:30:00Z', 'UTC', now) // 'in 3 days'
formatRelative('2024-04-15T14:30:00Z', 'Asia/Tokyo', now) // '2024-04-15'
relativeTo defaults to the current time.
formatNow(zone, pattern?)
format(new Date(), zone, pattern).
formatOffset(offsetMinutes)
Formats an offset in minutes as ±HH:mm:
import { formatOffset } from 'clockworktz'
formatOffset(345) // '+05:45'
formatOffset(-570) // '-09:30'
formatOffset(0) // '+00:00'
Versus Intl.DateTimeFormat
Intl.DateTimeFormat is great for locale-appropriate output ("15/03/2024" vs "3/15/2024"). Use clockworktz's formatter when you need an exact, stable layout (logs, filenames, APIs, UI with a fixed design) or tokens Intl doesn't give you directly, like xxx. The two work together: pass the same zone to both.