The localization package provides methods to format dates, times, numbers, and prices according to the rules of a specific locale. For typography rules, see Microtypography.

#Dates

By default, we always display the date short with abbreviation. We never use other date formats, outside of the defined ones.

  • The year is not abbreviated.
  • The year is displayed when, the date spans across a year change or it's stored for a longer period (timestamp).
  • We always remove the leading "0" from the date numbers
  • For the short with abbreviation format, the abbreviations dot is removed.
  • In EU countries the date format is always in the format of the main language of the country (e.g. all languages in France are formatted the way fr-FR is).
NameTypeDefaultDescriptionControls
date *string | number | Date-

Target date to format

locale *"de-AT" | "de-CH" | "de-DE" | "de-FR" | "de-NL" | "de-BE" | "de-IT" | "de-LU" | "en-AT" | "en-CH" | "en-DE" | "en-FR" | "en-NL" | "en-BE" | "en-IT" | "en-LU" | "fr-AT" | "fr-CH" | ... 21 more ... | "nl-LU"-

Used locale for formatting

timeZone *"Europe/Zurich" | "Europe/Berlin" | "Europe/Paris" | "Europe/Amsterdam" | "Europe/Brussels" | "Europe/Rome" | "Europe/Luxembourg" | "Europe/Vienna"-

TimeZone

options{ variant?: "short"; weekday?: "long" | "short"; } | { variant: "medium"; } | { variant: "month-only"; }-

Formatting options

#Short with abbreviation

The default date format is short with abbreviation including the abbrevated da of the week.


Sa, 31.12.Di, 1.2.So, 30.1.Do, 1.12.
de-ATSa, 31.12.Di, 1.2.So, 30.1.Do, 1.12.
en-ATSat, 31.12.Tue, 1.2.Sun, 30.1.Thu, 1.12.
de-BESa, 31/12Di, 1/2So, 30/1Do, 1/12
en-BESat, 31/12Tue, 1/2Sun, 30/1Thu, 1/12
fr-BEsam, 31/12mar, 1/2dim, 30/1jeu, 1/12
nl-BEza, 31/12di, 1/2zo, 30/1do, 1/12
de-CHSa, 31.12.Di, 1.2.So, 30.1.Do, 1.12.
en-CHSat, 31.12.Tue, 1.2.Sun, 30.1.Thu, 1.12.
fr-CHsam, 31/12mar, 1/2dim, 30/1jeu, 1/12
it-CHsab, 31.12.mar, 1.2.dom, 30.1.gio, 1.12.
de-DESa, 31.12.Di, 1.2.So, 30.1.Do, 1.12.
en-DESat, 31.12.Tue, 1.2.Sun, 30.1.Thu, 1.12.
en-FRSat, 31/12Tue, 1/2Sun, 30/1Thu, 1/12
fr-FRsam, 31/12mar, 1/2dim, 30/1jeu, 1/12
en-ITSat, 31/12Tue, 1/2Sun, 30/1Thu, 1/12
it-ITsab, 31/12mar, 1/2dom, 30/1gio, 1/12
de-NLSa, 31-12Di, 1-2So, 30-1Do, 1-12
en-NLSat, 31-12Tue, 1-2Sun, 30-1Thu, 1-12
nl-NLza, 31-12di, 1-2zo, 30-1do, 1-12

#Medium date

In some cases we use the date medium, for example if a date range is spaning over new year's eve.

  • The abbreviated weekday is removed if the year is displayed
  • The year is displayed when the two dates in a range span a change of year

Note: There is a shorthand method for medium dates called formatMediumDate(). It works exactly the same as formatDate() but with a hardcoded variant: medium in the options.


