Format relative time expressions and handle pluralization rules for different locales. Provides locale-aware relative time formatting and plural rule selection for complex grammatical patterns.
Formats relative time expressions with locale-appropriate patterns and units.
/**
* Format relative time expressions with locale-appropriate patterns
* @param config - Configuration with locale, formats, and error handler
* @param getRelativeTimeFormat - RelativeTimeFormat factory function
* @param value - Numeric value for the relative time (positive for future, negative for past)
* @param unit - Time unit for the relative expression
* @param options - Relative time formatting options including custom formats
* @returns Formatted relative time string
*/
function formatRelativeTime(
config: {
locale: string;
formats: CustomFormats;
onError: OnErrorFn;
},
getRelativeTimeFormat: Formatters['getRelativeTimeFormat'],
value: number,
unit?: Intl.RelativeTimeFormatUnit,
options?: FormatRelativeTimeOptions
): string;Usage Examples:
import { formatRelativeTime, createFormatters } from "@formatjs/intl";
const config = {
locale: 'en-US',
formats: {
relative: {
short: { numeric: 'auto', style: 'short' },
long: { numeric: 'always', style: 'long' }
}
},
onError: console.error
};
const formatters = createFormatters();
// Basic relative time formatting
const pastDay = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'day'
);
// Result: "yesterday"
const futureHour = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
2,
'hour'
);
// Result: "in 2 hours"
const pastWeek = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'week'
);
// Result: "last week"
// Different units
const minutes = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-30,
'minute'
);
// Result: "30 minutes ago"
const years = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
5,
'year'
);
// Result: "in 5 years"
// Using custom formats
const shortStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'day',
{ format: 'short' }
);
// Result: "2 days ago" (style dependent)Determines the appropriate plural rule for a given number in the specified locale.
/**
* Determine appropriate plural rule for numbers in locale
* @param config - Configuration with locale and error handler
* @param getPluralRules - PluralRules factory function
* @param value - Number to determine plural rule for
* @param options - Plural rules options including ordinal/cardinal type
* @returns LDML plural rule ('zero', 'one', 'two', 'few', 'many', 'other')
*/
function formatPlural(
config: {
locale: string;
onError: OnErrorFn;
},
getPluralRules: Formatters['getPluralRules'],
value: number,
options?: FormatPluralOptions
): LDMLPluralRule;Usage Examples:
import { formatPlural, createFormatters } from "@formatjs/intl";
const config = {
locale: 'en-US',
onError: console.error
};
const formatters = createFormatters();
// Cardinal plurals (for counting)
const one = formatPlural(config, formatters.getPluralRules, 1);
// Result: "one"
const many = formatPlural(config, formatters.getPluralRules, 5);
// Result: "other"
const zero = formatPlural(config, formatters.getPluralRules, 0);
// Result: "other" (in English)
// Ordinal plurals (for ordering: 1st, 2nd, 3rd, 4th)
const first = formatPlural(config, formatters.getPluralRules, 1, {
type: 'ordinal'
});
// Result: "one"
const second = formatPlural(config, formatters.getPluralRules, 2, {
type: 'ordinal'
});
// Result: "two"
const third = formatPlural(config, formatters.getPluralRules, 3, {
type: 'ordinal'
});
// Result: "few"
const fourth = formatPlural(config, formatters.getPluralRules, 4, {
type: 'ordinal'
});
// Result: "other"Options for controlling relative time formatting behavior.
type FormatRelativeTimeOptions = Omit<Intl.RelativeTimeFormatOptions, 'localeMatcher'> & {
/** Named format reference from custom formats */
format?: string;
};
interface RelativeTimeFormatOptions {
/** Whether to use numeric output (always) or natural language (auto) */
numeric?: 'always' | 'auto';
/** Formatting style affecting verbosity */
style?: 'long' | 'short' | 'narrow';
}Usage Examples:
// Numeric vs automatic formatting
const numericAlways = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'day',
{ numeric: 'always' }
);
// Result: "1 day ago"
const numericAuto = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'day',
{ numeric: 'auto' }
);
// Result: "yesterday"
// Different styles
const longStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'hour',
{ style: 'long' }
);
// Result: "2 hours ago"
const shortStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'hour',
{ style: 'short' }
);
// Result: "2 hr. ago"
const narrowStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'hour',
{ style: 'narrow' }
);
// Result: "2h ago"Options for controlling plural rule selection.
type FormatPluralOptions = Omit<Intl.PluralRulesOptions, 'localeMatcher'>;
interface PluralRulesOptions {
/** Type of plural rules: cardinal for counting, ordinal for ordering */
type?: 'cardinal' | 'ordinal';
}
type LDMLPluralRule = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';Usage Examples:
// Cardinal vs ordinal plurals
const cardinalOne = formatPlural(config, formatters.getPluralRules, 21, {
type: 'cardinal'
});
// Result: "other" (21 items)
const ordinalOne = formatPlural(config, formatters.getPluralRules, 21, {
type: 'ordinal'
});
// Result: "one" (21st place)
const cardinal22 = formatPlural(config, formatters.getPluralRules, 22, {
type: 'cardinal'
});
// Result: "other"
const ordinal22 = formatPlural(config, formatters.getPluralRules, 22, {
type: 'ordinal'
});
// Result: "two" (22nd place)Comprehensive support for all relative time units.
Usage Examples:
// All standard time units
const second = formatRelativeTime(config, formatters.getRelativeTimeFormat, -30, 'second');
// Result: "30 seconds ago"
const minute = formatRelativeTime(config, formatters.getRelativeTimeFormat, -15, 'minute');
// Result: "15 minutes ago"
const hour = formatRelativeTime(config, formatters.getRelativeTimeFormat, -3, 'hour');
// Result: "3 hours ago"
const day = formatRelativeTime(config, formatters.getRelativeTimeFormat, 7, 'day');
// Result: "in 7 days"
const week = formatRelativeTime(config, formatters.getRelativeTimeFormat, 2, 'week');
// Result: "in 2 weeks"
const month = formatRelativeTime(config, formatters.getRelativeTimeFormat, -6, 'month');
// Result: "6 months ago"
const quarter = formatRelativeTime(config, formatters.getRelativeTimeFormat, 1, 'quarter');
// Result: "in 1 quarter"
const year = formatRelativeTime(config, formatters.getRelativeTimeFormat, -10, 'year');
// Result: "10 years ago"
// Special cases with auto numeric
const yesterday = formatRelativeTime(config, formatters.getRelativeTimeFormat, -1, 'day', {
numeric: 'auto'
});
// Result: "yesterday"
const tomorrow = formatRelativeTime(config, formatters.getRelativeTimeFormat, 1, 'day', {
numeric: 'auto'
});
// Result: "tomorrow"
const now = formatRelativeTime(config, formatters.getRelativeTimeFormat, 0, 'second', {
numeric: 'auto'
});
// Result: "now"Different locales have different relative time patterns and plural rules.
Usage Examples:
// Relative time in different locales
const englishPast = formatRelativeTime(
{ ...config, locale: 'en-US' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "2 days ago"
const spanishPast = formatRelativeTime(
{ ...config, locale: 'es-ES' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "hace 2 días"
const frenchPast = formatRelativeTime(
{ ...config, locale: 'fr-FR' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "il y a 2 jours"
const germanPast = formatRelativeTime(
{ ...config, locale: 'de-DE' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "vor 2 Tagen"
// Complex plural rules in different locales
const polishPlurals = [1, 2, 5, 21, 22, 25].map(n =>
formatPlural(
{ ...config, locale: 'pl-PL' },
formatters.getPluralRules,
n
)
);
// Result: ["one", "few", "many", "many", "few", "many"]
const russianPlurals = [1, 2, 5, 21, 22, 25].map(n =>
formatPlural(
{ ...config, locale: 'ru-RU' },
formatters.getPluralRules,
n
)
);
// Result: ["one", "few", "many", "one", "few", "many"]
// Arabic has six plural forms
const arabicPlurals = [0, 1, 2, 3, 11, 100].map(n =>
formatPlural(
{ ...config, locale: 'ar-SA' },
formatters.getPluralRules,
n
)
);
// Result: ["zero", "one", "two", "few", "many", "other"]Complex relative time scenarios and edge cases.
Usage Examples:
// Fractional values (rounded by the formatter)
const fractionalHour = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1.5,
'hour'
);
// Result: "1 hour ago" (rounded)
// Very large values
const centuriesAgo = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-200,
'year'
);
// Result: "200 years ago"
// Edge cases with zero
const zeroMinutes = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
0,
'minute',
{ numeric: 'auto' }
);
// Result: "now"
const zeroMinutesNumeric = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
0,
'minute',
{ numeric: 'always' }
);
// Result: "in 0 minutes"
// Default unit (when not specified)
const defaultUnit = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-5
// Default unit is 'second'
);
// Result: "5 seconds ago"Integration with ICU MessageFormat for complex pluralization.
Usage Examples:
// Using formatPlural result in message formatting
const count = 5;
const pluralRule = formatPlural(config, formatters.getPluralRules, count);
const messages = {
zero: 'No items',
one: 'One item',
two: 'Two items',
few: 'A few items',
many: 'Many items',
other: `${count} items`
};
const message = messages[pluralRule];
// Result: "5 items"
// Complex plural patterns with ICU MessageFormat
const complexMessage = intl.formatMessage(
{
id: 'item.count',
defaultMessage: `{count, plural,
=0 {No items}
=1 {One item}
=2 {Two items}
few {A few items (#)}
many {Many items (#)}
other {# items}
}`
},
{ count: 5 }
);
// Ordinal plurals for rankings
const position = 23;
const ordinalRule = formatPlural(config, formatters.getPluralRules, position, {
type: 'ordinal'
});
const ordinalSuffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
const ordinalText = `${position}${ordinalSuffixes[ordinalRule]}`;
// Result: "23rd"Define reusable relative time format configurations.
Usage Examples:
const intl = createIntl({
locale: 'en-US',
formats: {
relative: {
short: {
numeric: 'auto',
style: 'short'
},
verbose: {
numeric: 'always',
style: 'long'
},
compact: {
numeric: 'auto',
style: 'narrow'
}
}
}
});
// Use custom formats
const shortFormat = intl.formatRelativeTime(-1, 'day', { format: 'short' });
// Result: "1 day ago" or "yesterday" (depending on implementation)
const verboseFormat = intl.formatRelativeTime(-1, 'day', { format: 'verbose' });
// Result: "1 day ago"
const compactFormat = intl.formatRelativeTime(-2, 'hour', { format: 'compact' });
// Result: "2h ago"When using createIntl, relative time and plural methods are available on the instance.
Usage Examples:
import { createIntl } from "@formatjs/intl";
const intl = createIntl({
locale: 'en-US'
});
// Instance methods
const relativeTime = intl.formatRelativeTime(-3, 'day');
// Result: "3 days ago"
const pluralRule = intl.formatPlural(5);
// Result: "other"
// Dynamic relative time calculation
const getRelativeTime = (date: Date) => {
const now = new Date();
const diffInMs = date.getTime() - now.getTime();
const diffInMinutes = Math.round(diffInMs / (1000 * 60));
if (Math.abs(diffInMinutes) < 60) {
return intl.formatRelativeTime(diffInMinutes, 'minute');
}
const diffInHours = Math.round(diffInMinutes / 60);
if (Math.abs(diffInHours) < 24) {
return intl.formatRelativeTime(diffInHours, 'hour');
}
const diffInDays = Math.round(diffInHours / 24);
return intl.formatRelativeTime(diffInDays, 'day');
};
// Usage
const pastDate = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2 hours ago
const relativeText = getRelativeTime(pastDate);
// Result: "2 hours ago"