$fmt = new IntlDateFormatter( "en_US" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/Los_Angeles',IntlDateFormatter::GREGORIAN );echo "en_US 格式化结果为: ".$fmt->format(time()), PHP_EOL;// en_US 格式化结果为: Friday, November 20, 2020 at 4:45:06 PM Pacific Standard Time$fmt = new IntlDateFormatter( "de-DE" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/Los_Angeles',IntlDateFormatter::GREGORIAN );echo "de_DE 格式化结果为: ".$fmt->format(IntlCalendar::createInstance()), PHP_EOL;// de_DE 格式化结果为: Freitag, 20. November 2020 um 16:45:06 Nordamerikanische Westküsten-Normalzeit$fmt = new IntlDateFormatter( "zh-CN" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'Asia/Shanghai',IntlDateFormatter::GREGORIAN );echo "zh-CN 格式化结果为: ".$fmt->format(time()), PHP_EOL;// zh-CN 格式化结果为: 2020年11月21日星期六 中国标准韶光 上午8:45:06

IntlDateFormatter 工具便是国际化组件中对付日期格式化的操作类。
它的布局参数很多,不过实在非常大略,第一个参数是国家区域设置,第二和第三个参数分别这天期和白天的显示格式,这个我们下段代码将演示。
第四个参数是时区设置,第五个参数是韶光规范,这里指定的是格里高利韶光。

利用 format() 方法就可以对韶光戳或者日历工具进行日期韶光的格式化。
它只能吸收这两种类型的参数并进行格式化。
它会根据 IntlDateFormatter 工具所设置的各种参数进行输出,比如输出的措辞是英语、德语、中文等,输出的韶光是按时区(中国8点,美国下午4点)。

对付日期和韶光的显示格式,我们可以利用几个 IntlDateFormatter 类的常量来表示,紧张有 FULL 、 SHORT 、MEDIUM、 LONG 这些类型。

php格式化时间进修PHP中的国际化日期格局化操作 Node.js

$fmt = new IntlDateFormatter( "zh-CN" ,IntlDateFormatter::SHORT, IntlDateFormatter::LONG, 'Asia/Shanghai',IntlDateFormatter::GREGORIAN );echo "zh-CN 格式化结果为: ".$fmt->format(time()), PHP_EOL;// zh-CN 格式化结果为: 2020/11/21 GMT+8 上午8:45:06

其余,布局函数的第六个参数是可以指定格式化的格式规则的。

$fmt = new IntlDateFormatter( "zh-CN" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'Asia/Shanghai',IntlDateFormatter::GREGORIAN, 'yyyy/MM/dd' );echo "zh-CN 格式化结果为: ".$fmt->format(time()), PHP_EOL;// zh-CN 格式化结果为: 2020/11/21根据指定工具格式化日期

上文中的 format() 方法我们看到只能利用韶光戳和日历工具类型。
实在还有另一种更强大的格式化方法,它便是 formatObject() 方法。
从名字可以推断出,它是根据指定的工具来格式化日期数据。

$cal = IntlCalendar::createInstance(new DateTimeZone('Asia/Shanghai'));echo IntlDateFormatter::formatObject($cal),PHP_EOL;// Nov 21, 2020, 8:45:06 AMecho IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL),PHP_EOL;// Saturday, November 21, 2020 at 8:45:06 AM China Standard Timeecho IntlDateFormatter::formatObject($cal, IntlDateFormatter::NONE, IntlDateFormatter::FULL),PHP_EOL;// 20201121 08:45 AMecho IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL, 'zh-CN'),PHP_EOL;// 2020年11月21日星期六 中国标准韶光 上午8:45:06echo IntlDateFormatter::formatObject($cal, "d 'of' MMMM y", 'zh-CN'), PHP_EOL;// 21 of 十一月 2020

最常用的依然是对日历工具的格式化,可以看到 formatObject() 方法的参数更多一些,它也可以直接指定日期和韶光的格式形式以及干系的措辞设置。
其余,它还可以指定丰富的输出规则,比如我们末了一段代码输出的是当天在这个月中是第几天。
在 PHP中的国际化日历类 这篇文章中,我们也利用过这个方法来进行测试,自定义的语法规则非常多,大家可以自己查阅 ICU 干系的文档。

除了对付日历类的格式化之外,formatObject() 方法还可以对 DateTime 工具进行日期格式化地输出。

$dt = new DateTime();echo IntlDateFormatter::formatObject($dt),PHP_EOL;// Nov 21, 2020, 8:45:06 AM

