学习PHP中的国际化日期格式化操作
对于国际化功能来说,日期相关的格式化操作也是一块重头戏,毕竟不同的时区,不同的国家对于日期的表示方式都会有些不同。今天我们主要来学习的就是国际化地表示日期相关的信息内容。
日期格式化
首先就是最直接的格式化能力。
$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 这些类型。
$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 AM
echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL),PHP_EOL;
// Saturday, November 21, 2020 at 8:45:06 AM China Standard Time
echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::NONE, IntlDateFormatter::FULL),PHP_EOL;
// 20201121 08:45 AM
echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL, 'zh-CN'),PHP_EOL;
// 2020年11月21日星期六 中国标准时间 上午8:45:06
echo 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; // en
echo $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 z
echo $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; // 9
echo $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
===============
关注公众号:【硬核项目经理】获取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料
知乎、公众号、抖音、头条搜索【硬核项目经理】
B站ID:482780532
学习PHP中的国际化日期格式化操作的更多相关文章
- 学习PHP中的国际化功能来查看货币及日期信息
做为一门在世界范围内广泛使用的编程语言,国际化能力往往是衡量一个编程语言是否能够大范围流行的重要内容.特别是对于 PHP 这种以 Web 页面编程为主战场的语言来说,国际化能力更是重中之重.在 PHP ...
- 学习PHP中国际化地数字格式处理
不知道大家有没有了解过,对于数字格式来说,西方国家会以三位为一个进位,使用逗号来分隔.比如,12345678,用标准的格式来表示的话就是 12,345,678 .不过我们中文其实并不会有这样的分隔符, ...
- 学习PHP中有趣的字符集国际化验证功能
今天的内容非常简单,不过也很有趣.不知道大家有没有经历过这样的事情,就是在某些字体下,0 和 O 不好区分,1 和 l 也是很难看清楚.当然,现在大部分的编辑器和 IDE 的默认字体都是会选择那些比较 ...
- PHP中的国际化日历类
在 PHP 的国际化组件中,还有一个我们并不是很常用的跟日期相关的操作类,它就是日历操作类.说是日历,其实大部分还是对日期时间的操作,一般也是主要用于日期的格式化和比较之类的.但是通常我们直接使用 d ...
- [Java 进阶]Java中的国际化
背景知识 现代软件开发,往往做出的应用程序不止给一个国家的人去使用.不同国家的人往往存在语言文字不通的问题.由此产生了国际化(internationalization).多语言(multi-langu ...
- javaweb学习总结(三十一)——国际化(i18n)
一.国际化开发概述 软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的.符合来访者阅读习惯的页面或数据. 国际化(internationaliz ...
- DAX和Power BI中的参考日期表
本文使用Power BI模板描述DAX中的引用Date表,可以在Analysis Services模型中使用相同的技术.在Dax Date Template页面下载最新版本的模板. 为什么引用Date ...
- Java中的时间日期处理
程序就是输入——>处理——>输出.对数据的处理是程序员需要着重注意的地方,快速.高效的对数据进行处理时我们的追求.其中,时间日期的处理又尤为重要和平凡,此次,我将把Java中的时间日期处理 ...
- php学习七:时间和日期
在学习php中的时间和日期的时候,必须要了解什么是时间戳,那么什么是时间戳呢,请看一下的定义 时间戳:从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数 ...
随机推荐
- CGO入门和OCR文字识别(非第三方API,有源码,效果好)实战
这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战 系列文章见: [第四天] GDB调试指南:C++中如何调试生产环境的程序? [第三天] IM敏感词算法原理和实现 [第二天] 现代IM架构研 ...
- 题解 Six(留坑)
传送门 考场上搞了个三进制状压,结果正确性假了-- 有想到从约数下手,但觉得就光预处理约数复杂度就爆炸就没往这边想-- 首先是关于约数个数的证明,再一次感谢战神: 因为 \(n = \prod p_i ...
- React性能优化总结
本文主要对在React应用中可以采用的一些性能优化方式做一下总结整理 前言 目的 目前在工作中,大量的项目都是使用react来进行开展的,了解掌握下react的性能优化对项目的体验和可维护性都有很大的 ...
- wpf 中的矩形的歪斜
<Grid> <Rectangle x:Name="rect12" Width="100" Opacity="1" Hei ...
- 使用git下载码云仓库文件步骤总结
从码云下载文件的两种方式(私服时) 1.让私服管理者复制链接,然后你加入私服: 2.生成公钥,让私服管理者添加你的公钥. 在eclipse中找到git,输入自己的登录账号和密码,下载文件到本地仓库,然 ...
- 八:Filter(过滤器)
一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...
- 六:使用Cookie进行会话管理
1.存储客户端的状态 因为Http协议是无状态的,也就是说每个客户访问服务器端资源时,服务器并不知道该客户端是谁,所以需要会话技术识别客户端的状态.会话技术是帮助服务器 记住客户端状态 2.会话技术 ...
- mzy git学习,初识git(一)
GIT学习 git工作区.暂存区.本地库.远程库 工作区:实际上我们工作的地方,进行写代码或者文件的地方. 暂存区:我们执行了git add 操作之后,就会被提交到暂存区. 本地库:其实最后我们需要执 ...
- Hibernate之关联关系
时间:2017-1-20 16:28 --一对多配置1.第一步:创建实体类 * 客户实体 * 订单实体 示例代码: /** * 客户实体 ...
- linux centos7 read 命令
2021-08-24 1. 命令简介 read 命令就是读取控制台输入,会将从键盘输入的数据分割成一个个字段依次存储在 parameter[0] .parameter[1] ......,若是没有指定 ...