{: .no_toc }

{: .no_toc .text-delta }

- TOC {:toc}

Number skeletons are a locale-agnostic way to configure a `NumberFormatter`

in ICU. Number skeletons work in `MessageFormat`

.

Number skeletons consist of case-sensitive tokens that correspond to settings in ICU `NumberFormatter`

. For example, to format a currency in compact notation with the sign always shown, you could use this skeleton:

sign-always compact-short currency/GBP

* Since ICU 67*, you can also use more concise syntax:

+! K currency/GBP

To use a skeleton in `MessageFormat`

, use the “number” type and prefix the skeleton with `::`

{0, number, :: +! K currency/GBP}

The ICU `toSkeleton()`

API outputs the long-form skeletons, but all parts of ICU that read user-specified number skeletons accept both long-form and concise skeletons.

A token consists of a *stem* and zero or more *options*. The stem is what occurs before the first `"/"`

character in a token, and the options are each of the subsequent `"/"`

-delimited strings. For example, `"compact-short"`

and “currency” are stems, and `"GBP"`

is an option.

Tokens are space-separated, with exceptions for concise skeletons listed at the end of this document.

Stems might also be dynamic strings (not a fixed list); these are called *blueprint stems*. For example, to format a number with 2-3 significant digits, you could use the following stem:

@@#

A few examples of number skeletons are shown below. The list of available stems and options can be found below in Skeleton Stems and Options.

Long Skeleton | Concise Skeleton | Input | en-US Output | Comments |
---|---|---|---|---|

`percent` | `%` | 25 | 25% | |

`.00` | `.00` | 25 | 25.00 | Equivalent to `Precision::fixedFraction(2)` |

`percent .00` | `% .00` | 25 | 25.00% | |

`scale/100` | `scale/100` | 0.3 | 30 | Multiply by 100 before formatting |

`percent scale/100` | `%x100` | 0.3 | 30% | |

`measure-unit/length-meter` | `unit/meter` | 5 | 5 m | `UnitWidth` defaults to `Short` |

`measure-unit/length-meter` `unit-width-full-name` | `unit/meter` `unit-width-full-name` | 5 | 5 meters | |

`currency/CAD` | `currency/CAD` | 10 | CA$10.00 | |

`currency/CAD` `unit-width-narrow` | `currency/CAD` `unit-width-narrow` | 10 | $10.00 | Use the narrow symbol variant |

`compact-short` | `K` | 5000 | 5K | |

`compact-long` | `KK` | 5000 | 5 thousand | |

`compact-short` `currency/CAD` | `K currency/CAD` | 5000 | CA$5K | |

- | - | 5000 | 5,000 | |

`group-min2` | `,?` | 5000 | 5000 | Require 2 digits in group for separator |

`group-min2` | `,?` | 15000 | 15,000 | |

`sign-always` | `+!` | 60 | +60 | Show sign on all numbers |

`sign-always` | `+!` | 0 | +0 | |

`sign-except-zero` | `+?` | 60 | +60 | Show sign on all numbers except 0 |

`sign-except-zero` | `+?` | 0 | 0 | |

`sign-accounting` `currency/CAD` | `() currency/CAD` | -40 | (CA$40.00) |

The full set of features supported by number skeletons is listed by category below.

Use one of the following stems to select compact or simple notation:

`compact-short`

or`K`

(concise)`compact-long`

or`KK`

(concise)`notation-simple`

(or omit since this is default)

There are two ways to select scientific or engineering notation: using long-form syntax or concise syntax.

Start with the stem `scientific`

or `engineering`

. Those stems take the following optional options:

`/sign-xxx`

sets the sign display option for the exponent; see Sign.`/*ee`

sets exponent digits to “at least 2”; use`/*eee`

for at least 3 digits, etc., use**Prior to ICU 67**`/+ee`

instead of`/*ee`

.

For example, all the following skeletons are valid:

`scientific`

`scientific/sign-always`

`scientific/*ee`

`scientific/*ee/sign-always`

The following are examples of concise form:

Concise Skeleton | Equivalent Long-Form Skeleton |
---|---|

`E0` | `scientific` |

`E00` | `scientific/*ee` |

`EE+!0` | `engineering/sign-always` |

`E+?00` | `scientific/sign-except-zero/+ee` |

More precisely:

- Start with
`E`

for scientific or`EE`

for engineering. - Allow either
`+!`

or`+?`

as a concise sign display option. - Expect one or more
`0`

s. If more than one, set minimum integer digits.

The supported types of units are percent, currency, and measurement units. The following skeleton tokens are accepted:

`percent`

or`%`

(concise)- Special:
`%x100`

to scale the number by 100 and then format with percent `permille`

`base-unit`

`currency/XXX`

