CakeFest 2024: The Official CakePHP Conference

La classe NumberFormatter

(PHP 5 >= 5.3.0, PHP 7, PHP 8, PECL intl >= 1.0.0)

Introduction

Les programmes stockent et manipulent des nombres en utilisant une représentation locale, binaire et indépendante. Lors de l'affichage d'un nombre, il est converti en une version particulière. Par exemple, un nombre tel que 12345.67 s'écrit "12,345.67" aux USA, "12 345,67" en France et "12.345,67" en Allemagne.

En appelant les méthodes fournies par NumberFormatter, vous pouvez formater les nombres, les montants de devises et les pourcentages, en fonctions des conventions locales. NumberFormatter prend en compte les conventions, ce qui fait que vous devez créer un nouvel objet NumberFormatter, pour chaque convention. Les méthodes de NumberFormatter, formatent des types primitifs comme des nombres décimaux, et produit une chaîne de caractères.

Pour les monnaies, vous pouvez utiliser le format monétaire pour créer un formateur qui retourne une chaîne, avec le symbole de devise approprié. Bien entendu, NumberFormatter ne connait pas les taux de changes, ce qui fait que l'affichage sera fait, quelqu'en soit la devise demandée. Cela signifie que le même nombre aura différentes valeurs monétaires en fonction de la configuration locale. Par exemple, le nombre 9988776.65 s'affichera :

  • 9 988 776,65 € en France
  • 9.988.776,65 € en Allemagne
  • $9,988,776.65 aux USA

Pour formater des pourcentages, vous devez créer un formateur local, avec un type de format pourcentage. Avec ce formateur, une fraction décimale telle que 0.75 sera affichée 75%.

Pour des formatages plus complexes, comme des nombres écrits littéralement, des formateurs à règles sont utilisés.

Synopsis de la classe

class NumberFormatter {
/* Constantes */
public const int PATTERN_DECIMAL;
public const int DECIMAL;
public const int CURRENCY;
public const int PERCENT;
public const int SCIENTIFIC;
public const int SPELLOUT;
public const int ORDINAL;
public const int DURATION;
public const int PATTERN_RULEBASED;
public const int IGNORE;
public const int CURRENCY_ACCOUNTING;
public const int DEFAULT_STYLE;
public const int ROUND_CEILING;
public const int ROUND_FLOOR;
public const int ROUND_DOWN;
public const int ROUND_UP;
public const int ROUND_HALFEVEN;
public const int ROUND_HALFDOWN;
public const int ROUND_HALFUP;
public const int PAD_BEFORE_PREFIX;
public const int PAD_AFTER_PREFIX;
public const int PAD_BEFORE_SUFFIX;
public const int PAD_AFTER_SUFFIX;
public const int PARSE_INT_ONLY;
public const int GROUPING_USED;
public const int MAX_INTEGER_DIGITS;
public const int MIN_INTEGER_DIGITS;
public const int INTEGER_DIGITS;
public const int MAX_FRACTION_DIGITS;
public const int MIN_FRACTION_DIGITS;
public const int FRACTION_DIGITS;
public const int MULTIPLIER;
public const int GROUPING_SIZE;
public const int ROUNDING_MODE;
public const int ROUNDING_INCREMENT;
public const int FORMAT_WIDTH;
public const int PADDING_POSITION;
public const int LENIENT_PARSE;
public const int POSITIVE_PREFIX;
public const int POSITIVE_SUFFIX;
public const int NEGATIVE_PREFIX;
public const int NEGATIVE_SUFFIX;
public const int PADDING_CHARACTER;
public const int CURRENCY_CODE;
public const int DEFAULT_RULESET;
public const int PUBLIC_RULESETS;
public const int PERCENT_SYMBOL;
public const int ZERO_DIGIT_SYMBOL;
public const int DIGIT_SYMBOL;
public const int MINUS_SIGN_SYMBOL;
public const int PLUS_SIGN_SYMBOL;
public const int CURRENCY_SYMBOL;
public const int EXPONENTIAL_SYMBOL;
public const int PERMILL_SYMBOL;
public const int PAD_ESCAPE_SYMBOL;
public const int INFINITY_SYMBOL;
public const int NAN_SYMBOL;
public const int TYPE_DEFAULT;
public const int TYPE_INT32;
public const int TYPE_INT64;
public const int TYPE_DOUBLE;
public const int TYPE_CURRENCY;
/* Méthodes */
public __construct(string $locale, int $style, ?string $pattern = null)
public static create(string $locale, int $style, ?string $pattern = null): ?NumberFormatter
public formatCurrency(float $amount, string $currency): string|false
public format(int|float $num, int $type = NumberFormatter::TYPE_DEFAULT): string|false
public getAttribute(int $attribute): int|float|false
public getErrorCode(): int
public getLocale(int $type = ULOC_ACTUAL_LOCALE): string|false
public getSymbol(int $symbol): string|false
public getTextAttribute(int $attribute): string|false
public parseCurrency(string $string, string &$currency, int &$offset = null): float|false
public parse(string $string, int $type = NumberFormatter::TYPE_DOUBLE, int &$offset = null): int|float|false
public setAttribute(int $attribute, int|float $value): bool
public setPattern(string $pattern): bool
public setSymbol(int $symbol, string $value): bool
public setTextAttribute(int $attribute, string $value): bool
}