31.12.20221.2.202230.1.20221.12.2022
de-AT31.12.20221.2.202230.1.20221.12.2022
en-AT31.12.20221.2.202230.1.20221.12.2022
de-BE31/12/20221/2/202230/1/20221/12/2022
en-BE31/12/20221/2/202230/1/20221/12/2022
fr-BE31/12/20221/2/202230/1/20221/12/2022
nl-BE31/12/20221/2/202230/1/20221/12/2022
de-CH31.12.20221.2.202230.1.20221.12.2022
en-CH31.12.20221.2.202230.1.20221.12.2022
fr-CH31/12/20221/2/202230/1/20221/12/2022
it-CH31.12.20221.2.202230.1.20221.12.2022
de-DE31.12.20221.2.202230.1.20221.12.2022
en-DE31.12.20221.2.202230.1.20221.12.2022
en-FR31/12/20221/2/202230/1/20221/12/2022
fr-FR31/12/20221/2/202230/1/20221/12/2022
en-IT31/12/20221/2/202230/1/20221/12/2022
it-IT31/12/20221/2/202230/1/20221/12/2022
de-NL31-12-20221-2-202230-1-20221-12-2022
en-NL31-12-20221-2-202230-1-20221-12-2022
nl-NL31-12-20221-2-202230-1-20221-12-2022

#Month only date

In some rare cases, day is not available in data, we use the month-only date format.

Note: In general, we avoid using this format, it's only used in defined special cases.


de-CHen-CHfr-FRit-ITnl-NL
2023-01-01Januar 2023January 2023janvier 2023gennaio 2023januari 2023
2023-02-01Februar 2023February 2023février 2023febbraio 2023februari 2023
2023-03-01März 2023March 2023mars 2023marzo 2023maart 2023
2023-04-01April 2023April 2023avril 2023aprile 2023april 2023
2023-05-01Mai 2023May 2023mai 2023maggio 2023mei 2023
2023-06-01Juni 2023June 2023juin 2023giugno 2023juni 2023
2023-07-01Juli 2023July 2023juillet 2023luglio 2023juli 2023
2023-08-01August 2023August 2023août 2023agosto 2023augustus 2023
2023-09-01September 2023September 2023septembre 2023settembre 2023september 2023
2023-10-01Oktober 2023October 2023octobre 2023ottobre 2023oktober 2023
2023-11-01November 2023November 2023novembre 2023novembre 2023november 2023
2023-12-01Dezember 2023December 2023décembre 2023dicembre 2023december 2023

#Dates in React components

In react components, the useLocalization() hook provides formatDate, by using the hook, there is no need to provide a locale.

import { useLocalization } from "@segments/localization";

const MediumDate = () => {
  const { formatDate } = useLocalization();
  return `Date: ${formatDate(date, { variant: "medium" })}`;
};

#Dates outside of React components

Outside of React components, the formatDate() method requires a locale.

import { formatDate, formatMediumDate } from "@segments/localization";

// usage with shorthand method
formatMediumDate(new Date(), "de-CH", "Europe/Zurich");

// regular usage
formatDate("2023-05-26", "de-CH", "Europe/Zurich");

#Time

Currently all locales use the same time format.

NameTypeDefaultDescriptionControls
date *string | number | Date-

Target date to format

locale *"de-AT" | "de-CH" | "de-DE" | "de-FR" | "de-NL" | "de-BE" | "de-IT" | "de-LU" | "en-AT" | "en-CH" | "en-DE" | "en-FR" | "en-NL" | "en-BE" | "en-IT" | "en-LU" | "fr-AT" | "fr-CH" | ... 21 more ... | "nl-LU"-

Used locale for formatting

timeZone *string-

TimeZone

#Time format

01:0002:0011:0013:0500:45
de-AT01:0002:0011:0013:0500:45
en-AT01:0002:0011:0013:0500:45
de-BE01:0002:0011:0013:0500:45
en-BE01:0002:0011:0013:0500:45
fr-BE01:0002:0011:0013:0500:45
nl-BE01:0002:0011:0013:0500:45
de-CH01:0002:0011:0013:0500:45
en-CH01:0002:0011:0013:0500:45
fr-CH01:0002:0011:0013:0500:45
it-CH01:0002:0011:0013:0500:45
de-DE01:0002:0011:0013:0500:45
en-DE01:0002:0011:0013:0500:45
en-FR01:0002:0011:0013:0500:45
fr-FR01:0002:0011:0013:0500:45
en-IT01:0002:0011:0013:0500:45
it-IT01:0002:0011:0013:0500:45
de-NL01:0002:0011:0013:0500:45
en-NL01:0002:0011:0013:0500:45
nl-NL01:0002:0011:0013:0500:45

