2018-05-31

PHP 获取周一,上个月的正确做法

Views: 4976 | 2 Comments

如果你理所当然地认为在 PHP 中获取周一,上周一,上个月,下个月这些时间能简单地用 strtotime() 函数来获取的话,那你就大错特错了!

$now = strtotime('2018-01-31');
echo date('Y-m-d', strtotime('+1 month', $now)) . "\n";

输出的结果是:

2018-03-03

并不是期望的返回2月份的某一天,而返回了错误的3月份。为什么呢?这和 strtotime() 的实现原理有关:

  • 将月份加1,就变成了 2018-02-31
  • 因为2月没有31号,所以修正,从 2018-02-28 再往前加3天

类似的,星期相关的代码也有问题。

$now = strtotime('2018-05-20'); // 这一天是周日
echo date('Y-m-d', strtotime('this monday', $now)) . "\n";
echo date('Y-m-d', strtotime('+0 monday', $now)) . "\n";

输出的结果是:

2018-05-21
2018-05-21

+0 monday 和 +1 monday 的结果是一样的,并不能将这种格式理解为本周一和下周一(见评论),特别容易出错的是,你可能会错误地认为 +1 monday 是下周一,但事实不是。要得到下周N,或者下下周N,需要先求出本周一。本周一的求法如下:

$now = strtotime('2018-05-20');
$time = $now - 86400 * (date('N', $now) - 1);
echo date('Y-m-d', $time) . "\n"; // 2018-05-14

然后再用本周一加减N个7天,得出前后的周一,之后再根据周一求周N。还有,"+n monday" 和 "-n monday" 的结果和期望不同,其处理逻辑不一致。结合评论,+n xxx 是从当天(含)开始找,-n xxx 是从前一天开始找, +-0 按 +1 处理。

一句话总结:PHP strtotime() 求上周,下周,上个月,下个月等,不能简单处理,需要特殊处理,都需要先求出本周一或者本周一号,再手动处理,而且星期的处理应该在求出本周一之后用时间戳整数运算。

Related posts:

  1. PHP求天数常犯的错误
  2. if-else对优化代码冗余度的反作用
  3. PHP浮点数显示和转成字符串
  4. WordPress分页代码
  5. 用PHP去除重复图片文件
Posted by ideawu at 2018-05-31 19:09:33

2 Responses to "PHP 获取周一,上个月的正确做法"

  • 第二个例子的用法和理解是错的。应该看文档,this monday 这种 "ordinal dayname" 格式的行为是从当天开始往后找对应的星期。因为从周日开始往后找周一,所以才会找到下周的周一。正确的语法应该是 "dayname reltext ‘week’" 写成 monday this week。 Reply
    @timothyqiu: 谢谢。 Reply

Leave a Comment