Constantes pré-définies

Ces styles sont utilisés par numfmt_create() pour définir le type de formateur.

NumberFormatter::PATTERN_DECIMAL
Format décimal défini par un modèle
NumberFormatter::DECIMAL
Format décimal
NumberFormatter::CURRENCY
Format monétaire
NumberFormatter::PERCENT
Format pourcentage
NumberFormatter::SCIENTIFIC
Format scientifique
NumberFormatter::SPELLOUT
Format littéral, basé sur des règles
NumberFormatter::ORDINAL
Format ordinal, basé sur des règles
NumberFormatter::DURATION
Format de durée, basé sur des règles
NumberFormatter::PATTERN_RULEBASED
Format de modèle, basé sur des règles
NumberFormatter::CURRENCY_ACCOUNTING
Format monétaire pour la comptabilité, par exemple, ($3.00) pour un montant de devise négatif au lieu de -$3.00. Disponible à partir de PHP 7.4.1 et ICU 53.
NumberFormatter::DEFAULT_STYLE
Format par défaut pour les conventions locales
NumberFormatter::IGNORE
Alias de PATTERN_DECIMAL

Ces constantes définissent la méthode d'analyse et de formatage des nombres. Ils doivent être utilisés comme arguments des fonctions numfmt_format() et numfmt_parse().

NumberFormatter::TYPE_DEFAULT
Dérive le type depuis le type de variable
NumberFormatter::TYPE_INT32
Formate / analyse un entier 32 bits
NumberFormatter::TYPE_INT64
Formate / analyse un entier 64 bits
NumberFormatter::TYPE_DOUBLE
Formate / analyse un nombre décimal
NumberFormatter::TYPE_CURRENCY
Formate / analyse une valeur monétaire. Obsolète à partir de PHP 8.3.0

Attributs de formats de nombre utilisés par numfmt_get_attribute() et numfmt_set_attribute().

