Date and time formatting
The formatting of dates and times varies greatly between locales (e.g. "Apr 24, 2023" in en-US
vs. "24 квіт. 2023 р." in uk-UA
). By using the formatting capabilities of next-intl
, you can handle all i18n differences in your Next.js app automatically.
If you're formatting dates and times, you should set up a global time zone.
Formatting dates and times
You can format plain dates that are not part of a message with the useFormatter
hook:
import {useFormatter} from 'next-intl';
function Component() {
const format = useFormatter();
const dateTime = new Date('2020-11-20T10:36:01.516Z');
// Renders "Nov 20, 2020"
format.dateTime(dateTime, {
year: 'numeric',
month: 'short',
day: 'numeric'
});
// Renders "11:36 AM"
format.dateTime(dateTime, {hour: 'numeric', minute: 'numeric'});
}
See the MDN docs about DateTimeFormat
(opens in a new tab) to learn more about the options that you can provide to the dateTime
function or try the interactive explorer for Intl.DateTimeFormat
(opens in a new tab).
How can I parse dates or manipulate them?
To parse dates, you can pass them to the Date
constructor (opens in a new tab).
Since next-intl
is only concerned with formatting dates, you can use a library like date-fns (opens in a new tab) to manipulate them.
import {subDays} from 'date-fns';
// Make sure your date string conforms to ISO 8601
const date = new Date('2020-11-20T10:36:01.516Z');
// 2020-11-18T10:36:01.516Z
const twoDaysAgo = subDays(date, 2);
Formatting relative time
Relative time durations can be formatted with a separate function:
import {useFormatter} from 'next-intl';
function Component() {
const format = useFormatter();
const dateTime = new Date('2020-11-20T08:30:00.000Z');
const now = new Date('2020-11-20T10:36:00.000Z');
// Renders "2 hours ago"
format.relativeTime(dateTime, now);
}
Note that values are rounded, so e.g. if 100 seconds have passed, "2 minutes ago" will be returned.
Supplying now
is necessary for the function to return consistent results. If you have configured a global value for now
on the provider, you can omit the second argument:
format.relativeTime(dateTime);
useNow
If you want the relative time value to update over time, you can do so with the useNow
hook:
import {useNow, useFormatter} from 'next-intl';
function Component() {
const now = useNow({
// Update every 10 seconds
updateInterval: 1000 * 10
});
const format = useFormatter();
const dateTime = new Date('2020-11-20T10:36:01.516Z');
// Renders e.g. "2 hours ago" and updates continuously
format.relativeTime(dateTime, now);
}
Dates and times within messages
Dates and times can be embedded within messages by using the ICU syntax.
{
"ordered": "Ordered on {orderDate, date, medium}"
}
These formats are supported out of the box: full
, long
, medium
and short
.
If you work with translators, it can be helpful for them to use an editor that supports the ICU syntax for dates and times (e.g. the Crowdin Editor (opens in a new tab)).
You can customize the formatting by using date skeletons:
{
"ordered": "Ordered on {orderDate, date, ::yyyyMd}"
}
Note the leading ::
that is used to indicate that a skeleton should be used.
These formats from ICU are supported:
Symbol | Meaning |
---|---|
G | Era designator |
y | Year |
M | Month in year |
L | Stand-alone month in year |
d | Day in month |
E | Day of week |
e | Local day of week |
c | Stand-alone local day of week |
a | AM/PM marker |
h | Hour [1-12] |
H | Hour [0-23] |
K | Hour [0-11] |
k | Hour [1-24] |
m | Minute |
s | Second |
z | Time zone |
Custom date and time formats
To use custom formats in messages, you can provide formatters based on DateTimeFormat
options (opens in a new tab) that can be referenced by name.
{
"ordered": "Ordered on {orderDate, date, short}"
}
t(
'orderDate',
{date: new Date('2020-11-20T10:36:01.516Z')},
{
dateTime: {
short: {
day: 'numeric',
month: 'short',
year: 'numeric'
}
}
}
);
To reuse date and time formats for multiple components, you can configure global formats.