On This Page
Date Utilities
The Date utilities format dates and durations for display. formatDate prints a Date through a token string, formatDuration prints a millisecond count the way a person reads it, '4m 2s', with a decimal form that is the inverse of toDuration.
Functions
formatDate
function formatDate(date, format = 'LLL', options = {})Formats a date according to the specified format string and options.
International Support This function uses
Intl.DateTimeFormatinternally, please refer to the associated docs for details on timezone and formatting usage. Formatter instances are cached internally for performance, so repeated calls with the same locale and timezone avoid re-creatingIntl.DateTimeFormatobjects.
Timezone Lookup You can use IANA.org’s guide to look up supported timezones.
Local Timezone Usage When the ‘local’ keyword is used for the timezone option, the function will use the local timezone of the environment where the code is running. This is particularly useful for displaying dates in the user’s local time without needing to detect the timezone programmatically.
Timezone Shorthand
formatDate accepts shorthand timezone aliases alongside full IANA names. The aliases are the timezones export, a shorthand-to-IANA map, and the same object formatDate.config.timezones holds, so a package that only needs the table imports it without the formatter. Abbreviations are ambiguous by nature (IST is Kolkata, Jerusalem, or Dublin depending on who you ask), so the picks are yours to remap once at app boot, through either name. Full IANA names always pass through untouched.
import { formatDate, timezones } from '@semantic-ui/utils';
formatDate.config.timezones = { // North America ET: 'America/New_York', CT: 'America/Chicago', MT: 'America/Denver', PT: 'America/Los_Angeles', AKT: 'America/Anchorage', HT: 'Pacific/Honolulu', AT: 'America/Halifax',
// South America BRT: 'America/Sao_Paulo',
// Europe UK: 'Europe/London', WET: 'Europe/London', CET: 'Europe/Paris', ECT: 'Europe/Paris', EET: 'Europe/Helsinki', IRST: 'Europe/Dublin',
// Australia/Oceania AET: 'Australia/Sydney', ACT: 'Australia/Adelaide', AWT: 'Australia/Perth', NZT: 'Pacific/Auckland',
// Asia IST: 'Asia/Kolkata', INST: 'Asia/Kolkata', JST: 'Asia/Tokyo', SGT: 'Asia/Singapore',};
// remap an ambiguous alias for your app, once, through either nametimezones.IST = 'Asia/Jerusalem';formatDate.config.timezones.IST; // 'Asia/Jerusalem'Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| date | Date | object | The date to format. A Temporal value holding an instant prints in its own timeZoneId, and a value that hands its instant over through toJSDate() reads the same way, unless timezone names a zone |
|
| format | string | ‘LLL’ | The format string (e.g., ‘YYYY-MM-DD’, ‘LT’, ‘LL’) |
| options | object | Additional formatting options |
Options
| Name | Type | Default | Description |
|---|---|---|---|
| locale | string | ‘default’ | The locale to use for formatting |
| hour12 | boolean | true | Whether to use 12-hour time. When false, the hh and h tokens output 24-hour values and the a token outputs an empty string. |
| timezone | string | ‘UTC’ | The timezone to use. Use 'local' for the browser’s local timezone. |
Returns
A formatted date string, or 'Invalid Date' if the input is not a valid date.
Format Tokens
| Token | Output | Example |
|---|---|---|
YYYY |
4-digit year | 2023 |
YY |
2-digit year | 23 |
MMMM |
Full month name | January |
MMM |
3-letter month | Jan |
MM |
Zero-padded month | 01 |
M |
Month number | 1 |
DD |
Zero-padded day | 05 |
D |
Day number | 5 |
Do |
Day with ordinal suffix | 5th |
dddd |
Full weekday name | Thursday |
ddd |
3-letter weekday | Thu |
HH |
24-hour padded | 14 |
hh |
12-hour padded (or 24-hour when hour12: false) |
02 |
h |
12-hour (or 24-hour when hour12: false) |
2 |
mm |
Zero-padded minutes | 05 |
ss |
Zero-padded seconds | 09 |
a |
am/pm (empty when hour12: false) |
pm |
Text inside square brackets is treated as a literal and passed through without replacement: [Today is] dddd outputs Today is Thursday.
Preset Formats
| Preset | Pattern | Example |
|---|---|---|
LT |
h:mm a |
3:34 pm |
LTS |
h:mm:ss a |
3:34:56 pm |
L |
MM/DD/YYYY |
05/18/2023 |
l |
M/D/YYYY |
5/18/2023 |
LL |
MMMM D, YYYY |
May 18, 2023 |
ll |
MMM D, YYYY |
May 18, 2023 |
LLL |
MMMM D, YYYY h:mm a |
May 18, 2023 3:34 pm |
lll |
MMM D, YYYY h:mm a |
May 18, 2023 3:34 pm |
LLLL |
dddd, MMMM D, YYYY h:mm a |
Thursday, May 18, 2023 3:34 pm |
llll |
ddd, MMM D, YYYY h:mm a |
Thu, May 18, 2023 3:34 pm |
Example
import { formatDate } from '@semantic-ui/utils';
const date = new Date('2023-05-15T14:30:00Z');
console.log(formatDate(date)); // "May 15, 2023 2:30 pm"console.log(formatDate(date, 'YYYY-MM-DD')); // "2023-05-15"console.log(formatDate(date, 'LT', { timezone: 'America/New_York' })); // "10:30 am"console.log(formatDate(date, 'LT', { timezone: 'ET' })); // "10:30 am" (shorthand)console.log(formatDate(date, 'LT', { timezone: 'local' })); // Formats using the local timezone
// 24-hour format — hh and h give 24h values, a gives empty stringconsole.log(formatDate(date, 'HH:mm', { hour12: false })); // "14:30"console.log(formatDate(date, 'hh:mm a', { hour12: false })); // "14:30 "
// Escaped literal textconsole.log(formatDate(date, '[Today is] dddd, MMMM Do, YYYY')); // "Today is Monday, May 15th, 2023"
// A Temporal value prints in its own timeZoneIdconsole.log(formatDate(Temporal.ZonedDateTime.from('2023-05-15T23:30:00+09:00[Asia/Tokyo]'), 'LT')); // "11:30 pm"console.log(formatDate(Temporal.Instant.from('2023-05-15T14:30:00Z'), 'LT')); // "2:30 pm" (an Instant has no zone, so UTC)formatDuration
function formatDuration(value, { format, decimals, unit, lossless, separator } = {})Formats a duration for display, or null when there is no duration to format. 242100 prints as '4m 2s', 300000 as '5m', 500 as '500ms', and the sign is kept. Accepts anything toDuration reads, so '90s' prints as '1m 30s' with no conversion in between.
format picks the form, the same word formatDate takes. 'units', the default, prints the two largest non-zero whole units with a space: '6m 30s', '1h 5m', '1d 5m'. 'clock' prints whole units and the remainder in the next, the way a lap time reads: 390000 is '6:30', an hour and five minutes '1:05:00', the hours unbounded past a day. Both read '49s' below a minute, round to the whole second (59600 is '1m' and '1:00'), and never print zero for a positive value (400 is '400ms'). Neither reads back through toDuration, which reads one quantity, and a word outside the three answers null like an unknown unit.
'decimal' prints one quantity in the largest unit it fills, 90000 as '1.5m'. It is the inverse of toDuration and the two share one grammar: every string the decimal form prints reads back through toDuration, and the unit ladder is spelled in toDuration’s vocabulary. decimals, lossless and unit apply to it alone.
decimals is a maximum, so '5m' never prints as '5.0m', and a value that rounds up to a whole unit promotes (3598200 is '1h' at one decimal, not '60m'). unit holds one unit so a column reads down in the same scale, printed as spelled. separator goes between the number and the unit, so { unit: 'minutes', separator: ' ' } gives '1.5 minutes'. A space is the one separator toDuration reads back, since its grammar allows one there and nothing else.
lossless is for a config view. The default picks the largest unit the value fills and rounds, so 100000 prints as '1.7m', which reads back as 102000. Under lossless the walk continues to the largest unit whose print reads back to exactly the same value, '100s', where the check is the very product toDuration computes. A value with no short exact form prints in a small unit (93784000 is '93784s'), which is the honest answer for a value nobody configured by hand.
Parameters
| Name | Type | Description |
|---|---|---|
| value | unknown | The milliseconds, or a duration expression |
| settings | object | Optional configuration |
Options
| Name | Type | Default | Description |
|---|---|---|---|
| decimals | number | formatDuration.config.decimals (1) |
The decimal form’s maximum decimal places, trailing zeros drop |
| unit | string | largest unit filled | The decimal form’s held unit, printed as spelled, any spelling toDuration reads ('s', 'minutes', 'hr') |
| lossless | boolean | formatDuration.config.lossless (false) |
The decimal form’s pick of the largest unit that reads back through toDuration to the same value |
| format | string | formatDuration.config.format ('units') |
'units' for '6m 30s' and '1h 5m', 'clock' for '6:30' and '1:05:00', 'decimal' for one unit with decimals |
| separator | string | formatDuration.config.separator ('') |
Text between the number and the unit, ' ' for '1.5 minutes' |
Returns
The formatted duration, or null if there is no duration to format.
Example
import { formatDuration, toDuration } from '@semantic-ui/utils';
console.log(formatDuration(500)); // '500ms'console.log(formatDuration(300000)); // '5m'console.log(formatDuration(242100)); // '4m 2s'console.log(formatDuration(3900000)); // '1h 5m'console.log(formatDuration(49400)); // '49s'console.log(formatDuration(-90000)); // '-1m 30s'console.log(formatDuration('90s')); // '1m 30s'console.log(formatDuration(390000, { format: 'clock' })); // '6:30'console.log(formatDuration(3900000, { format: 'clock' })); // '1:05:00'console.log(formatDuration(90000, { format: 'decimal' })); // '1.5m'console.log(formatDuration(1234567, { format: 'decimal', decimals: 3 })); // '20.576m'console.log(formatDuration(3598200, { format: 'decimal' })); // '1h'console.log(formatDuration(90000, { format: 'decimal', unit: 's' })); // '90s'console.log(formatDuration(90000, { format: 'decimal', unit: 'minutes', separator: ' ' })); // '1.5 minutes'console.log(formatDuration(100000, { format: 'decimal' })); // '1.7m'console.log(formatDuration(100000, { format: 'decimal', lossless: true })); // '100s'console.log(formatDuration('banana')); // null
// a config accepts '5m' on the way in and shows '5m' on the way outconst reuseAfter = toDuration(config.reuseAfter) ?? 300000;console.log(formatDuration(reuseAfter, { format: 'decimal', lossless: true })); // '5m'formatDuration.config
formatDuration.config holds the defaults for format ('units'), decimals, lossless, and separator, plus units, the ladder walked largest first. Each entry is a spelling toDuration.config.units holds, which is where the span comes from, so a unit is added to both. Edit it once at app boot and every call inherits it. Per-call settings still win.
import { formatDuration, toDuration } from '@semantic-ui/utils';
toDuration.config.units.y = 365.25 * 24 * 60 * 60 * 1000;formatDuration.config.units.unshift('y');
console.log(formatDuration(63115200000)); // '2y'console.log(toDuration('2y')); // 63115200000