为什么说这个 Calendar 扩展很好玩呢?因为你基本用不到它!这个扩展是一套关于日期历法的扩展,但是对于我们来说,它没有农历的相关操作,所以对于我们中国人来说这个扩展并没有什么实际的作用。不过这并不妨碍我们去了解学习它。

日期历法类型

对于正常情况下的日期操作来说,PHP 默认使用的是 UTC 时间,也就是国际标准时间,对于我们国家来说,需要在标准 UTC 的时间上加 8 来表示北京时间东八区。当然,也可以直接修改 php.ini 或者数据库中的时区相关参数来定义好日期时区。

标准时区对应的其实就是格里高利时间历法 Gregorian 。也就是我们现在最常用的公历、阳历日期。Calendar 扩展中除了这个标准的公历历法之外,还支持 犹太历法 Jewish 、 法历 French 以及另一个非常出名的 儒略历 Julian 。我们的 Gregorian 历法就是从 Julian 历中演化而来的,它们的差距并不大,但 犹太历 和 法历 的差距就比较大了,一会在下面的代码中我们将看到各种历法之间的差别。

关于这些历法的具体内容大家可以自行查询一下相关的资料,也能够学习到一些有趣的历史知识,比如为什么废弃了 儒略历 而将公历定为了 格里历 。还有 法历 为什么只有短短的那些年,犹太历 为什么年份记得这么大了。法历 和 犹太历 月份名字的来源等,都是很有趣的故事。

Calendar 扩展安装及历法信息查看

Calendar 扩展已经集成在 PHP 安装包中了,不需要特别的单独去安装。如果你无法使用 Calendar 相关的函数,可以重新编译 PHP 并加上 --enable-calendar 参数即可。

接下来我们看下指定历法的详细信息,这里我们指定的是 犹太历 。

$info = cal_info(2);
print_r($info);
// Array
// (
// [months] => Array
// (
// [1] => Tishri
// [2] => Heshvan
// [3] => Kislev
// [4] => Tevet
// [5] => Shevat
// [6] => Adar I
// [7] => Adar II
// [8] => Nisan
// [9] => Iyyar
// [10] => Sivan
// [11] => Tammuz
// [12] => Av
// [13] => Elul
// ) // [abbrevmonths] => Array
// (
// [1] => Tishri
// [2] => Heshvan
// [3] => Kislev
// [4] => Tevet
// [5] => Shevat
// [6] => Adar I
// [7] => Adar II
// [8] => Nisan
// [9] => Iyyar
// [10] => Sivan
// [11] => Tammuz
// [12] => Av
// [13] => Elul
// ) // [maxdaysinmonth] => 30
// [calname] => Jewish
// [calsymbol] => CAL_JEWISH
// )

cal_info() 函数接收的参数是一个常量,分别是 CAL_GREGORIAN ,CAL_JULIAN ,CAL_JEWISH ,CAL_FRENCH ,它们对应的数字就是 0,1,2,3 。在这段代码中,我们返回的就是 CAL_JEWISH 的信息。可以看出,犹太历 中的月份名称与公历中的英文名称都不一样,比如这里有 尼撒月 Nisan 、提市黎月 Tishri 。具体的内容就不深究了,毕竟我们在日常生活中是完全接触不到这种历法的。

大家可以自己试试其它历法返回的信息内容,公历和儒略历是一样的,法历中的月份名字就又不一样了,而且这些名字还都很有意思。

日期历法转换

首先,要进行历法转换的话,我们要将指定的日期转换成 Julian Days 计数。这个 jd 计数可以看作是 Calendar 扩展的一个中间变量,用于各种历法之间的换算。

//  转变Unix时间戳为Julian Day计数
$today = unixtojd(mktime(0, 0, 0, 9, 23, 2020));
echo $today, PHP_EOL; // 2459116

使用 unixtojd() 函数就可以将一个 unix 时间戳转换成 jd 计数。接下来,我们看看 2020 年 9 月 23 号对应的 犹太历 是哪一天。

// 获取当前犹太历时间
print_r(cal_from_jd($today, CAL_JEWISH));
// Array
// (
// [date] => 1/5/5781
// [month] => 1
// [day] => 5
// [year] => 5781
// [dow] => 3
// [abbrevdayname] => Wed
// [dayname] => Wednesday
// [abbrevmonth] => Tishri
// [monthname] => Tishri
// )

返回的信息中已经很明确了吧,我们这一天是 犹太历 的 5781 年 1 月 5 号 星期三 。当前的月份是 Tishri 提市黎月 ,对应着公历年的第一个月,犹太历中教会年的第七个月,代表着秋天的到来。

cal_from_jd() 函数的作用就是根据 jd计数 返回指定历法的详细信息。而另外一个 cal_to_jd() 函数则是从一个支持的历法数据转换为 jd计数 。

echo cal_to_jd(CAL_JEWISH, 1, 5, 5781), PHP_EOL; // 2459116
echo cal_to_jd(CAL_GREGORIAN,9, 23, 2020), PHP_EOL; // 2459116

