---
title: "How do I format numbers, dates and currencies inside an ICU message?"
description: "Give the argument a type and a style, such as `{n, number}`, `{n, number, percent}`, `{d, date, long}` or `{t, time, short}`, or a skeleton such as `{price, number, ::currency/EUR}` and `{d, date, ::yMMMd}`. Pass raw values from code and let the message format them for its locale."
category: icu-message-format
date: 2026-10-09
canonical: https://localizely.com/i18n-questions/icu-message-format/how-do-i-format-numbers-dates-and-currencies-inside-an-icu-message/
---

# How do I format numbers, dates and currencies inside an ICU message?

Add a type and an optional style to the argument: `{n, number}`, `{n, number, percent}`, `{d, date, long}`, `{t, time, short}`. For anything the named styles do not cover, use a skeleton, which starts with `::`, for example `{price, number, ::currency/EUR}` or `{d, date, ::yMMMd}`. The message formats the raw value with the conventions of its own locale.

The named styles of ICU's `MessageFormat` are `integer`, `currency` and `percent` for numbers, and `short`, `medium`, `long` and `full` for dates and times. With the values 1234567.891, 0.25 and 9.5 and the date 9 October 2026, 15:04:

```icu-message-format
{count, number}
{count, number, integer}
{share, number, percent}
{price, number, ::currency/EUR}
{price, number, ::.00}
{when, date, long}
{when, time, short}
{when, date, ::yMMMd}
```

Formatted for `en-US` these give `1,234,567.891`, `1,234,568`, `25%`, `€9.50`, `9.50`, `October 9, 2026`, `3:04 PM` and `Oct 9, 2026`. Formatted for `de-DE` the same messages give `1.234.567,891`, `1.234.568`, `25 %`, `9,50 €`, `9,50`, `9. Oktober 2026`, `15:04` and `9. Okt. 2026`. Nothing in the message changes between the two; only the locale does.

Skeletons are locale-independent requests. A number skeleton combines stems such as `currency/EUR`, `.00` (exactly two fraction digits), `precision-integer`, `percent` and `compact-short` (1234567 becomes `1.2M`); the [number skeleton reference](https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html) lists them. A date skeleton names the fields you want, `yMMMd` for year, abbreviated month and day, and the locale supplies the order and punctuation (`Oct 9, 2026`, `9. Okt. 2026`, `2026年10月9日`); `j` asks for the locale's preferred hour cycle, so `{when, time, ::jm}` prints `3:04 PM` in English and `15:04` in German. Number skeletons in messages require ICU 62 and date and time skeletons ICU 64; [FormatJS](https://formatjs.github.io/docs/core-concepts/icu-syntax/) supports number skeletons and a subset of the date and time skeletons.

Pass raw values. Give the message a number and a date or timestamp and let it do the formatting. A string pre-formatted in code freezes one locale's conventions and stops the translator from changing the style, for example from `long` to `short` where the sentence is tight.

Pitfalls:

- `currency` without a code takes the currency from the locale's region; with a region-less locale such as `en` ICU prints the placeholder `¤9.50`. Prefer `::currency/EUR` with an explicit ISO code.
- The `percent` style multiplies by 100 (0.25 gives `25%`), the skeleton stem `percent` alone does not (`::percent` gives `0.25%`); use `::percent scale/100` for a fraction.

The [ICU message editor](/icu-message-editor/) shows the output per language.

Source: https://localizely.com/i18n-questions/icu-message-format/how-do-i-format-numbers-dates-and-currencies-inside-an-icu-message/