`measure-unit/aaaa-bbbb`

or`unit/bbb`

(concise)

The `percent`

, `permille`

, and `base-unit`

stems do not take any options.

The `currency`

stem takes one required option: the three-letter ISO code of the currency to be formatted.

The `measure-unit`

stem takes one required option: the unit identifier of the unit to be formatted. The full unit identifier is required: both the type and the subtype (for example, `length-meter`

).

The `unit`

stem is an alternative to `measure-unit`

that accepts a core unit identifier with the subtype but not the type (for example, `meter`

instead of `length-meter`

). It also supports variations allowed by UTS 35, including the per unit with the `-per-`

infix (for example, `unit/furlong-per-second`

).

To specify a unit to put in the denominator, use the following skeleton token. As with the `measure-unit`

stem, pass the unit identifier as the option:

`per-measure-unit/aaaa-bbbb`

Note that if the `unit`

stem is used, the denominator can be placed in the same token as the numerator.

The unit width can be specified by the following stems:

`unit-width-narrow`

`unit-width-short`

`unit-width-full-name`

`unit-width-iso-code`

`unit-width-hidden`

For more details, see `UNumberUnitWidth`

.

The precision category has more blueprint stems than most other categories; they are documented in detail below. The following non-blueprint stems are accepted:

`precision-integer`

(round to the nearest integer) --- accepts fraction-precision options`precision-unlimited`

(do not perform rounding; display all digits)`precision-increment/dddd`

(round to, a decimal number) --- see below`dddd`

`precision-currency-standard`

`precision-currency-cash`

To round to the nearest nickel, for example, use the skeleton `precision-increment/0.05`

. For more information on the decimal number syntax, see Scale.

The following are examples of fraction-precision stems:

Stem | Explanation | Equivalent C++ Code |
---|---|---|

`.00` | Exactly 2 fraction digits | `Precision::fixedFraction(2) ` |

`.00*` | At least 2 fraction digits | `Precision::minFraction(2)` |

`.##` | At most 2 fraction digits | `Precision::maxFraction(2) ` |

`.0#` | Between 1 and 2 fraction digits | `Precision::minMaxFraction(1, 2)` |

More precisely, the fraction precision stem starts with `.`

, then contains zero or more `0`

symbols, which implies the minimum fraction digits. Then it contains either a `*`

, for unlimited maximum fraction digits, or zero or more `#`

symbols, which implies the minimum fraction digits when added to the `0`

symbols.

Note that the stem `.`

is considered valid and is equivalent to `precision-integer`

.

Fraction-precision stems accept a single optional option: a number of significant digits. The options here correspond to the API functions on `FractionPrecision`

. Some options require specifying `r`

or `s`

for relaxed mode or strict mode. For more information, see the API docs for UNumberRoundingPriority.

Skeleton | Explanation | Equivalent C++ Code |
---|---|---|

`.##/@@@*` | At most 2 fraction digits, but guarantee at least 3 significant digits | `Precision::maxFraction(2)` `.withMinDigits(3)` |

`.##/@##r` | Same as above | `Precision::maxFraction(2)` `.withSignificantDigits(1, 3, RELAXED)` |

`.##/@@@r` | Same as above, but pad trailing zeros to at least 3 significant digits | `Precision::maxFraction(2)` `.withSignificantDigits(3, 3, RELAXED)` |

`.00/@##` | Exactly 2 fraction digits, but do not display more than 3 significant digits | `Precision::fixedFraction(2)` `.withMaxDigits(3)` |

`.00/@##s` | Same as above | `Precision::fixedFraction(2)` `.withSignificantDigits(1, 3, STRICT)` |

`.00/@##s` | Same as above, but pad trailing zeros to at least 3 significant digits | `Precision::fixedFraction(2)` `.withSignificantDigits(3, 3, STRICT)` |

Precisely, the option follows the syntax of the significant digits stem (see below), but one of the following must be true:

- Option has one or more
`@`

s followed by the wildcard character (`withMinDigits`

) - Option has exactly one
`@`

followed by zero or more`#`

s (`withMaxDigits`

) - Option has one or more
`@`

s followed by zero or more`#`

s and ends in`s`

or`r`

(`withSignificantDigits`

)

The following are examples of stems for significant figures:

Stem | Explanation | Equivalent C++ Code |
---|---|---|

`@@@` | Exactly 3 significant digits | `Precision::fixedSignificantDigits(3)` |

`@@@*` | At least 3 significant digits | `Precision::minSignificantDigits(3)` |

`@##` | At most 3 significant digits | `Precision::maxSignificantDigits(3)` |

`@@#` | Between 2 and 3 significant digits | `...::minMaxSignificantDigits(2, 3)` |

The precise syntax is very similar to fraction precision. The blueprint stem starts with one or more `@`