不过须要把稳的是,从官方文档的 Note 来看,formatObject() 的速率非常慢,在 PHP5 下面与 format() 方法有 10 倍旁边的差距,在 PHP7 下也有 3 倍旁边的差距。
以是说,如果不是有特殊的需求的话,只管即便还是不要利用 formatObject() 这个方法来格式化日期韶光。

反解析日期字符串

和之前我们在 学习PHP中国际化地数字格式处理 中讲过的一样,我们可以将工具或者韶光戳格式化为标准的字符串格式显示,那么能不能将这种标准的字符串格式数据再反转回来呢?

$fmt = new IntlDateFormatter( "en_US" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/Los_Angeles',IntlDateFormatter::GREGORIAN );$arr = $fmt->localtime($fmt->format(time()));print_r($arr);// Array// (// [tm_sec] => 1// [tm_min] => 59// [tm_hour] => 16// [tm_year] => 120// [tm_mday] => 20// [tm_wday] => 5// [tm_yday] => 325// [tm_mon] => 10// [tm_isdst] => 0// )echo $fmt->parse("Thursday, November 19, 2020 at 5:05:41 PM Pacific Standard Time"), PHP_EOL;// 1605834341

localtime() 方法便是用于解析给定的标准日期内容的,根据 IntlDateFormatter 初始化时的规则,将字符串的内容反向输出为一个数组,个中包含了年、月、日、时、分、秒等信息。
而 parse() 方法则是直接将给定的内容转换为对应的韶光戳。

$fmt = new IntlDateFormatter( "zh-CN" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'Asia/Shanghai',IntlDateFormatter::GREGORIAN );$arr = $fmt->localtime("2020年11月20日星期五 中国标准韶光 上午8:54:08");print_r($arr);// Array// (// [tm_sec] => 8// [tm_min] => 54// [tm_hour] => 8// [tm_year] => 120// [tm_mday] => 20// [tm_wday] => 5// [tm_yday] => 325// [tm_mon] => 10// [tm_isdst] => 0// )echo $fmt->parse("2020年11月20日星期五 中国标准韶光 上午8:54:08"), PHP_EOL;// 1605833648

不管是中英文都是良好支持的。

干系属性获取及设置日历类型信息

对付日历类型来说,只有两种类型的日历,GREGORIAN 和 TRADITIONAL,分别对应的是格里高利和传统日历。
在布局参数中我们可以通过第五个参数指定,也可以在工具利用的过程中利用 setCalendar() 方法来设置。
getCalendar() 方法用于获取当前设置的日期类型信息。

$fmt = new IntlDateFormatter( "en_US" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/Los_Angeles',IntlDateFormatter::GREGORIAN );echo $fmt->getCalendar(), PHP_EOL; // 1$fmt->setCalendar(IntlDateFormatter::TRADITIONAL);echo $fmt->getCalendar(), PHP_EOL; // 0日期和韶光类型

// 日期类型获取及设置$fmt = new IntlDateFormatter( "en_US" ,IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/Los_Angeles',IntlDateFormatter::GREGORIAN );echo $fmt->getDateType(), PHP_EOL; // 0$fmt = new IntlDateFormatter( "en_US" ,IntlDateFormatter::SHORT, IntlDateFormatter::FULL, 'America/Los_Angeles',IntlDateFormatter::GREGORIAN );echo $fmt->getDateType(), PHP_EOL; // 3// 韶光类型获取及设置echo $fmt->getTimeType(), PHP_EOL; // 0$fmt = new IntlDateFormatter( "en_US" ,IntlDateFormatter::SHORT, IntlDateFormatter::MEDIUM, 'America/Los_Angeles',IntlDateFormatter::GREGORIAN );echo $fmt->getTimeType(), PHP_EOL; // 2

对付日期和韶光类型来说,我们只能通过布局函数的参数进行指定,获取到的也是对应常量的值。

区域措辞信息

echo $fmt->getLocale(), PHP_EOL; // enecho $fmt->getLocale(Locale::VALID_LOCALE), PHP_EOL; // en_US

这个就不多做阐明了,之前的文章中都有,彷佛国际化干系组件的类中都会包含这两个方法。

格式规则获取及设置

我们可以在布局函数的第六个参数中指定格式化的规则,同时也可以对工具进行动态的设置。

echo $fmt->getPattern(), PHP_EOL; // M/d/yy, h:mm:ss a$fmt->setPattern('yyyyMMdd hh:mm:ss z');echo $fmt->getPattern(), PHP_EOL; // yyyyMMdd hh:mm:ss zecho $fmt->format(time()), PHP_EOL; // 20201120 04:59:01 PST

利用 setPattern() 设置格式规则之后,再次进行 formar() 便是以新的格式规则进行格式化了。

时区设置

首先我们来看一个 getTimezoneId() 方法。
它是直接获取时区内容的,也便是一个字符串。

echo $fmt->getTimezoneId(), PHP_EOL; // America/Los_Angeles// $fmt->setTimeZoneId('CN'); // PHP7 已删除// echo $fmt->getTimezoneId(), PHP_EOL;

不过在 PHP7 中已经删除了 setTimezoneId() 方法,现在推举是利用 setTimezone() 方法来设置时区信息,我们立时来看看。

var_dump($fmt->getTimezone());// object(IntlTimeZone)#4 (4) {// ["valid"]=>// bool(true)// ["id"]=>// string(19) "America/Los_Angeles"// ["rawOffset"]=>// int(-28800000)// ["currentOffset"]=>// int(-28800000)// }$fmt->setTimeZone('Asia/Shanghai');var_dump($fmt->getTimezone());// object(IntlTimeZone)#4 (4) {// ["valid"]=>// bool(true)// ["id"]=>// string(13) "Asia/Shanghai"// ["rawOffset"]=>// int(28800000)// ["currentOffset"]=>// int(28800000)// }$fmt->setTimeZone('GMT+00:30');var_dump($fmt->getTimezone());// object(IntlTimeZone)#4 (4) {// ["valid"]=>// bool(true)// ["id"]=>// string(9) "GMT+00:30"// ["rawOffset"]=>// int(1800000)// ["currentOffset"]=>// int(1800000)// }

与 getTimezoneId() 方法不同的是,getTimezone() 方法返回的是一个 IntlTimeZone 工具,关于这个工具的内容官方文档不全,很多方法参数都没有写,我也不好预测,以是不会写这个工具的文章,大家可以自己查阅干系的资料。
不过对付大略的设置时区来说,setTimezone() 方法可以直策应用字符串做为参数。
比如我们在上面的代码分别将美国洛杉矶的时区修正为中国上海以及GMT+00:30这两种时区。
对应地,如果我们再 format() 输出韶光的话,便是以当前时区的标准韶光为准进行输出了。

获取日历工具

本身在格式化数据的时候,我们就与日历工具打了很多交道,当然通过 IntlDateFormatter 工具我们也是可以得到日历信息的。

$cal = $fmt->getCalendarObject();var_dump( $cal->getType(), $cal->getTimeZone(), $cal->getLocale(Locale::VALID_LOCALE));// string(9) "gregorian"// object(IntlTimeZone)#3 (4) {// ["valid"]=>// bool(true)// ["id"]=>// string(9) "GMT+00:30"// ["rawOffset"]=>// int(1800000)// ["currentOffset"]=>// int(1800000)// }// string(5) "en_US"宽容能力

末了我们再看一下宽容能力,实在也便是一种严格模式的操作。
比如我们如果定义一个缺点的韶光,IntlDateFormatter 中的操作并不会报错,由于它默认是宽容处理的。

$fmt->setPattern('dd/mm/yyyy');var_dump($fmt->isLenient()); // bool(true)echo $fmt->parse('35/13/1955'), PHP_EOL;// -470449020

很明显,这个日期是一个缺点的日期。
通过 isLenient() 方法我们可以获取当前是否是宽容处理的状态。
我们现在将宽容处理的能力取消掉,再看看会是什么结果。

$fmt->setLenient(FALSE);echo $fmt->parse('35/13/1955'), PHP_EOL;// echo $fmt->getErrorCode(), PHP_EOL; // 9echo $fmt->getErrorMessage(), PHP_EOL; // Date parsing failed: U_PARSE_ERROR

parse() 方法没有任何输出了。
同时通过 getErrorCode() 和 getErrorMessage() 也看到了缺点信息。
这便是 IntlDateFormatter 工具中宽容处理的紧张能力。

总结

本日学习的内容比较多和零散,不过紧张都是 IntlDateFormatter 这个工具的内容。
数字和日期格式是国际化干系功能中最紧张的功能,也能够随时运用到我们的日常业务开拓中,大家可以多多地学习理解干系的知识。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/8.学习PHP中的国际化日期格式化操作.php

参考文档:

https://www.php.net/manual/zh/class.intldateformatter.php