学习PHP中国际化地数字格式处理

不知道大家有没有了解过,对于数字格式来说,西方国家会以三位为一个进位,使用逗号来分隔。比如,12345678,用标准的格式来表示的话就是 12,345,678 。不过我们中文其实并不会有这样的分隔符,另外像某些地区则是以空格为分隔的,这个我们马上通过代码就可以看到。其实在之前的文章中我们就已经接触过一点这方面的知识,学习php中的国际化功能来查看货币及日期信息,今天就来详细的学习一遍。至于为什么要格式化数字、货币这些内容呢?我们将在文章讲解中逐一说明。

数字标准格式

首先还是看我们开头介绍的标准数字格式。

$localeArr = ['en_US', 'zh_CN', 'ja_JP', 'de_DE', 'fr_FR', 'ar-IQ', 'ru_RU'];
foreach ($localeArr as $locale) {$fmt = new NumberFormatter($locale, NumberFormatter::DECIMAL);echo $locale . ':', $fmt->format(1234567.891234567890000), PHP_EOL;
}
// en_US:1,234,567.891
// zh_CN:1,234,567.891
// ja_JP:1,234,567.891
// de_DE:1.234.567,891
// fr_FR:1 234 567,891
// ar-IQ:١٬٢٣٤٬٥٦٧٫٨٩١
// ru_RU:1 234 567,891

我们先指定了许多的国家地区编码,然后循环它们,使用 NumberFormatter 对象来对他们进行实例化。第二个参数就是要实例化的格式类型,这里我们指定的是数字类型。然后使用 format() 方法就可以对指定的数字进行格式化地输出了。可以看到,德国是使用 . 来分隔进位,使用逗号来做为小数点。而法国和俄罗斯则是使用空格来表示进位,逗号表示小数点。其它国家则是沿用标准的英式表示。

对于很多财务及银行项目来说,标准数字格式非常有用。往往我们接触到比较多的是在汇款时要填写的普通数字、中文大写,而一些面向企业和涉外的公司财务也需要这种标准格式的数字来进行存根的记录。既然说到财务了,我们再看看货币格式的展示。

货币格式

foreach ($localeArr as $locale) {$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);echo $locale . ':', $fmt->format(1234567.891234567890000), PHP_EOL;echo $locale . ':', $fmt->formatCurrency(1234567.891234567890000, 'RUR'), PHP_EOL;
}
// en_US:$1,234,567.89
// en_US:RUR 1,234,567.89
// zh_CN:¥1,234,567.89
// zh_CN:RUR 1,234,567.89
// ja_JP:¥1,234,568
// ja_JP:RUR 1,234,567.89
// de_DE:1.234.567,89 €
// de_DE:1.234.567,89 RUR
// fr_FR:1 234 567,89 €
// fr_FR:1 234 567,89 RUR
// ar-IQ:١٬٢٣٤٬٥٦٨ د.ع.‏
// ar-IQ:١٬٢٣٤٬٥٦٧٫٨٩ RUR
// ru_RU:1 234 567,89 ₽
// ru_RU:1 234 567,89 р.

在这段代码中,我们使用了两种模式的输出。第一个是指定 NumberFormatter 的第二个参数为 CURRENCY ,也就是指定格式化为货币格式。其实就是为标准格式的数字前后增加了对应地区的代币符号。比如我们中国和日本通用的 ¥ ,一般是放在金额的前面,而欧洲的则使用 € 欧元标识放在金额的后面。

另一种形式就是 formatCurrency() 这个方法可以指定一个货币类型,如果不是这个类型的区域设置的话,就直接输出这个货币字符。在测试代码中,我们给定的是俄罗斯的老卢布,其它区域中会直接输出 RUR ,而在区域设置为俄罗斯时,输出的就是标准的老卢布符号(现在使用的是新卢布,符号是 ₽ ,老卢布就是 р.)。

详细的地区格式化样式

是不是感觉已经很高大上了?不不不,上面两种格式只是开胃菜,真正好玩的现在马上端给你。

