strtotime() 问题及使用总结

strtotime 使用

strtotime — 将任何字符串的日期时间描述解析为 Unix 时间戳 

函数原型:

int strtotime ( string $time [, int $now = time() ] )

第2个参数,一般用不到,主要是计算返回时间戳的相对值。如:

<?php
// 设置北京时区
date_default_timezone_set("PRC");

# 例 1:
// 将 "2018-09-19 00:00:00" 转化为时间戳
$strtime = strtotime("2018-09-19 00:00:00", time() + 3600);
// 会输出 2018-09-19 00:00:00, 在这种情况下, 第 2 个参数无意义
echo date("Y-m-d H:i:s", $strtime), PHP_EOL; 


# 例 2
// 将 “当前时间 加 1天” 转化为时间戳
$strtime = strtotime("+1 day");
// 会输出 2018-09-19 15:48:15
echo date("Y-m-d H:i:s", $strtime), PHP_EOL; 


# 例 3
// 将 “当前时间 加 1天” 转化为时间戳
$strtime = strtotime("+1 day", time() + 3600);
// 会输出 2018-09-19 16:48:15, 在这种情况下, 
// 时间戳以下个小时为准,实际当前时间是 15 点,对比例 2
echo date("Y-m-d H:i:s", $strtime), PHP_EOL;

由上面的例子可以看出 strtotime 在计算相对时间的时候,非常有用,常用例子:

<?php
// 设置北京时区
date_default_timezone_set("PRC");

// 当前时间    2018-09-18 16:06:18
echo date('Y-m-d H:i:s'), PHP_EOL;

// 明天 和 昨天
echo date('Y-m-d H:i:s', strtotime("+1 day")), PHP_EOL;   // 2018-09-19 16:06:18
echo date('Y-m-d H:i:s', strtotime("-1 day")), PHP_EOL;   // 2018-09-17 16:06:18

// 上月 和 下月         
echo date('Y-m-d H:i:s', strtotime("+1 month")), PHP_EOL; // 2018-10-18 16:06:18
echo date('Y-m-d H:i:s', strtotime("-1 month")), PHP_EOL; // 2018-08-18 16:06:18

// 明年 和 去年
echo date('Y-m-d H:i:s', strtotime("+1 year")), PHP_EOL;  // 2019-09-18 16:06:18
echo date('Y-m-d H:i:s', strtotime("-1 year")), PHP_EOL;  // 2017-09-18 16:06:18

// 下个小时和上个小时
echo date('Y-m-d H:i:s', strtotime("+1 hour")), PHP_EOL;  // 2018-09-18 17:06:18
echo date('Y-m-d H:i:s', strtotime("-1 hour")), PHP_EOL;  // 2018-09-18 15:06:18

// 下一分钟和上一分钟
echo date('Y-m-d H:i:s', strtotime("+1 minutes")), PHP_EOL;  // 2018-09-18 16:07:18
echo date('Y-m-d H:i:s', strtotime("-1 minutes")), PHP_EOL;  // 2018-09-18 16:05:18

// 下一秒和上一秒
echo date('Y-m-d H:i:s', strtotime("+1 seconds")), PHP_EOL;  // 2018-09-18 16:06:19
echo date('Y-m-d H:i:s', strtotime("-1 seconds")), PHP_EOL;  // 2018-09-18 16:06:17

如果需要其它相对时间,只需要修改 + (-) number 即可,如:

<?php
// 设置北京时区
date_default_timezone_set("PRC");

// 当前时间    2018-09-18 16:06:18
echo date('Y-m-d H:i:s'), PHP_EOL;

// 下周 和 上周
echo date('Y-m-d H:i:s', strtotime("+7 day")), PHP_EOL;   // 2018-09-25 16:06:18
echo date('Y-m-d H:i:s', strtotime("-7 day")), PHP_EOL;   // 2018-09-11 16:06:18


strtotime 问题

上节我们看出 strtotime 计算相对时间非常有用。但是,此函数也有一点小“问题”,如: 

今天是2018-07-31 执行代码,

date("Y-m-d",strtotime("-1 month"))

怎么输出是 2018-07-01?

这个问题,在鸟哥的博客里也说的很清楚了,这里我做一下记录,防止下次忘记。虽然这个问题看起来很迷惑, 但从内部逻辑上来说呢, 其实是”对”的。


我们来模拟下date内部的对于这种事情的处理逻辑:

  • 先做-1 month, 那么当前是07-31, 减去一以后就是06-31.

  • 再做日期规范化, 因为6月没有31号, 所以就好像2点60等于3点一样, 6月31就等于了7月1 

是不是逻辑很”清晰”呢? 比如:

<?php
echo date("Y-m-d", strtotime("-1 month", strtotime("2017-03-31"))), PHP_EOL;   // 2017-03-03
echo date("Y-m-d", strtotime("+1 month", strtotime("2017-08-31"))), PHP_EOL;   // 2017-10-01
echo date("Y-m-d", strtotime("next month", strtotime("2017-01-31"))), PHP_EOL; // 2017-03-03
echo date("Y-m-d", strtotime("previous month", strtotime("2017-03-31"))), PHP_EOL; // 2017-03-03

解决方案 

从PHP5.3开始呢, date新增了一系列修正短语, 来明确这个问题, 那就是”first day of” 和 “last day of”, 也就是你可以限定好不要让date自动”规范化”:

<?php
// 输出2017-02-28
echo date("Y-m-d", strtotime("last day of -1 month", strtotime("2017-03-31"))), PHP_EOL;

// 输出2017-09-01
echo date("Y-m-d", strtotime("first day of +1 month", strtotime("2017-08-31"))), PHP_EOL;

// 输出2017-02-01
echo date("Y-m-d", strtotime("first day of next month", strtotime("2017-01-31"))), PHP_EOL;

// 输出2017-02-28
echo date("Y-m-d", strtotime("last day of last month", strtotime("2017-03-31"))), PHP_EOL;

总结

那如果是5.3之前的版本, 还是放弃吧,截止写此文章时,7.3 已经快来了 

另外 strtotime 函数的第一个参数支持的时间格式可以参考:php strtotime


未经允许不得转载:易读小屋  »  strtotime() 问题及使用总结