#Time ranges

Time ranges are connected by the en-dash character \u2013 without any spaces, example 01:00–02:35

NameTypeDefaultDescriptionControls
endDate *string | number | Date-

End date to format

locale *"de-AT" | "de-CH" | "de-DE" | "de-FR" | "de-NL" | "de-BE" | "de-IT" | "de-LU" | "en-AT" | "en-CH" | "en-DE" | "en-FR" | "en-NL" | "en-BE" | "en-IT" | "en-LU" | "fr-AT" | "fr-CH" | ... 21 more ... | "nl-LU"-

Used locale for formatting

startDate *string | number | Date-

Start date to format

timeZone *"Europe/Zurich" | "Europe/Berlin" | "Europe/Paris" | "Europe/Amsterdam" | "Europe/Brussels" | "Europe/Rome" | "Europe/Luxembourg" | "Europe/Vienna"-

TimeZone

#Time range format

01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
de-AT01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
en-AT01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
de-BE01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
en-BE01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
fr-BE01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
nl-BE01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
de-CH01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
en-CH01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
fr-CH01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
it-CH01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
de-DE01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
en-DE01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
en-FR01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
fr-FR01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
en-IT01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
it-IT01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
de-NL01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
en-NL01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45
nl-NL01:00–02:0002:00–03:0011:00–12:0013:05–14:0500:45–01:45

#Time in React components

In React components, the useLocalization() hook provides formatTime, formatTimeRange, by using the hook, there is no need to provide a locale.

import { useLocalization } from "@segments/localization";

const TimeRange = () => {
  const { formatTimeRange } = useLocalization();
  return `Time range: ${formatTimeRange(startDate, endDate)}`;
};

#Time outside of React components

Outside of React components, the formatTime() or formatTimeRange() method can be used directly, by providing a locale and a time zone.

formatTime(new Date(), "de-CH", "Europe/Zurich");

#Relative time

Describes the timespan between now and a past date, in a human-readable format.

  • The relative time is always translated, into the current locale.
  • Examples: "2 hours ago" or "10 years ago".
NameTypeDefaultDescriptionControls
date *string | number | Date-

Target date to format

locale *"de-AT" | "de-CH" | "de-DE" | "de-FR" | "de-NL" | "de-BE" | "de-IT" | "de-LU" | "en-AT" | "en-CH" | "en-DE" | "en-FR" | "en-NL" | "en-BE" | "en-IT" | "en-LU" | "fr-AT" | "fr-CH" | ... 21 more ... | "nl-LU"-

Used locale for formatting

now *string | number | Date-

Used locale for formatting

timeZone *string-

TimeZone

#Examples by locale

de-CHen-CHfr-FRit-ITnl-NL
in 10 daysin 10 Tagenin 10 daysdans 10 jourstra 10 giorniover 10 dagen
in 2 daysübermorgenday after tomorrowaprès-demaindopodomaniovermorgen
in 1 daymorgentomorrowdemaindomanimorgen
now, until midnightheutetodayaujourd'huioggivandaag
past 60 secondsgerade ebenjust nowà l'instantproprio orazojuist
minutes agovor einer Minute1 minute agoil y a une minute1 minuto fa1 minuut geleden
10 minutes agovor 10 Minuten10 minutes agoil y a 10 minutes10 minuti fa10 minuten geleden
1 hour agovor einer Stunde1 hour agoil y a une heure1 ora fa1 uur geleden
10 hours agovor 10 Stunden10 hours agoil y a 10 heures10 ore fa10 uren geleden
1 day agovor einem Tag1 day agoil y a un jour1 giorno fa1 dag geleden
6 days agovor 6 Tagen6 days agoil y a 6 jours6 giorni fa6 dagen geleden
1 week agovor einer Woche1 week agoil y a une semaine1 settimana fa1 week geleden
3 weeks agovor 3 Wochen3 weeks agoil y a 3 semaines3 settimane fa3 weken geleden
1 month agovor einem Monat1 month agoil y a un mois1 mese fa1 maand geleden
10 months agovor 10 Monaten10 months agoil y a 10 mois10 mesi fa10 maanden geleden
1 year agovor einem Jahr1 year agoil y a un an1 anno fa1 jaar geleden
10 years agovor 10 Jahren10 years agoil y a 10 ans10 anni fa10 jaren geleden