NumberFormatter::PARSE_INT_ONLY
Analyse uniquement les entiers.
NumberFormatter::GROUPING_USED
Séparateur de groupes.
NumberFormatter::DECIMAL_ALWAYS_SHOWN
Affiche toujours une virgule décimale.
NumberFormatter::MAX_INTEGER_DIGITS
Nombre maximal de chiffres.
NumberFormatter::MIN_INTEGER_DIGITS
Nombre minimal de chiffres.
NumberFormatter::INTEGER_DIGITS
Nombre de chiffres.
NumberFormatter::MAX_FRACTION_DIGITS
Nombre maximal de décimales.
NumberFormatter::MIN_FRACTION_DIGITS
Nombre minimal de décimales.
NumberFormatter::FRACTION_DIGITS
Nombre de décimales.
NumberFormatter::MULTIPLIER
Multiplicateur.
NumberFormatter::GROUPING_SIZE
Taille de regroupement.
NumberFormatter::ROUNDING_MODE
Mode d'arrondi.
NumberFormatter::ROUNDING_INCREMENT
Incrément d'arrondi.
NumberFormatter::FORMAT_WIDTH
La largeur de complément pour le formattage d'un nombre.
NumberFormatter::PADDING_POSITION
La position à laquelle le complément se fait. Voyez les constantes de complément pour avoir les différentes valeurs possibles.
NumberFormatter::SECONDARY_GROUPING_SIZE
Taille secondaire de groupement.
NumberFormatter::SIGNIFICANT_DIGITS_USED
Utilise les chiffres significatifs.
NumberFormatter::MIN_SIGNIFICANT_DIGITS
Nombre minimum de chiffres significatifs.
NumberFormatter::MAX_SIGNIFICANT_DIGITS
Nombre maximum de chiffres significatifs.
NumberFormatter::LENIENT_PARSE
Mode d'analyse utilisé par les formats à règles.

Attributs de texte pour les formats de nombres, utilisés par numfmt_get_text_attribute() et numfmt_set_text_attribute().

NumberFormatter::POSITIVE_PREFIX
Préfixe positif.
NumberFormatter::POSITIVE_SUFFIX
Suffixe positif.
NumberFormatter::NEGATIVE_PREFIX
Préfixe négatif.
NumberFormatter::NEGATIVE_SUFFIX
Suffixe négatif.
NumberFormatter::PADDING_CHARACTER
Le caractère à utiliser pour compléter les formats jusqu'à la taille.
NumberFormatter::CURRENCY_CODE
Le code de devise ISO.
NumberFormatter::DEFAULT_RULESET
Le jeu de règles par défaut. Il est uniquement utilisable avec les formatteurs à règles.
NumberFormatter::PUBLIC_RULESETS
Le jeu de règles publiques. Ceci est uniquement disponible avec les formatteurs à règles. C'est un attribut en lecture seule. Les règles publiques sont retournées sous forme d'une seule chaîne, et chaque règle est délimitée par un point-virgule ';'.

Les symboles de format utilisés par numfmt_get_symbol() et numfmt_set_symbol().

NumberFormatter::DECIMAL_SEPARATOR_SYMBOL
Le séparateur décimal.
NumberFormatter::GROUPING_SEPARATOR_SYMBOL
Le séparateur de groupes.
NumberFormatter::PATTERN_SEPARATOR_SYMBOL
Le modèle de séparateur.
NumberFormatter::PERCENT_SYMBOL
Le signe de pourcentage.
NumberFormatter::ZERO_DIGIT_SYMBOL
Zéro.
NumberFormatter::DIGIT_SYMBOL
Un caractère représentant un chiffre dans un modèle.
NumberFormatter::MINUS_SIGN_SYMBOL
Le signe moins.
NumberFormatter::PLUS_SIGN_SYMBOL
Le signe plus.
NumberFormatter::CURRENCY_SYMBOL
Le symbole de devise.
NumberFormatter::INTL_CURRENCY_SYMBOL
Le symbole international de devise.
NumberFormatter::MONETARY_SEPARATOR_SYMBOL
Le séparateur monétaire.
NumberFormatter::EXPONENTIAL_SYMBOL
Le symbole d'exponentiel.
NumberFormatter::PERMILL_SYMBOL
Le symbol par mille.
NumberFormatter::PAD_ESCAPE_SYMBOL
Le caractère de protection des symboles.
NumberFormatter::INFINITY_SYMBOL
Le symbole de l'infini.
NumberFormatter::NAN_SYMBOL
Le symbole "n'est pas un nombre".
NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL
Le symbole des chiffres significatifs.
NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL
Le séparateur de groupes monétaires.

