PHP中处理时间,最常见的2个函数是 time() 和 date()
time() 返回Unix时间戳,而date()用于将时间戳格式化成可读形式,这些都不是问题。关键是遇到时区时,需要好好理解。
最近,我想把从当天起始开始的30000秒的时刻换算成8时20分,这时,用 date('H时i分', 30000) 结果得到 16时20分,这里要分几步来理解:
1、PHP官网关于time()函数的注释下面,有Timo K的注释说得好
The documentation should have this info. The function time() returns always timestamp that is timezone independent (=UTC).
文档应该有这样的信息:函数time()总是返回时区无关的时间戳(即Unix时间戳总是对于UTC标准时而言的)
<?php
date_default_timezone_set("UTC");
echo "UTC:".time();
echo "<br>";
date_default_timezone_set("Europe/Helsinki");
echo "Europe/Helsinki:".time();
echo "<br>";
?>
上面的代码中,time()得到的数字是一样的,和时区无关,而前后代码的执行远小于1秒。
Local time as string can be get by strftime() and local timestamp (if ever needed) by mktime().
字符串形式的本地时间可以用strftime()获取,本地时间戳(如果必要)可以用mktime()
2、date()函数的作用:格式化一个本地时间/日期,即date()函数与时区有关
假设当前北京时间 2014年6月8日9时17分03秒,
<?php echo date('Y年m月d日H时i分s秒', time()); ?> 的执行过程是这样的:
time()获得了Unix时间戳,等价于 UTC:1970年1月1日0时0分0秒到UTC:2014年6月8日1时17分03秒 的秒数,然后date()函数检查php.ini的设置,发现
date.timezone = Asia/Shanghai,即东八区,所以在 UTC:2014年6月8日1时17分03秒 的基础上加8小时,显示“2014年6月8日9时17分03秒”
对于前面的例子 date('H时i分', 30000), 因为 30000秒是 UTC 经过 30000秒,相当于 UTC:1970年1月1日8时20分0秒,对应东八区“1970年1月1日16时20分0秒”,从而
date('H时i分', 30000) 显示成 16时20分。得到的教训是,此类任务,不应该借用date()函数,而应该自己直接写转换函数,这样才可以避免时区相关性
另外:我们可能会用到getdate()来获取日期和时间中的每个组成部分(getdate将日期和时间解析为一个数组)
3、gettimeofday()函数:获取当前时间,返回数组 array(Unix时间戳秒数,微秒数,和UTC的偏差分钟数,区域纠正类型)
gettimeofday()的优势是获取比较精确的时间戳秒数和微秒数,也能获得当前时间和UTC的偏差
注意:microtime 函数专门用来获取时间戳秒数和微秒数
4、strftime()函数的作用:根据区域设置,格式化一个本地时间/日期,常配合setlocale()使用。如果仅用于php.ini设定的时区,这个函数几乎没有必要(用date()就可以了),格式控制甚至比date()还复杂一些。如果用了strftime,那么可能会用到strptime来把字符串中的各部分解析成数组,类似getdate的作用。
5、mktime()函数作用:获得一个日期的Unix时间戳,即已知本地的年月日时分秒,换算成Unix时间戳,有点像getdate的逆过程
<?php echo mktime(8, 20, 0, 1, 1, 1970); ?>
上述代码得到 1200
这说明,mktime()函数中的 年月日时分秒 是本地时间,执行时先换算成UTC时间,然后计算秒数,即mktime()函数的参数是和时区有关的
6、strtotime()函数作用:解析英文文本形式的时间/日期为时间戳,该函数某种程度上是date()/strftime()的逆过程,但它同时支持复合的描述和相对时间的描述
官网的例子:
<?php
echo strtotime("now"), "\n";
echo strtotime("10 September 2000"), "\n";
echo strtotime("+1 day"), "\n";
echo strtotime("+1 week"), "\n";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
echo strtotime("next Thursday"), "\n";
echo strtotime("last Monday"), "\n";
?>
例如,获取今天的开始时刻$todaystart = strtotime('today');
7、checkdate函数:检验日期的有效性
总结:PHP处理时间,总体的秒数、微秒数都是指Unix时间戳,它和时区无关(总是对应UTC),其他从时间戳换算的函数,总是时区相关的。
最常用的函数作用理解如下:
time()获得当前时间戳
date()把指定时间戳变成字符串,strtotime()把关于时间的“人话”字符串变成时间戳
mktime()把年月日时分秒变成时间戳,getdate()把时间戳变成年月日时分秒
gettimeofday()、microtime()可以获取微秒数