可以看到上面 犹太历 返回的 jd计数 和我们公历返回的 jd计数 是一致的。

当然,我们也可以将 jd计数 的日期转换成 unix 时间。

echo date("Y-m-d", jdtounix($today)), PHP_EOL;
// 2020-09-23

除了 cal_from_jd() 和 cal_to_jd() 之外,Calendar 扩展还为我们提供了一些快捷的函数进行日期的转换,只不过它们是直接返回的字符串类型的日期信息,不是像 cal_from_jd() 函数一样返回日期的详细信息。

// 转变一个Gregorian历法日期到Julian Day计数
$jd = GregorianToJD(9, 23, 2020); // 转变一个Julian Day计数为Gregorian历法日期
echo jdtogregorian($jd), PHP_EOL; // 9/23/2020
// 转变一个Julian Day计数为Julian历法日期
echo jdtojulian($jd), PHP_EOL; // 9/10/2020
// 转变一个Julian Day计数为犹太历法日期
echo jdtojewish($jd), PHP_EOL; // 1/5/5781
// 转变一个Julian Day计数为unix时间戳
echo jdtounix($jd), PHP_EOL; // 1600819200 $jd = GregorianToJD(9, 23, 1799);
// 转变一个Julian Day计数为French历法日期
echo jdtofrench($jd), PHP_EOL; // 1/1/8

GregorianToJD() 方法就是快捷地转换一个公历日期为 jd计数 。而 jdtoxxxxx 为些函数就是快速地返回 jd计数 对应的日期历法的字符串信息。

大家可以注意下,法历 日期只能是公历 1792年9月22日到1806年9月22日 这段日期以内的日期,也就是 法兰西第一共和国 成立后推出的 法历 ,并在 1806年 结束使用,因为 1804年 拿破仑 成立了 法兰西第一帝国 。帝国废止了 法历(共和历)并全面推行 公历 。

某个月份的天数

上面的历史知识学习的怎么样?接下来还是回归到 Calendar 扩展中的学习中来。

$num = cal_days_in_month(CAL_GREGORIAN, 2, 2020);
echo $num, PHP_EOL; // 29

cal_days_in_month() 函数是返回指定历法月份的天数,比如我们看看 2020 年的 2月 是不是 闰月 就可以用这个函数来实现。

复活节彩蛋

复活节是西方非常重要的一个节日,所以在 Calendar 扩展中就有函数可以直接获得指定年份的复活节日期。关于复活节的计算方式其实还是比较复杂的,手工推算是比较麻烦的,而程序计算就非常方便了。

// 指定年份的复活节时间戳
echo date("M-d-Y", easter_date(2019)), PHP_EOL; // Apr-21-2019
echo date("M-d-Y", easter_date(2020)), PHP_EOL; // Apr-12-2020
echo date("M-d-Y", easter_date(2021)), PHP_EOL; // Apr-04-2021 // 3月21日到复活节之间的天数
echo easter_days(2019), PHP_EOL; // 31
echo easter_days(2020), PHP_EOL; // 22
echo easter_days(2021), PHP_EOL; // 14

easter_date() 函数就是返回指定年份的复活节日期。而 easter_days() 函数则是返回从当年公历的 3月21日 到复活节之间的天数。

复活节是每年春分月圆后的第一个星期日,而春分一般是在3月21日,这就简化为只要计算满月的日期和紧挨的星期日的日期就可以得到每年复活节的具体日期了。这种函数在西方世界的软件开发中会非常常用,其实就像我们需要获取每年春节的具体公历日期一样。

总结

是不是很有意思的一套扩展函数。不过对于我们主要面向国内开发的开发者来说用处确实不大,但笔者在学习这个扩展的时候另外收获了不少历史方面的知识,也算是开了眼界,也不失为一大收获,大家也自己试着玩玩并且查查相关的历史知识吧,说不定你的收获会更多!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202009/source/10.PHP中非常好玩的Calendar扩展学习.php

参考文档:

https://www.php.net/manual/zh/book.calendar.php