symbols, which implies the minimum significant digits. Then it contains either a `*`

, for unlimited maximum significant digits, or zero or more `#`

symbols, which implies the minimum significant digits when added to the `@`

symbols.

* Starting with ICU 69*, a new option called

`trailingZeroDisplay`

was added. To enable this in an ICU number skeleton, append `/w`

to any precision token:Skeleton | Explanation | Equivalent C++ Code |
---|---|---|

`.00/w` | Exactly 2 fraction digits, but hide them if they are all 0 | `Precision::fixedFraction(2)` `.trailingZeroDisplay(` `UNUM_TRAILING_ZERO_HIDE_IF_WHOLE)` |

`precision-curren` `cy-standard/w` | Currency rounding, but hide fraction digits if they are all 0 | `Precision::currency(UCURR_USAGE_STANDARD)` `.trailingZeroDisplay(` `UNUM_TRAILING_ZERO_HIDE_IF_WHOLE)` |

* Prior to ICU 67*, the symbol

`+`

was used for unlimited precision, instead of `*`

(for example, `.00+`

). For backwards compatibility, either `+`

or `*`

is accepted. This applies for both fraction digits and significant digits.The rounding mode can be specified by the following stems:

`rounding-mode-ceiling`

`rounding-mode-floor`

`rounding-mode-down`

`rounding-mode-up`

`rounding-mode-half-even`

`rounding-mode-half-down`

`rounding-mode-half-up`

`rounding-mode-unnecessary`

For more details, see Rounding Modes.

The following examples show how to specify integer width (minimum or maximum integer digits):

Long Form | Concise Form | Explanation | Equivalent C++ Code |
---|---|---|---|

`integer-width/*000` | `000` | At least 3 integer digits | `IntegerWidth::zeroFillTo(3)` |

`integer-width/##0` | - | Between 1 and 3 integer digits | `IntegerWidth::zeroFillTo(1)` `.truncateAt(3)` |

`integer-width/00` | - | Exactly 2 integer digits | `IntegerWidth::zeroFillTo(2)` `.truncateAt(2)` |

`integer-width/*` | - | Zero or more integer digits | `IntegerWidth::zeroFillTo(0) ` |

`integer-width-trunc` | - | Zero integer digits | `IntegerWidth::zeroFillTo(0)` `.truncateAt(0)` |

The long-form option starts with either a single `*`

symbol, signaling no limit on the number of integer digits (no * truncateAt*), or zero or more

`#`

symbols. It should then be followed by zero or more `0`

symbols, indicating the minimum integer digits (the argument to `zeroFillTo`

`*`

symbol, the maximum integer digits (the argument to `truncateAt`

`#`

symbols plus the number of `0`

symbols.The concise skeleton is simply one or more `0`

characters. This supports minimum integer digits but not maximum integer digits.

The special stem `integer-width-trunc`

covers the case when both * truncateAt* and

`zeroFillTo`

* Prior to ICU 67*, use the symbol

`+`

instead of `*`

.To specify the scale, use the following stem and option:

`scale/dddd`

where * dddd* is a decimal number. For example, the following are valid skeletons:

`scale/100`

(multiply by 100)`scale/1E2`

(same as above)`scale/0.5`

(multiply by 0.5)

The decimal number should conform to a standard decimal number syntax. In C++, it is parsed using the decimal number library described in LocalizedNumberFormatter::formatDecimal. In Java, it is parsed using BigDecimal. For maximum compatibility, it is highly recommended that your decimal number is able to be parsed by both engines.

The grouping strategy can be specified by the following stems:

`group-off`

or`,_`

(concise)`group-min2`

or`,?`

(concise)`group-auto`

(or omit since this is the default)`group-on-aligned`

or`,!`

(concise)`group-thousands`

(no concise equivalent)

For more details, see `UNumberGroupingStrategy`

.

The following stems are allowed for specifying the number symbols:

`latin`

(use Latin-script digits)`numbering-system/nnnn`

(use the`nnnn`

numbering system)

A custom `NDecimalFormatSymbols`

instance is not supported at this time.

The following stems specify sign display:

`sign-auto`

(or omit since this is the default)`sign-always`

or`+!`

(concise)`sign-never`

or`+_`

(concise)`sign-accounting`

or`()`

(concise)`sign-accounting-always`

or`()!`

(concise)`sign-except-zero`

or`+?`

(concise)`sign-accounting-except-zero`

or`()?`

(concise)`sign-negative`

or`+-`

(concise)`sign-accounting-negative`

or`()-`

(concise)

For more details, see `UNumberSignDisplay`

.

The following stems specify decimal separator display:

`decimal-auto`

`decimal-always`

For more details, see `UNumberDecimalSeparatorDisplay`

.