$fmt = new NumberFormatter('zh_CN', NumberFormatter::PERCENT);
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 123 456 789 %
$fmt = new NumberFormatter('zh_CN', NumberFormatter::SCIENTIFIC);
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 1,2345678912345679E6
$fmt = new NumberFormatter('zh_CN', NumberFormatter::SPELLOUT);
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 一百二十三万四千五百六十七点八九一二三四五六七九
$fmt = new NumberFormatter('zh_CN', NumberFormatter::SPELLOUT);
echo $fmt->format(1234502.891234567890000), PHP_EOL; // 一百二十三万四千五百〇二点八九一二三四五六七九
$fmt = new NumberFormatter('zh_CN', NumberFormatter::ORDINAL);
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 第1,234,568
$fmt = new NumberFormatter('zh_CN', NumberFormatter::DURATION);
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 1,234,568

PERCENT 不多说了,百分比,就是增加了一个百分号,而且不是以标准格式输出的,会以空格进行进位分隔。SCIENTIFIC 就是我们常见的科学计数法,测试代码中的结果就是 1.xx 的 10 的 6 次方的意思。

SPELLOUT 就比较厉害了,按当前区域语言的拼写规则。没错,直接转换成了我们的中文表示。如果需要再转换成中文的大写,直接字符替换就可以了,这个绝对是这次文章的重大发现。之前在一家公司面试的时候就有人问过如何将数字转换成中文表示,因为很多的财务系统都需要这样的功能。不管是做帐还是处理发票,中文大写或小写都是系统自动输出的。当时还写了半天算法,如果大家自己写算法的时候除了需要注意单位外,零的表示也是非常重要的一点,有兴趣的朋友可以自己尝试一下。不过下回如果面试的时候有人问这个问题,那我直接就会甩出 NumberFormatter::SPELLOUT 这个神器了。

ORDINAL 是排序的表示,在中文中其实就是在前面增加了一个 第 字。DURATION 是基于持续时间规则的格式。这两种都会抛弃掉小数点。

格式化规则设置

虽说已经有这么多的规则格式供我们使用了,但大家的业务总是千奇百怪的,我们能不能定义自己的格式规则呢?既然这么写了,那当然是可以的啦。

var_dump($fmt->getPattern()); // string(8) "#,##0.##"
$fmt->setPattern("#0.# kg");
var_dump($fmt->getPattern()); // string(6) "0.# kg"
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 1234567.9 kg

看出来了吗?我们使用 setPattern() 方法来定义了一个带 kg 的格式规则,很显示,我们是需要一个表示重量的格式。然后仅保留一位小数点,不需要分隔符号。这样再次使用 format() 方法的时候就会按照我们指定的格式来进行格式化了。

属性操作

当然,除了直接设置规则格式外,我们还可以指定一些属性值来改变当前的格式效果。

$fmt = new NumberFormatter( 'zh_CN', NumberFormatter::DECIMAL );
echo "Digits: ".$fmt->getAttribute(NumberFormatter::MAX_FRACTION_DIGITS), PHP_EOL; // Digits: 3
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 1,234,567.891
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, 2);
echo "Digits: ".$fmt->getAttribute(NumberFormatter::MAX_FRACTION_DIGITS), PHP_EOL; // Digits: 2
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 1,234,567.89

这段代码中,我们通过 setAttribute() 来设置 MAX_FRACTION_DIGITS 的值,用于改变最大保留的小数点位数。当然,不仅限于这一个属性,还有很多别的可以修改的属性,大家可以自行查阅官方手册。

分隔符号设置

同样,我们可以直接修改格式化中的分隔符、小数点等使用的符号。直接使用 setSymbol() 方法就可以。

var_dump($fmt->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL)); // string(1) ","
$fmt->setSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, "*");
var_dump($fmt->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL)); // string(1) "*"
echo $fmt->format(1234567.891234567890000), PHP_EOL; // 1*234*567.891

与地区格式化关联的文本属性设置

我们还可以直接设置与地区格式化相关的一些文本信息,比如下面代码中使用 setTextAttribute() 修改了负号的表示。我们还可以使用这个方法修改间隔字符,货币编码等内容,大家可以自己对照官方文档测试学习。