Les modes d'arrondi utilisés par les fonctions numfmt_get_attribute() et numfmt_set_attribute() avec l'attribut NumberFormatter::ROUNDING_MODE.

NumberFormatter::ROUND_CEILING
Mode d'arrondi vers l'infini positif.
NumberFormatter::ROUND_DOWN
Mode d'arrondi vers zéro.
NumberFormatter::ROUND_FLOOR
Mode d'arrondi vers l'infini négatif.
NumberFormatter::ROUND_HALFDOWN
Mode d'arrondi vers le plus proche entier, a moins qu'ils soient équidistants : arrondi inférieur dans ce cas.
NumberFormatter::ROUND_HALFEVEN
Mode d'arrondi vers le plus proche entier, a moins qu'ils soient équidistants : arrondi vers le nombre pair dans ce cas.
NumberFormatter::ROUND_HALFUP
Mode d'arrondi vers le plus proche entier, a moins qu'ils soient équidistants : arrondi supérieur dans ce cas.
NumberFormatter::ROUND_UP
Mode d'arrondi qui éloigne de zéro.

Valeurs de compléments utilisés par numfmt_get_attribute() et numfmt_set_attribute() avec l'attribut NumberFormatter::PADDING_POSITION.

NumberFormatter::PAD_AFTER_PREFIX
Caractères de compléments ajoutés après le préfixe.
NumberFormatter::PAD_AFTER_SUFFIX
Caractères de compléments ajoutés après le suffixe.
NumberFormatter::PAD_BEFORE_PREFIX
Caractères de compléments ajoutés avant le préfixe.
NumberFormatter::PAD_BEFORE_SUFFIX
Caractères de compléments ajoutés avant le suffixe.

Sommaire

add a note

User Contributed Notes 9 notes

up
48
giorgio dot liscio at email dot it
13 years ago
this class seems to be painful: it is not, formatting and parsing are highly customizable, but what you probably need is really simple:

if you want to localize a number use:

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::DECIMAL);
echo
$a->format(12345.12345) . "<br>"; // outputs 12.345,12
$a->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, 0);
$a->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, 100); // by default some locales got max 2 fraction digits, that is probably not what you want
echo $a->format(12345.12345) . "<br>"; // outputs 12.345,12345
?>

if you want to print money use:

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
echo
$a->format(12345.12345) . "<br>"; // outputs €12.345,12
?>

if you have money data stored as (for example) US dollars and you want to print them using the it-IT notation, you need to use

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
echo
$a->formatCurrency(12345, "USD") . "<br>"; // outputs $ 12.345,00 and it is formatted using the italian notation (comma as decimal separator)
?>

another useful example about currency (how to obtain the currency name by a locale string):

<?php
$frontEndFormatter
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
$adminFormatter = new \NumberFormatter("en-US", \NumberFormatter::CURRENCY);
$symbol = $adminFormatter->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL); // got USD
echo $frontEndFormatter->formatCurrency(12345.12345, $symbol) . "<br>";
?>
up
1
stan at dragnev dot ca
3 years ago
Here's an example of how to use PATTERN_DECIMAL to print a number with two fraction digits, use () for negative numbers and pad to five characters to the left of the decimal point, using spaces as the padding character:

<?php

$fmt
= new NumberFormatter("en-CA", NumberFormatter::PATTERN_DECIMAL, "* #####.00 ;(* #####.00)");
echo
$fmt->format(-45.1);

// Outputs: " (45.10)"

?>

Note that the ; in the pattern denotes the beginning of a subpattern, which is used for negative numbers. Hence the brackets around the pattern after the semicolon.
up
0
Einenlum
2 months ago
Be aware that (at least with the locale 'fr-FR') NumberFormatter doesn't use spaces. It doesn't even use non breakable spaces (NBSP). It uses narrow non breakable spaces (NNBSP). This broke my tests.

