学习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)到当前时间的秒数 ...
随机推荐
- 给 Arm 生态添把火,腾讯 Kona JDK Arm 架构优化实践
前言 Arm 架构以其兼具性能与功耗的特点,在智能终端以及嵌入式领域得到了广泛的使用,不断扩大其影响力.而在 PC 端以及数据中心,之前往往是 x86 架构在其中发挥着主要的作用.最近,随着人工智能. ...
- 剖析虚幻渲染体系(10)- RHI
目录 10.1 本篇概述 10.2 RHI基础 10.2.1 FRenderResource 10.2.2 FRHIResource 10.2.3 FRHICommand 10.2.4 FRHICom ...
- MongoDB-01-基础
mongodb逻辑结构 Mongodb 逻辑结构 MySQL逻辑结构 库 (database) 库 集合(collection) 表 文档(document) 数据行 安装部署 1 系统准备 1 这里 ...
- 【笔记】KNN之分类准确度
分类准确度 分类准确度 以sklearn中的手写数字datasets.load_digits为例,其是8*8的图形,具有64个特征值,类别由0到9 我们挑选出666这个图形,将其可视化 X = dig ...
- 解决docker删除加载失败的镜像报错
背景: 准备在vulhub复现weblogic反序列化漏洞时报错,环境加载失败准备删除weblogic镜像时报错: unable to delete 7d35c6cd3bcd (must be for ...
- 你真的熟悉ASP.NET MVC的整个生命周期吗?
一.介绍 我们做开发的,尤其是做微软技术栈的,有一个方向是跳不过去的,那就是MVC开发.我相信大家,做ASP.NET MVC 开发有的有很长时间,当然,也有刚进入这个行业的.无论如何,如果有人问你,你 ...
- NOIP 模拟 $36\; \rm Cicada 与排序$
题解 \(by\;zj\varphi\) 设 \(rk_{i,j}\) 表示第 \(i\) 个数最后在相同的数里排第 \(j\) 位的概率. 转移时用一个 \(dp\),\(dp_{i,j,0/1}\ ...
- bootstrap导航条报错 Uncaught TypeError: Cannot convert object to primitive value
原文: https://feiffy.cc/uncaught-typeerror-cannot-convert-object-to-primitive-value 最近发现我的博客页面移动端上下拉菜单 ...
- TypeScript 入门指南 【大白话】
前言 聊聊为何要学习TypeScript? 从开发角度来讲, TypeScript 作为强类型语言,对属性有类型约束.在日常开发中少了减少了不必要的因参数类型造成的BUG,当你在使用同事封装好的函数时 ...
- 【mysql】mysql简介及高手是如何练成的
1.什么是mysql MySQL 是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于Oracle 公司. Mysql 是开源的,可以定制的,采用了GPL 协议,你可以修改源码 ...