var_dump($fmt->getTextAttribute(NumberFormatter::NEGATIVE_PREFIX)); // string(1) "-"
echo $fmt->format(-1234567.891234567890000), PHP_EOL;
$fmt->setTextAttribute(NumberFormatter::NEGATIVE_PREFIX, "负号 ");
var_dump($fmt->getTextAttribute(NumberFormatter::NEGATIVE_PREFIX)); // string(7) "负号 "
echo $fmt->format(-1234567.891234567890000), PHP_EOL; // 负号 1,234,567.891

获取地区信息

这两个方法就是简单地获取当前的地区信息了,之前在其它的文章中我们也讲过,VALID_LOCALE 是表示有效区域,ACTUAL_LOCALE 表示的是实际区域。

var_dump($fmt->getLocale(Locale::VALID_LOCALE)); // string(10) "zh_Hans_CN"
var_dump($fmt->getLocale(Locale::ACTUAL_LOCALE)); // string(10) "zh_Hans_CN"

字符转换为数字、货币格式

我们能够将数字进行格式化地输出,输出之后的内容因为增加了分隔符之类的内容,所以都会转成字符串,那么,我们能不能把已经格式化过的标准数字字符再转回数字类型呢?

$fmt = new NumberFormatter( 'zh_CN', NumberFormatter::DECIMAL );
$num = "1,234,567.891";
echo $fmt->parse($num)."n"; // 1234567.891
echo $fmt->parse($num, NumberFormatter::TYPE_INT32)."n"; // 1234567
$fmt = new NumberFormatter( 'zh_CN', NumberFormatter::CURRENCY );
echo $fmt->parseCurrency('¥1,234,567.89', $currency), PHP_EOL; // 1234567.89
var_dump($currency); // string(3) "CNY"

两个方法,第一个是 parse() 方法,将标准格式的数字字符串转回指定类型的数字,可以指定为 TYPE_INT32 、TYPE_INT64 、TYPE_DOUBLE 、TYPE_CURRENCY 等类型。另外一个方法是 parseCurrency() 方法,从名字就可以看出,它是将货币格式转回数字,并且,很重要的一点是,它的第二个引用参数,可以将货币符号的通用编码也返回回来,比如测试代码中返回的 CNY 代表的就是我们使用的人民币。

错误信息

最后我们来看看 NumberFormatter 中的错误信息如何获取。

echo $fmt->parseCurrency('1,234,567.89', $currency), PHP_EOL;
var_dump($fmt->getErrorCode()); // int(9)
var_dump(intl_is_failure($fmt->getErrorCode())); // bool(true)
var_dump($fmt->getErrorMessage()); // string(36) "Number parsing failed: U_PARSE_ERROR"

在这里我们使用非标准的货币字符串来使用 parseCurrency() 进行转换,parseCurrency() 必须接收的是带货币符号的内容,所以这里就产生了错误。我们使用 getErrorCode() 可以获取到错误码,使用 getErrorMessage() 可以获取到错误信息。另外是一个 intl_is_failure() 函数,用于根据错误码判断是否产生了区域语言问题的错误。

总结

又是大开眼界的一次学习旅程,中文小写格式的转换真的是之前完全不知道的,而货币的互相转换我觉得也完全可以应用到一些采集程序中,比如电商页面价格的采集分析。总之,还是感觉到收获满满的。另外,这一套 NumberFormatter 对象也是提供了面向过程的函数式使用方法的,比如 numfmt_create() ,记住是 numfmt_ 开头的函数哦,不要和 number_format() 相关的函数搞混了。

测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/4.学习PHP中国际化地数字格式处理.php

文章转自:PHP中国际化地数字格式处理_PHP-考高分网 (kaotop.com)http://www.kaotop.com/it/262343.html

