问题起源:
<?php
$d = gmmktime (20,45,51,12,13,1901);
echo gmdate("Y-m-d",$d);
echo ",";
$d = gmmktime (20,45,52,12,13,1901);
echo gmdate("Y-m-d",$d);
echo "\r\n";
$d = gmmktime (3,14,8,1,19,2038);
echo gmdate("Y-m-d",$d);
echo ",";
$d = gmmktime (3,14,7,1,19,2038);
echo gmdate("Y-m-d",$d);
?>
在WindowXP机器,php5.2.5,默认为东八区北京时间,运行以上代码输出:
1970-01-01,1901-12-13
1970-01-01,2038-01-19
上面使用gm开头的日期函数是保证日期基准(不受服务器所在时区的干扰)。
原来php时间函数使用32位有符号整型存储时间戳。上面的问题是因为整型溢出导致。1970年1月1日0时0分0秒gmmktime()返回时间戳整数0,早于该时间返回负数,晚于该时间返回正数。文档说有效的时间戳典型范围是:格林威治时间1901年12月13日20:45:52到2038年1月19日03:14:07。(此范围符合32位有符号整数的最小值和最大值)。所以,如果你处理的日期超过这个范围,就需要使用自己的日期处理函数。
注:文档说
引用
Before PHP 5.1.0, negative timestamps were not supported under any known version of Windows and some other systems as well. Therefore the range of valid years was limited to 1970 through 2038.
所以我使用php5.2.13测试结果是可以表示负时间戳的。
有好事者写了一个库,用float来处理date。为了保证性能,当日期没有溢出使用php内置处理方法,否则调用自己的处理方法。为了使用这些函数,请做如下替换:
getdate() with adodb_getdate()
date() with adodb_date()
gmdate() with adodb_gmdate()
mktime() with adodb_mktime()
gmmktime() with adodb_gmmktime()
现附上该函数库文件(但是很遗憾,我发现该库不能运行正常:()