PHP strtotime 转月份的问题

需求

输入 开始日期和结束日期,返回两个日期之间 月份的列表,包含开始和结束的月份。

实现

可能代码会这么写


function showMonthRange($start, $end)
    {
        $end = date('Ym', strtotime($end)); // 转换为月
        $range = [];
        $i = 0;
        do {
            $month = date('Ym', strtotime($start . ' + ' . $i . ' month'));
            //echo $i . ':' . $month . '
'; $range[] = $month; $i++; } while ($month < $end); return $range; }

问题

当输入 【2020-03-31】 和 【2020-04-01】 时 返回了 【202003,202005】,期望返回的是【202003,202004】
出现这个问题的原因时:strtotime 的 +1 month,会直接在month字段上加1,然后再转成日期,4月没有31日,就会变成 5月1日

解决

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

var_dump(date("Y-m-d", strtotime("last day of -1 month", strtotime("2017-03-31"))));
//输出2017-02-28
var_dump(date("Y-m-d", strtotime("first day of +1 month", strtotime("2017-08-31"))));
输出2017-09-01
var_dump(date("Y-m-d", strtotime("first day of next month", strtotime("2017-01-31"))));
输出2017-02-01
var_dump(date("Y-m-d", strtotime("last day of last month", strtotime("2017-03-31"))));
输出2017-02-28
public static function getMonthRange($startDate, $endDate, $format = "Y-m-d")
    {
        $end = date($format, strtotime('first day of ' . $endDate . ' + 0 month')); // 转换为月
        $range = [];
        $i = 0;
        do {
            $month = date($format, strtotime('first day of ' . $startDate . ' + ' . $i . ' month'));
            $range[] = $month;
            $i++;
        } while ($month < $end);
        return $range;
    }

那如果是5.3之前的版本(还有人用么?), 你可以使用mktime之类的, 把所有的日子忽略掉, 比如都限定为每月1号就可以了, 只不过就不如直接用first day来的更加优雅

参考:
https://www.laruence.com/2018/07/31/3207.html

你可能感兴趣的:(PHP)