#Numbers

Numbers refer to general numerical values such as quantities, sizes, or measurements.

  • Grouping numbers starts at 10 000, meaning 9999 and lower, are not grouped.
  • Grouping separator is the narrow no-break space character U+202F, example: 15 500
  • All locales use the same grouping separator.
NameTypeDefaultDescriptionControls
actual *number-

Target number to format

locale *"de-AT" | "de-CH" | "de-DE" | "de-FR" | "de-NL" | "de-BE" | "de-IT" | "de-LU" | "en-AT" | "en-CH" | "en-DE" | "en-FR" | "en-NL" | "en-BE" | "en-IT" | "en-LU" | "fr-AT" | "fr-CH" | ... 21 more ... | "nl-LU"-

Used locale for formatting

options *FormatNumberOptions<boolean>-

Formatting options

#Examples by locale

2020.56200020000200000.56
de-AT2020,56200020 000200 000,56
en-AT2020,56200020 000200 000,56
de-BE2020,56200020 000200 000,56
en-BE2020,56200020 000200 000,56
fr-BE2020,56200020 000200 000,56
nl-BE2020,56200020 000200 000,56
de-CH2020.56200020 000200 000.56
en-CH2020.56200020 000200 000.56
fr-CH2020.56200020 000200 000.56
it-CH2020.56200020 000200 000.56
de-DE2020,56200020 000200 000,56
en-DE2020,56200020 000200 000,56
en-FR2020,56200020 000200 000,56
fr-FR2020,56200020 000200 000,56
en-IT2020,56200020 000200 000,56
it-IT2020,56200020 000200 000,56
de-NL2020,56200020 000200 000,56
en-NL2020,56200020 000200 000,56
nl-NL2020,56200020 000200 000,56

#Numbers in React components

In React components, the useLocalization() hook provides formatNumber, by using the hook, there is no need to provide a locale.

import { useLocalization } from "@segments/localization";

const MyNumberComponent: FunctionComponent<{ sum: number }> = ({ sum }) => {
  const { formatNumber } = useLocalization();
  return `Number: ${formatNumber(sum)}`;
};

#Numbers outside of React components

Outside of React components, the formatNumber() method can be used directly, by providing a locale.

import { formatNumber } from "@segments/localization";

const formattedNumber = formatNumber(20.56, "de-CH");

#Numbers in specification tables

For specification tables of products use: { style: "specs" }


2020.56200020000200000.56
de-AT20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
en-AT20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
de-BE20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
en-BE20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
fr-BE20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
nl-BE20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
de-CH20 mAh20.56 mAh2000 mAh20 000 mAh200 000.56 mAh
en-CH20 mAh20.56 mAh2000 mAh20 000 mAh200 000.56 mAh
fr-CH20 mAh20.56 mAh2000 mAh20 000 mAh200 000.56 mAh
it-CH20 mAh20.56 mAh2000 mAh20 000 mAh200 000.56 mAh
de-DE20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
en-DE20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
en-FR20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
fr-FR20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
en-IT20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
it-IT20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
de-NL20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
en-NL20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh
nl-NL20 mAh20,56 mAh2000 mAh20 000 mAh200 000,56 mAh

#In React components

import { useLocalization } from "@segments/localization";
import type { FunctionComponent } from "react";

const MyTimeComponent: FunctionComponent<{ time: Date }> = ({ time }) => {
  const { formatTime } = useLocalization();
  return <span>Time: {formatTime(time)}</span>;
};

#Outside of React components

