PHP中令人疑惑的strtotime

  在处理时间的时候我们经常会使用 strtotime 结合 -1 month+1 monthnext monthlast month,但有时候会得到很困惑的结果,所以使用这个函数的时候会很没底,下面我们来看看吧。

举个例子:

1
2
3
4
5
<?php
$date = date('Y-m-d', strtotime('-1 month', strtotime('2020-07-31')));
var_dump($date);
//执行结果
//string(10) "2020-07-01"

  输出怎么是 2020-07-01呢?我们期望的是 2020-06-30,下面一步步说明这样处理的逻辑:

  1. 先做 -1 month 操作,当前是 07-31,减去一个月是 06-31;
  2. 做日期规范化,因为6月没有31号,所以 06-31 就变成 07-01 了。
    我们来验证一下第二步:
    1
    2
    3
    4
    <?php
    var_dump(date('Y-m-d', strtotime('2020-06-31')));
    //执行结果
    string(10) "2020-07-01"

  也就是说只要涉及到大小月的最后一天就可能有这个疑惑,验证一下:

1
2
3
4
5
6
7
8
9
<?php
var_dump(date("Y-m-d", strtotime("-1 month", strtotime("2020-03-31"))));
//输出2020-03-02
var_dump(date("Y-m-d", strtotime("+1 month", strtotime("2020-08-31"))));
//输出2020-10-01
var_dump(date("Y-m-d", strtotime("next month", strtotime("2020-01-31"))));
//输出2020-03-02
var_dump(date("Y-m-d", strtotime("last month", strtotime("2020-03-31"))));
//输出2020-03-02

  那怎么处理这种时间呢?别着急,从 PHP5.3 开始,date 函数新增了一系列修正语来明确整个问题,也就是 first day oflast day of 来限定 date 不自动规范化,验证一下:

1
2
3
4
5
6
7
8
9
<?php
var_dump(date("Y-m-d", strtotime("last day of -1 month", strtotime("2020-03-31"))));
//输出2020-02-29
var_dump(date("Y-m-d", strtotime("first day of +1 month", strtotime("2020-08-31"))));
//输出2020-09-01
var_dump(date("Y-m-d", strtotime("first day of next month", strtotime("2020-01-31"))));
//输出2020-02-01
var_dump(date("Y-m-d", strtotime("last day of last month", strtotime("2020-03-31"))));
//输出2020-02-29

  搞清楚了,以后就可以放心使用了。