为什么说这个 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. Compile Java Codes in Linux Shell instead of Ant Script

    The following is frequently used ant script, compile some java source codes with a libary path, then ...

  2. RadioButton 自定义样式(带动画)

    <Style x:Key="Radbtn" TargetType="{x:Type RadioButton}"> <Setter Proper ...

  3. murmur3 hash(hash算法)

    HashUtil.java package com.example.test.util; import com.google.common.base.Charsets; import com.goog ...

  4. Apache/Nginx/IIS日志记录的各个字段内容与含义

    一.Apache 1.1 Apache日志文件名称及路径介绍 当我们安装并启动Apache后,Apache会自动生成两个日志文件,这两个日志文件分别是访问日志access_log(在Windows上是 ...

  5. 【文件格式探究】EP.1 对ePub文件格式的初探

    这是"文件格式探究"专题的第 1 期--初探 "ePub" 文件格式.这个专题将会给各位读者呈现笔者探索各种文件格式的过程,具体则是文件的内容是如何呈现出来的. ...

  6. java String数组城市

    String[] citys = {"北京","天津","河北","山西","内蒙古"," ...

  7. jQuery中的文档操作处理(五):append()、prepend()、after()、before()、wrap()、wrapAll()、wrapInner()、clone()等

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  8. 12-SpringCloud GateWay

    GateWay和Zuul说明 Zuul开发人员窝里斗,实属明日黄花 重点关注Gate Way GateWay是什么 上一代zuul 1.x官网 Gateway官网 概述 Cloud全家桶中有个很重要的 ...

  9. github push报LibreSSL SSL_connect错误

    最近发现在家里push代码到github的时候总是报错,报错内容如下: fatal: unable to access 'https://github.com/MangoDowner/clear-le ...

  10. OpenCV waitKey 无法正常捕捉方向键(上下左右),总结和解决方案,可以用waitKeyEx

    在win10+python+opencv3.4.5,测试 while True: key = cv2.waitKey(0) print('key =', key) 依次按上.下.左.右方向键,输出: ...