import { formatNumber } from "@segments/localization";

const price = formatNumber(20.56, "de-CH", { style: "specs", unit: "mAh" });

#Price

  • Currency is always prefixed to the number, example: CHF 20.56.
  • Decimal places without value are always represented with .– example: CHF 50.–
  • Grouping prices stars 10 000, meaning 9999 and lower, are not grouped.
  • Grouping separator is narrow no-break space U+202F, example: CHF 15 500.56

NameTypeDefaultDescriptionControls
locale *"de-AT" | "de-CH" | "de-DE" | "de-FR" | "de-NL" | "de-BE" | "de-IT" | "de-LU" | "en-AT" | "en-CH" | "en-DE" | "en-FR" | "en-NL" | "en-BE" | "en-IT" | "en-LU" | "fr-AT" | "fr-CH" | ... 21 more ... | "nl-LU"-

Used locale for formatting

options *FormatPriceOptions<boolean>-

Formatting options

price *number-

Target price to format

#Prices without currency

2020.56200020000200000.56-200000.56
de-AT20,–20,562000,–20 000,–200 000,56-200 000,56
en-AT20,–20,562000,–20 000,–200 000,56-200 000,56
de-BE20,–20,562000,–20 000,–200 000,56-200 000,56
en-BE20,–20,562000,–20 000,–200 000,56-200 000,56
fr-BE20,–20,562000,–20 000,–200 000,56-200 000,56
nl-BE20,–20,562000,–20 000,–200 000,56-200 000,56
de-CH20.–20.562000.–20 000.–200 000.56-200 000.56
en-CH20.–20.562000.–20 000.–200 000.56-200 000.56
fr-CH20.–20.562000.–20 000.–200 000.56-200 000.56
it-CH20.–20.562000.–20 000.–200 000.56-200 000.56
de-DE20,–20,562000,–20 000,–200 000,56-200 000,56
en-DE20,–20,562000,–20 000,–200 000,56-200 000,56
en-FR20,–20,562000,–20 000,–200 000,56-200 000,56
fr-FR20,–20,562000,–20 000,–200 000,56-200 000,56
en-IT20,–20,562000,–20 000,–200 000,56-200 000,56
it-IT20,–20,562000,–20 000,–200 000,56-200 000,56
de-NL20,–20,562000,–20 000,–200 000,56-200 000,56
en-NL20,–20,562000,–20 000,–200 000,56-200 000,56
nl-NL20,–20,562000,–20 000,–200 000,56-200 000,56

#Prices with currency

2020.56200020000200000.56-200000.56
de-ATEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
en-ATEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
de-BEEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
en-BEEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
fr-BEEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
nl-BEEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
de-CHCHF 20.–CHF 20.56CHF 2000.–CHF 20 000.–CHF 200 000.56CHF -200 000.56
en-CHCHF 20.–CHF 20.56CHF 2000.–CHF 20 000.–CHF 200 000.56CHF -200 000.56
fr-CHCHF 20.–CHF 20.56CHF 2000.–CHF 20 000.–CHF 200 000.56CHF -200 000.56
it-CHCHF 20.–CHF 20.56CHF 2000.–CHF 20 000.–CHF 200 000.56CHF -200 000.56
de-DEEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
en-DEEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
en-FREUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
fr-FREUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
en-ITEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
it-ITEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
de-NLEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
en-NLEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56
nl-NLEUR 20,–EUR 20,56EUR 2000,–EUR 20 000,–EUR 200 000,56EUR -200 000,56

#Prices in React components

In React components, the useLocalization() hook provides formatPrice, by using the hook, there is no need to provide a locale.

import { useLocalization } from "@segments/localization";

const MyPriceComponent: FunctionComponent<{ price: number }> = ({ price }) => {
  const { formatPrice } = useLocalization();
  return `Price: ${formatPrice(price)}`;
};

#Prices outside of React components

Outside of React components, the formatPrice() method can be used directly, by providing a locale.

import { formatPrice } from "@segments/localization";

const price = formatPrice(20.56, "de-CH", { currency: "CHF" });