PHP的strtotime方法中的陷阱

strtotime 在PHP中是一个超级函数,可以处理多种格式的时间字符串。 比如我们要获得本月的第一天和最后一天

date('Y-m-d',strtotime('first day of this month')); // 第一天
date('Y-m-d',strtotime('last day of this month')); // 最后一天

但是在提供便利性的同时这个方法也有一些坑,比如: 比如我们想根据某个日期获取上个月的月份信息,就有可能这样用:

date('Y-m',strtotime('2021-03-31 -1 month')); //2021-03
date('Y-m',strtotime('2021-03-31 -2 month')); //2021-01

你可能会觉得有点出乎意料,第一行为什么不是二月份,第二行怎么感觉又对了,我们把日期显示出来看下

date('Y-m-d',strtotime('2021-03-31 -1 month')); //2021-03-03
date('Y-m-d',strtotime('2021-03-31 -2 month')); //2021-01-31

可以看到2021-03-31减去一个月并没有去到二月份,而是在03-03,如果对数字敏感可以发现,这是31减去了28, 28是2021-02月份的天数,所以strtotime 操作中的 -x month的操作是按照前面月份的天数来操作的, 而-2 month 的操作是减去上个月的天数,然后再减去上上个月的天数:
date('Y-m-d',strtotime('2021-03-31 -1 month'))是到2021-03-03,
date('Y-m-d',strtotime('2021-03-31 -2 month')); 等于2021-03-03再减去 一月份的31天得到2021-01-31 //(2021-03-03 -31天 = 2021-03-31)

我们再看看+x month 的操作

date('Y-m-d',strtotime('2021-01-10 +2 month'))
2021-03-10

echo date('Y-m-d',strtotime('2021-04-01 +1 month'));
2021-05-01

echo date('Y-m-d',strtotime('2021-02-10 +1 month'));
2021-03-10

echo date('Y-m-d',strtotime('2021-01-10 +1 month'));
2021-02-10

完美的获得的后面一个月/两个月的对应的日期,换个方式思考你可以把它看成加上本月的天数。+2 month就是加上本月的天数,再加上下一月的天数

+x month -x month 的行为完全不同。