PHP中国际化地数字格式处理相关推荐

  1. 学习PHP中国际化地数字格式处理

    不知道大家有没有了解过,对于数字格式来说,西方国家会以三位为一个进位,使用逗号来分隔.比如,12345678,用标准的格式来表示的话就是 12,345,678 .不过我们中文其实并不会有这样的分隔符, ...

  2. java国际化——Locale+数字格式

    [0]README 1) 本文部分文字描述转自 core java volume 2 , 测试源代码均为原创, 旨在理解 java国际化--Locale+数字格式 的基础知识 : 2) java 编程 ...

  3. 第十一章--FCF中的基本数字格式

    [AJava原创]FusionCharts Free中文开发指南[使用文档教程]第十一章--FCF中的基本数字格式 时间:2009-01-16 17:48    来源:AJava.org    作者: ...

  4. html中怎么判断数字格式是否,javascript中怎么判断是否是数字?

    JavaScript中判断是否是数字的方法:1.使用isNaN()函数判断.2.使用正则表达式/^[0-9]+.?[0-9]*/可以判断是否是数字.3.使用parseFloat()函数判断是否是数字. ...

  5. FusionCharts Free中文开发指南 第十一章--FCF中的基本数字格式

    在我们的 报表里,经常要对数值进行一些格式化,如小数位,千分位等等.这在FCF里实现起来非常容易.下面我们就来看看. 控制小数位位数 所有的FCF图形都支持decimalPrecision属性,这个属 ...

  6. [AJava]FusionCharts Free中文开发指南[使用文档教程]第十一章--FCF中的基本数字格式 ...

    在我们的报表里,经常要对数值进行一些格式化,如小数位,千分位等等.这在FCF里实现起来非常容易.下面我们就来看看. 控制小数位位数所有的FCF图形都支持decimalPrecision属性,这个属性是 ...

  7. java中自定义输入数字格式_Java 创建并使用自定义数字格式、35;###、####.#####和语言环境...

    import java.util.*; import java.text.*; /* nowjava - 时代Java 提 供 */ public class DecimalFormatDemo { ...

  8. Datagridview中数字格式列 不显示小数点前面的0

    用代码设置DataGridView中某列为数字格式,但当小数为0.*的时候,前面的0却不显示.只显示.*. 看网上有说: 调整本地设置,控制面板-区域和语言选项,在弹出框的区域选项卡中,选择自定义,在 ...

  9. Excel 2007中创建或删除自定义数字格式

    Excel 2007提供了许多内置数字格式,但如果这些格式无法满足您的需要,您可以自定义内置数字格式以便创建自己的数字格式. 创建自定义数字格式 1.打开要创建并存储自定义数字格式的工作簿. 2.在& ...

最新文章

  1. c++ make_pairpair
  2. http://blog.51cto.com/wbb827/1175634
  3. Python爬虫的框架有哪些?推荐这五个!
  4. exp/expdp中query参数的使用
  5. 关于vue项目的打包
  6. 处理网络请求qs、图片转base64的优劣
  7. java删除list元素的几种方式
  8. 上周热点回顾(6.5-6.11)
  9. 3.10 触发字检测
  10. 谈谈如何学习R语言基础教程
  11. xlsxwriter设置列宽_Python3之excel操作——xlsxwriter模块
  12. Windows NT 下载
  13. 三极管的下拉电阻作用是什么?
  14. 2021前端面试经常被问到的题(附答案)
  15. initialize
  16. ClouderaCDH安装配置说明
  17. 阿里巴巴开发规约之编程规约(1)
  18. 计算机win10开机音乐,Windows10系统更改开关机声音的两种方法
  19. Procmon 的使用
  20. Web在jsp页面中生成柱状图,折线图,饼状图

热门文章

  1. phpmyadin安装配置
  2. 苹果内购之不能超过99.99美金被拒绝
  3. 《了不起的盖茨比》----走出绿灯困境
  4. 任正非谈接班人要求:要具有对新技术与客户需求的深刻理解
  5. java 年龄_Java 计算年龄
  6. 【020期】面试官问:Java 遍历 Map 集合有几种方式?效率如何?
  7. 项目上线前出Bug,测试人该如何调整心态
  8. MD文档的表情mark
  9. 【实践与问题解决29】苹果系统如何做脚本控制手机自动手势
  10. HR赫莲娜携张雨绮、胡杏儿、杨丞琳等先锋女性诠释改变