由于php 32位使用 int 类型保存时间戳,也就是从1970 00:00:00 到当前时间的秒数。

而32位int 数字的取值范围是 -2147483648 到 2147483647。

所以当 时间戳为最大值 2147483647 时,表示的时间是 2038-01-19 03:14:07 或北京时间 2038-01-19 11:14:07 (为了表述方便,下文中,将这个临界点时间称之为 T0)。

而当时间大于这个时间时,php很多内置函数都会出错。

比如

当日期和时间大于 北京时间 2038-01-19 11:14:07 时

time()函数,原本应该返回时间戳,现在会始终返回-1。

date("Y-m-d H:i:s")函数,会返回 1970-01-01 07:59:59(北京时间),其实也是因为 time()=-1导致的,date默认的第二个参数就是time()。

同样,mktime() 等函数也会异常。

上网查了解决办法,

1、换用64位系统。这里说的64位系统,需要操作系统、web服务系统,以及PHP都要64位的。

2、使用php5.2之后推出的 DateTime 类。

首先说第一种方法,因为我的服务器建设在Windows系统上,然后又有几个自制插件,这些插件在php 64位下面可能不能使用,因此这个方法不能用。

再说DateTime类,网上几乎几十篇文章都说使用DateTime类就能解决2038年问题。

我在自己的服务器上测试了一下,使用DateTime类似乎确实可以让日期超过2038上限,各种转换,都没问题,这里我不具体说明,大家网上搜"php datetime",都有说明。

但是,我在把服务器的时间设置为2040年4月18日的时候,发现,datetime 类依然无法获取当前时间。代码如下:

$date = new DateTime();

echo $date->format('Y-m-d H:i:s');

输出的还是 1970-01-01 07:59:59

但是,如果使用 $date->setDate(2040,4,18) 之后,再显示,再输出时间戳等,都是正常的代码如下:

$date = new DateTime();

$date->setDate(2040,4,18);

$date->setTime(10,24,11);

echo $date->format('Y-m-d H:i:s')."\r\n";

echo $date->format('U')."\r\n";

这时 输出时间 2040-04-18 10:24:11 ,以及时间戳 2218328651 都是正常的。

问题在于,datetime 类可以解决 2038年之后的时间的各种运算和转换,但是当系统日期在2038年那个T0时间之后,php系统根本无法获取当前时间。

我还试了 new DateTime("today");new DateTime('+2 days');new DateTime('tomorrow'); 等等,都无法获取今天,明天,后天等日期。

这时,整个php 系统无法获取当前的年月日和时间。

然后我开始在php的系统数组 $_SERVER 中寻找,看看哪里能找到和时间相关的内容,终于被我找到一个 $_SERVER["REQUEST_TIME"],这个实际上是一个记录用户刷新页面时php相应时刻的时间。它的值,在T0之前,和time()是一致的,但是,当T0之后,它就变成负数了。那么,怎么通过 $_SERVER["REQUEST_TIME"] 来获取真实的 时间戳呢?

很简单,32位int 数字的取值范围是 -2147483648 到 2147483647,转成2进制就会发现,其实是最高位用作符号位,最高位0表示正数,最高位1表示负数,当数字达到 2147483647后,二进制 就是 01111111 11111111 11111111 11111111(31个1),这时就是T0时刻的时间戳,继续+1 以后,变成了 10000000000000000000000000000000 (31个0),如果是无符号32位整数,就是 2147483648(正数) 但是在有符号的整数里,最高位1表示负数,就是 -2147483648(负数),而 $_SERVER["REQUEST_TIME"] 的特性是根据时间的推移进行累加。所以,它的时间线如下:

T0 之前:它等于 1970 00:00:00 到当前时间的秒数,和time()相同

T0 时: 它等于 2147483647

T0 后1秒: 它等于 2147483647+1=2147483648 被表示为 -2147483648 我们把 -2147483648 记作 T1,T1=T0+1秒的时刻

T0 后N秒:-2147483648-1+N

所以,当 $_SERVER["REQUEST_TIME"]<0 时,真正的时间戳为 $_SERVER["REQUEST_TIME"]-(-2147483648)+ 2147483647。

其中 $_SERVER["REQUEST_TIME"]-(-2147483648)表示 T1(变成负数,即T0+1秒) 时刻到当前时间 过了多少秒。

据此,写出一个新的取代time()的函数,该函数在系统时间超过T0 时,也能返回正确的时间戳,但是它的范围是无符号32位上限 4294967295,北京时间 2106-02-07 06:28:15。在这个时间之前,应该都可以正常使用。

function sunTime(){

if($_SERVER["REQUEST_TIME"]>0){

$t=$_SERVER["REQUEST_TIME"];

}else{

$t0=PHP_INT_MAX; // 第 2147483647 秒 再过一秒为 2147483648秒,但最高位变成1,系统中为 -2147483648

$t1=0-$t0-1; // t0后面1秒,瞬间变成负数,值为 -2147483648

$t2=($_SERVER["REQUEST_TIME"]);//虽然$_SERVER["REQUEST_TIME"]变成了负数,但是 系统依然通过 +1秒 来计时

$t=$t2-$t1+$t0.""; //t2-t1 就是变成负数后过了多少秒,t0就是变成负数前的秒数。

}

$date=new datetime("@".$t);

$timemark=$date->format("U");

return $timemark;

}