<?php

$formatter
= new NumberFormatter(
'fr-FR',
NumberFormatter::DEFAULT_STYLE
);

$value = $formatter->format(100_000); // '100 000'

// If you want to replace narrow non breakable spaces with non breakable spaces:

str_replace("\u{202F}", "\u{00A0}", $value);

// If you want to replace it with a normal space

str_replace("\u{202F}", " ", $value);
up
0
gwyneth dot llewelyn at gwynethllewelyn dot net
1 year ago
When using the `NumberFormatter` class for pretty-printing currency in PHP 7.3 and 8+, it's not clear from the documentation that you can use the empty string "" as the locale for the constructor, and that will retrieve the default locale (whatever it has been set to in your environment).

`formatCurrency()`, by contrast, does not accept the empty string for the default currency symbol; it will display a 'generic' currency symbol instead (¤).

Tested with PHP 7.4.30, 8.0.21, 8.1.8 under Ubuntu Linux and 8.1.8 under macOS Big Sur (11.6.8). I tried under other alternatives (e.g. Linux running on ARM chips, PHP 7.3.3) but sadly the `NumberFormatter` library does not seem to be present (or could not be found) on those systems...
up
2
sudheer at binaryvibes dot co dot in
13 years ago
Sample script to print number in English.

<?php
$f
= new NumberFormatter("en", NumberFormatter::SPELLOUT);
echo
$f->format(123456);

?>

Produces the result:
one hundred twenty-three thousand four hundred fifty-six
up
-2
AF
3 years ago
Please pay attention to the Arabic decimal separator (https://en.wikipedia.org/wiki/Decimal_separator#Other_numeral_systems).

All the following conditions are true:
<?php
(new \NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) === '٫';
(new
\NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) == '٫';

(new
\NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) !== ',';
(new
\NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) != ',';
?>
up
-3
Joey
7 years ago
Be warned that this class sometimes lacks sufficient error output. I recently instantiated it while invalid pattern to the constructor.

php -r '$nf = new \NumberFormatter("tlh-KX.UTF8", \NumberFormatter::IGNORE, "{,,#;#}");var_dump($nf->format(5));'

Fatal error: Call to a member function format() on null in Command line code on line 1

Rather than emitting an error message or throwing an exception null is returned after calling new.

I'm not sure if it's fixed in PHP 7 but it's something to watch out for. Make sure you check your parameters very closely.
up
-1
jimbo2150 at gmail dot com
1 year ago
The NumberFormatter class can be used to convert integer numbers to Roman numerals without a custom function using an array of symbols and associated values:

<?php

function intToRomanNumeral(int $num) {
static
$nf = new NumberFormatter('@numbers=roman', NumberFormatter::DECIMAL);
return
$nf->format($num);
}

echo
intToRomanNumeral(2); // II

echo intToRomanNumeral(5); // V

echo intToRomanNumeral(10); // X

echo intToRomanNumeral(50); // L

echo intToRomanNumeral(57); // LVII
echo intToRomanNumeral(58); // LVIII

echo intToRomanNumeral(100); // C

echo intToRomanNumeral(150); // CL

echo intToRomanNumeral(1000); // M

echo intToRomanNumeral(10000); // ↂ

?>
up
-11
Adam
7 years ago
Good to know Numberformatter::SPELLOUT using soft hypens.

So, if you want to avoid it use preg_replace:

<?php
$azaz
= new NumberFormatter("hu-HU", NumberFormatter::SPELLOUT);
$text = preg_replace('~\x{00AD}~u', '', $azaz->format(123456));
print
$text;
?>
Output without preg_replace:
egy-­száz-­huszon-­három-­ezer négy-­száz-­ötven-­hat

Output with preg_replace:
egyszázhuszonháromezer négyszázötvenhat
To Top