PHP DateTime类计算早于改历时间的问题

时间戳只能计算 1970 年后的时间,由于需要计算更早的日期,发现 PHP 还有提供一个 DateTime类,但在使用中发现有问题。

1582年,因为旧历精度问题,导致已经积累了十天的偏差,,所以此年10月5号~10月14号跳过,10月4号之后直接是10月15号,同时修个置闰规则,成为如今使用的格里高利历。

现行公历(拉丁语:Calendarium Gregorianum,又译格里历、国瑞历、额我略历、格列高利历、格里高利历、葛瑞格里历、格列高历,也称基督历),是由意大利医生兼哲学家阿洛伊修斯·里利乌斯改革儒略历制定的历法,由罗马大公教会教宗格列高利十三世在1582年颁行。
格里历与儒略历一样,格里历也是每四年在2月底置一闰日,但格里历特别规定,除非能被400整除,所有的世纪年(能被100整除)都不设闰日;如此,每四百年,格里历仅有97个闰年,比儒略历减少3个闰年。
格里高利历

问题出在1582年之前,之前应该是使用旧历,也就是儒略历,主要差异在置闰方法不同。
但PHP的DateTime类计算依然是按新历计算(或者说计算时早于改历不会自动换算成儒略历),所以导致1300年之类整百年的时候,二月日期不对,实际传入这天时,会自动换算成3月1号,diff计算天数差,也会有错误。

并且在实际使用中,早于改历之前的时间并没用格里历表式的习惯,都是换成儒略历表达,所以DateTime类这样的设计,等于说早于改历的时间基本不能用的,还是得自己另外处理一遍。(其他语言像是C#提供的历法计算似乎也存在类似情况)。

儒略历,是格里历的前身,由罗马共和国独裁官儒略·凯撒采纳埃及亚历山大的希腊数学家兼天文学家索西琴尼计算的历法,在公元前45年1月1日起执行,取代旧罗马历历法的一种历法。一年设12个月,大小月交替,四年一闰,平年365日,闰年于二月底增加一闰日,年平均长度为365.25日。由于累积误差随着时间越来越大,1582年后被教皇格里高利十三世改善,变为格里历,即沿用至今的公历。
儒略历

还有一个细节就是,儒略历定制于公元前45年,是大小月交替的,但在5世纪的时候,有一次历法改革,改变了月份划分不是规律的大小月交替了(现行日历样式),资料上说明并不是很清楚,这点很容易遗漏(我也是请教了一下才发现这问题..)。


补充一下:PHP5+里实际上有日历扩展,如果需要专业的日历应用最好还是使用扩展。一般应用到1970之前的都很少,所以都不考虑对超长时间段的支持。
对于这种超长期的日历计算,时间戳时间太近不适合,格里历也太近,儒略历转换成近代时间也不方便。在历法上有一个类似于时间戳的历法算法儒略日,名字和儒略历很像但并不是同一个概念。这是由法国学者Joseph Justus Scliger(1540-1609)在1583年所提出,从儒略历公元前4713年1月1日,协调世界时中午12时开始至今的天数,很适合处理超长时间范围的问题。


01小径
在路上,遇见了一只BUG,我将它抓住,收藏在了这里。<( ̄︶ ̄)>
648 声望
14 粉丝
0 条评论
推荐阅读
Chrome 历史版本下载
由于测试时候会需要用到历史版本,但发现不是很好找,于是记录一下。window/MAC/Linux:[链接]Window:[链接] MAC:[链接]firefox的历史版本:[链接]

LnEoi阅读 55

PHP转Go实践:xjson解析神器「开源工具集」
我和劲仔都是PHP转Go,身边越来越多做PHP的朋友也逐渐在用Go进行重构,重构过程中,会发现php的json解析操作(系列化与反序列化)是真的香,弱类型语言的各种隐式类型转换,很大程度的减低了程序的复杂度。

王中阳Go11阅读 2.7k评论 4

封面图
Git操作不规范,战友提刀来相见!
年终奖都没了,还要扣我绩效,门都没有,哈哈。这波骚Git操作我也是第一次用,担心闪了腰,所以不仅做了备份,也做了笔记,分享给大家。问题描述小A和我在同时开发一个功能模块,他在优化之前的代码逻辑,我在开...

王中阳Go6阅读 2.9k评论 4

封面图
图片防盗链破解 解决图片防盗链问题 反向代理
当客户端(浏览器)向服务器请求内容的时候,会提交一个header,这个header中包含了如:浏览器信息、cookie等内容,那么有一个叫referer的东东,也包含在这里面。

TANKING7阅读 11.7k评论 5

Hyperf 3.0 发布,PHP 新时代
在过去的一年半时间里,Hyperf 2.2 共发布了 35 个小版本,使 Hyperf 达到了一个前所未有的高度,这里也获得了一些不错的数据反馈。

huangzhhui4阅读 1.5k评论 1

封面图
微信公众号开发:自动回复文本/图片/图文消息/关键词回复/上传素材/自定义菜单
对接流程1、申请微信公众号测试账号URL:[链接]2、登录,配置开发者服务器URL和Token开发者服务器配置代码:config.php {代码...} URL是config.php在你服务器的URLToken是上面代码自己设置的Token搞定之后,就能完...

TANKING2阅读 10.5k

Ajax实现搜索联想 搜索关键词提醒 无刷新搜索
通过javascript监听搜索框的内容,调用后端即可。(1)javascript监听搜索框的内容(2)把搜索框的关键词传给后端进行搜索(3)搜索到结果,遍历到页面

TANKING1阅读 4.6k

648 声望
14 粉丝
宣传栏