所以,目前网上很多人都以为使用 DateTime类可以解决问题,殊不知等时间真正到了2038那个时间之后,php系统获得当前时间都会出错。而我这方法也是目前网上唯一存在的方法。

阳光浪子

2018-04-18

php 2038,php在2038年后datetime类也无法获得当前日期的解决相关推荐

  1. datetime unix php,PHP基于DateTime类解决Unix时间戳与日期互转问题【针对1970年前及2038年后时间戳】...

    本文实例讲述了PHP基于DateTime类解决Unix时间戳与日期互转问题.分享给大家供大家参考,具体如下: 这个问题主要在32位的系统下出现,64位的不存在这样的问题.php 5.2+提供了Date ...

  2. mysql 2038年问题_当前系统在2038年之后datetime类也无法获取当前时间的解决

    由于php 32位使用 int 类型保存时间戳,也就是从1970 00:00:00 到当前时间的秒数. 而32位int 数字的取值范围是 -2147483648 到 2147483647. 所以当 时 ...

  3. Python中datetime类错误

    在使用python的datetime类的时候,如下所示: a=datetime.datetime(2014,08,02) ^ SyntaxError: invalid token 如果转换的是2014 ...

  4. 求计算两个时间的差(DateTime类和TimeSpan类)

    日期时间数据是项目设计过程中经常需要处理的信息,C#提供了DateTime类和TimeSpan类来处理日期时间数据.下面介绍说明Datetime类和TimeSpan类的使用 //初始化DateTime ...

  5. C# DateTime类

    面向对象编程 1. 自己造轮子--Time类 2. 现成的轮子--DateTime类 1. 自己造轮子--Time类 using System; using System.Collections.Ge ...

  6. .Net时间运算 - DateTime类,TimeSpan类

    DateTime类是.Net中用于处理时间类型数据的. 一.字段 MaxValue 表示 DateTime 的最大可能值.此字段为只读. MinValue     表示 DateTime 的最小可能值 ...

  7. datetime.datetime类介绍

    datetime类是date和time的结合体,包括date与time的所有信息,date和time类中具有的方法和属性,datetime类都具有. 所以在我们日常的工作中,可以仅使用datetime ...

  8. C# DateTime类详解

    1.获取时间 只需要使用 System 命名空间下的 DateTime 类即可完成 Debug.Log(System.DateTime.Now); // 当前本地时间 (年月日时分秒) -- 10/4 ...

  9. arduino红外遥控库IRremote的IRsend类sendRaw函数溢出问题及其解决方法

    arduino红外遥控库IRremote的IRsend类sendRaw函数溢出问题及其解决方法 参考文章: (1)arduino红外遥控库IRremote的IRsend类sendRaw函数溢出问题及其 ...

最新文章

  1. 【面试】我是如何在面试别人Spring事务时“套路”对方的
  2. xml转json和实体类的两种方式
  3. 2020-12-28 Matlab自动化控制-Adrc自抗扰控制
  4. Linux内核: 分析coredump文件
  5. 设置mysql的字符编码解决中文乱码问题
  6. python3 从尾部读取_Python3基础:列表详解
  7. java 的原码、补码、反码小总结
  8. Linux 命令之 kill -- 杀死进程
  9. sparql查询mysql_SPARQL常用查询
  10. 大数据_MapperReduce_从CSV文件中读取数据到Hbase_测试---Hbase工作笔记0022
  11. 线程学习9——Mutex类
  12. kill -9 杀不死的进程处理办法
  13. wien10 / win11双开微信
  14. bochs镜像java模拟器_【 bochs win7镜像完整版 】bochs win7镜像完整版(bochs win7 img文件)新版下载 - U大师...
  15. HTTP 000 CONNECTION FAILED for url <https://repo.anaconda.com/pkgs/main/linux-64/tqdm-4.64.0-py39h06
  16. excel使用vb选中指定单元格,到指定行的最后一行有数据的等行数的单元格区间(列等高复制)
  17. IN和Like的使用
  18. python自学-class14(down)-窗口界面的设计基础
  19. 蓝桥六届 打印大X JAVA
  20. 《原子习惯》读书分享

热门文章

  1. 利用临时文件恢复PowerPoint(PPT)文件
  2. 常见排序算法时间复杂度和空间复杂度
  3. 【译】Sobel 算子文档
  4. 中国传媒大学计算机课程表,课 程 表 - 中国传媒大学
  5. VS 关于GetLastError()返回码列表及对应的解释
  6. 法学专业能从事计算机工作吗,未来20年,这5个专业都是“香饽饽”,毕业生工作好找前途大好!...
  7. 5款高逼格实用手机APP推荐,千万不能错过!
  8. db2和相关驱动的下载
  9. vue日历排班组件_vue之手把手教你写日历组件
  10. Analysis of Struts2 : http://wenku.baidu.com/view/ad421874a417866fb84a8e75.html