===============

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PHP中非常好玩的Calendar扩展学习的更多相关文章

  1. PHP中一个好玩的性别判断扩展

    今天我们来学习的一个扩展同时它也是非常小众的一个扩展,其实说白了,或许是根本没什么人用过得扩展.当然,我们也只是出于学习的目的来看看这个扩展到底是什么东西,有什么好玩的地方. 扩展说明 Gender ...

  2. PHP中的MySQLi扩展学习(三)mysqli的基本操作

    我们继续 MySQLi 扩展的学习,上篇文章中提到过,MySQLi 的扩展相对于 PDO 来说功能更加的丰富,所以我们依然还会在学习过程中穿插各种 MySQLi 中好玩的方法函数.不过,今天的主角是 ...

  3. PHP中操作任意精度大小的GMP扩展学习

    对于各类开发语言来说,整数都有一个最大的位数,如果超过位数就无法显示或者操作了.其实,这也是一种精度越界之后产生的精度丢失问题.在我们的 PHP 代码中,最大的整数非常大,我们可以通过 PHP_INT ...

  4. 学习PHP中的高精度计时器HRTime扩展

    不知道大家还记得在学校的时候体育测试时老师带的秒表吗?当枪声想起时,我们开始跑步,这时秒表启动,当我们跑过终点后,老师会按下按扭记录我们的成绩,这就是一个典型的定时器的应用.今天我们要学习的内容其实就 ...

  5. PHP中的MySQLi扩展学习(六)MySQLI_result对象操作

    在之前的文章中,我们就已经接触过 MYSQLI_result 相关的内容.它的作用其实就是一个查询的结果集.不过在 PDO 中,一般直接通过 query() 或者 PDOStatement 对象进行查 ...

  6. PHP中的MySQLi扩展学习(五)MySQLI_STMT对象操作

    就像 PDO 中的 PDO_Statment 对象一样,MySQLI_STMT 对象也是一个预处理语句所形成的对象,专门用来操作 MySQLi 所生成的预处理语句的.其实操作方式之类也都比较相似,不外 ...

  7. PHP中的MySQLi扩展学习(四)mysqli的事务与预处理语句

    对于 MySQLi 来说,事务和预处理语句当然是它之所以能够淘汰 MySQL(原始) 扩展的资本.我们之前也已经学习过了 PDO 中关于事务和预处理语句相关的内容.所以在这里,我们就不再多讲理论方面的 ...

  8. PHP中的MySQLi扩展学习(二)mysqli类的一些少见的属性方法

    虽说是少见的一些属性方法,但是可能还是有不少同学在日常的开发中使用过,这里只是学习了可能相对来说我们用得比较少的一些 mysqli 的属性或方法.就当是扩展一下自己的知识体系. 切换用户 首先就是切换 ...

  9. PHP中的MySQLi扩展学习(一)MySQLi介绍

    关于 PDO 的学习我们告一段落,从这篇文章开始,我们继续学习另外一个 MySQL 扩展,也就是除了 PDO 之外的最核心的 MySQLi 扩展.可以说它的祖先,也就是 MySQL(原始) 扩展是我们 ...

随机推荐

  1. CD管理和检索软件比较

    之前一直用EverCD+,考虑到鸡蛋不能放在一个篮子里,又找了几款功能类似的进行了比较,主要考察一下几个功能: 多个镜像:一个数据文件可以包含多个目录的镜像,便于数据管理和搜索: 目录更新:目录内容发 ...

  2. Rip CD on Ubuntu

    用Mint自带的banshee可以把CD转换为ogg文件,[Media -> Import Media],然后选择Audio CD,但只能转换为ogg格式,好像不能自动获取ID3标签:比较好的方 ...

  3. 能说会道爱办公——“别人家的”Chrome插件到底怎么做

    根据相关数据显示,谷歌的Chrome浏览器目前已达近七成的市场占有率,成为浏览器的"霸主".大家选择Chrome,除了是因为性能的优越以及强大的兼容性之外,Chrome充足的扩展插 ...

  4. docker安装完权限问题

    在用户权限下docker 命令需要 sudo 否则出现以下问题 通过将用户添加到docker用户组可以将sudo去掉,命令如下 sudo groupadd docker #添加docker用户组 su ...

  5. VirtualBox-虚拟硬盘扩容-win7

    问题: 我在VirtualBox下搭建的win7系统只设置了一个C盘,当初只给硬盘分配32G,如今深受生活的毒打,发现只剩5G可用,装个PS都费劲. 我要扩容,扩容! 当前环境: VirtualBox ...

  6. 2018秋招C/C++面试题总结

    一.C和C++的区别是什么? C是面向过程的语言,C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛.C中函数不能进行重载,C++函数可以重载C++在C的基础上增添类,C是一个结构化语言,它 ...

  7. Mybatis轻松入门(仅要求会用看着一个就够了,略过源码分析部分即可)

    文章目录 ==一.概念== 二.快速入门 1.开发步骤 2.环境搭建 2.1.导入Mybatis的坐标和其他坐标 2.2.创建User表 2.3.编写实体 2.4.编写UserMapper配置文件 2 ...

  8. 在ubuntu18.04上部署项目时遇到的问题总结

    因为在实验室中,有几台空闲的机子,我便选了一台准备做一个本地的服务器,因为买的阿里云学生机和之前用于FQ的机子感觉都不太顺手,阿里的学生机配置稍低,FQ用的服务器延迟太高.开始在centos和ubun ...

  9. SpringBoot数据访问之整合mybatis注解版

    SpringBoot数据访问之整合mybatis注解版 mybatis注解版: 贴心链接:Github 在网页下方,找到快速开始文档 上述链接方便读者查找. 通过快速开始文档,搭建环境: 创建数据库: ...

  10. Flink API

    一.Flink API 1.DataSet:对静态数据进行批处理操作.将静态数据抽象成分布式数据集,使用Flink各种操作符处理数据,支持 Java .Scala.Python 2.DataStrea ...