View Source Cldr.Number.Format.Compiler (Cldr Numbers v2.32.0)

Compiles number patterns with a lexer/parser into patterns for fast runtime interpretation.

Number patterns affect how numbers are interpreted in a localized context. Here are some examples, based on the French locale. The "." shows where the decimal point should go. The "," shows where the thousands separator should go. A "0" indicates zero-padding: if the number is too short, a zero (in the locale's numeric set) will go there. A "#" indicates no padding: if the number is too short, nothing goes there. A "¤" shows where the currency sign will go. The following illustrates the effects of different patterns for the French locale, with the number "1234.567". Notice how the pattern characters ',' and '.' are replaced by the characters appropriate for the locale.

Number Pattern Examples

PatternCurrencyText
#,##0.##n/a1 234,57
#,##0.###n/a1 234,567
###0.#####n/a1234,567
###0.0000#n/a1234,5670
00000.0000n/a01234,5670
#,##0.00 ¤EUR1 234,57 €

The number of # placeholder characters before the decimal do not matter, since no limit is placed on the maximum number of digits. There should, however, be at least one zero someplace in the pattern. In currency formats, the number of digits after the decimal also do not matter, since the information in the supplemental data (see Supplemental Currency Data) is used to override the number of decimal places — and the rounding — according to the currency that is being formatted. That can be seen in the above chart, with the difference between Yen and Euro formatting.

Special Pattern Characters

Many characters in a pattern are taken literally; they are matched during parsing and output unchanged during formatting. Special characters, on the other hand, stand for other characters, strings, or classes of characters. For example, the '#' character is replaced by a localized digit for the chosen numberSystem. Often the replacement character is the same as the pattern character; in the U.S. locale, the ',' grouping character is replaced by ','. However, the replacement is still happening, and if the symbols are modified, the grouping character changes. Some special characters affect the behavior of the formatter by their presence; for example, if the percent character is seen, then the value is multiplied by 100 before being displayed.

To insert a special character in a pattern as a literal, that is, without any special meaning, the character must be quoted. There are some exceptions to this which are noted below.

Number Pattern Character Definitions

SymbolMeaning
0Digit
1..9'1' through '9' indicate rounding to the nearest n
@Significant digit

| Digit, omitting leading/trailing zeros

. | Decimal separator or monetary decimal separator

  •    | Minus sign

    , | Grouping separator

  •    | Prefix positive exponents with localized plus sign
    %Multiply by 100 and show as percentage
    Multiply by 1000 and show as per mille (aka “basis points”)
    ;Separates positive and negative subpatterns
    ¤Any sequence is replaced by the localized currency symbol
  •    | Pad escape, precedes pad character

    ' | Used to quote special characters in a prefix or suffix

A pattern contains a positive subpattern and may contain a negative subpattern, for example, "#,##0.00;(#,##0.00)". Each subpattern has a prefix, a numeric part, and a suffix. If there is no explicit negative subpattern, the implicit negative subpattern is the ASCII minus sign (-) prefixed to the positive subpattern. That is, "0.00" alone is equivalent to "0.00;-0.00". (The data in CLDR is normalized to remove an explicit subpattern where it would be identical to the explicit form.) If there is an explicit negative subpattern, it serves only to specify the negative prefix and suffix; the number of digits, minimal digits, and other characteristics are ignored in the negative subpattern. That means that "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)". However in the CLDR data, the format is normalized so that the other characteristics are preserved, just for readability.

Note: The thousands separator and decimal separator in patterns are always ASCII ',' and '.'. They are substituted by the code with the correct local values according to other fields in CLDR. The same is true of the - (ASCII minus sign) and other special characters listed above.

Extracted from Unicode number formats in TR35

Summary

Functions

Parse a number format definition and analyze it.

Extract the metadata from the format.

Extract the metadata from the format or raise an exception..

Returns an Elixir AST of a formatting pipeline that when executed produces the formatted output for a given format string.

A regular expression that can be used to split either a number format or a number itself.

Parse a number format definition

Returns a number placeholder symbol.

Scan a number format definition

Functions

Parse a number format definition and analyze it.

After parsing, reduce the format to a set of metrics that can then be used to format a number.

Link to this function

format_to_metadata(format)

View Source

Extract the metadata from the format.

The metadata is used to generate the formatted output. A numeric format is optional and in such cases no analysis is required.

Link to this function

format_to_metadata!(format)

View Source

Extract the metadata from the format or raise an exception..

The metadata is used to generate the formatted output. A numeric format is optional and in such cases no analysis is required.

Link to this function

formatting_pipeline(meta)

View Source

Returns an Elixir AST of a formatting pipeline that when executed produces the formatted output for a given format string.

Not all formats require all parts of the full formatting pipeline so by compiling only those parts of the pipeline that are required we produce an optimal code path.

A regular expression that can be used to split either a number format or a number itself.

Since it accepts characters that are not digits (like '#', '@' and ',') it cannot be used to validate a number. Its only use is to split a number or a format into parts for later processing.

Parse a number format definition

Using a yexx lexer, parse a number format definition into list of elements we can then interpret to format a number.

Example

iex> Cldr.Number.Format.Compiler.parse "¤ #,##0.00;¤-#,##0.00"
{:ok,
 [positive: [currency: 1, literal: " ", format: "#,##0.00"],
  negative: [currency: 1, minus: '-', format: :same_as_positive]]}
@spec placeholder(
  :decimal
  | :group
  | :exponent
  | :exponent_sign
  | :plus
  | :minus
  | :currency
) ::
  String.t()

Returns a number placeholder symbol.

  • symbol is one of :decimal, group, :exponent, :plus, :minus, :currency

These symbols are used in decimal number format and are replaced with locale-specific characters during number formatting.

Example

iex> Cldr.Number.Format.Compiler.placeholder(:plus)
"+"

Scan a number format definition

Using a leex lexer, tokenize a rule definition