登录
原创

PHP 日期月份处理问题,strtotime的BUG

发布于 2022-02-21 阅读 2132
  • 后端
  • PHP
原创

PHP 日期月份处理问题,strtotime的BUG

由于每个月份天数不同导致日期在月份加减的时候会出现问题,非预期的结果
日期常用操作date(‘Y-m-d’,strtotime(‘2022-01-01’))

问题如下:

日期进行月份增加时候会先将月份加1,然后进行日期格式化,但是02月份最大日期为28号,所以多余三天顺延就导致日期为2022-03-03
当日期格式正确的时候,即月份在112之间,日期在131之间,在使用strtotime的时候是不会报错的
所以下面两个日期月份增减的的问题是不是更好立即了

var_dump(date("Y-m-d", strtotime("2020-11-31")));
// 这个输出是:string(10) "2020-12-01"

1、月份增加后日期超范围

// 当前日期为:2022-01-31时候
var_dump(date('Y-m-d',strtotime('1 month',stritotime('2022-01-31'))))
// 输出 2022-03-03

2、月份减少同样会有问题

var_dump(date('Y-m-d',strtotime('-1 month',stritotime('2022-03-31'))))
// 输出 2022-03-03

修复

官方给出了修正语法,但感觉实际使用中并没啥卵用:
因为这个是修正了月份第一天和最后一天格式化,不管今天是什么日期,最后格式出来的日期都是月份第一天或最后一天,所以也要慎用

即便下面的日期为:2020-03-15这样正常的日期格式化后仍然是2020-03-01或2020-03-31:如下1

1、var_dump(date("Y-m-d", strtotime("last day of -1 month", strtotime("2020-03-15"))));
//输出2020-02-28

var_dump(date("Y-m-d", strtotime("last day of -1 month", strtotime("2020-03-31"))));
//输出2020-02-28
 
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-28

下面提供兼容解决:解决因每月天数不等,导致的对月份增减可能得不到逾期结果的问题:不让月份延伸到预期月份的下一个月

var_dump(strMonthDate(-1, '2022-03-31'));
// 2022-02-28

var_dump(strMonthDate(1, '2022-03-31'));
// 2022-04-30

/**
 * @param int $month 加减月份数
 * @param string $strToDate "Y-m-d 或 Y-m-d H:i:s 格式"
 * @param string $type
 * @return false|string
 */
function strMonthDate(int $month, string $sourceDate = '', string $type = 'date')
{
    if ($sourceDate) {
        $dateTime = '#^(21|20|19)\d{2}-((0[1-9])|(1[0-2]))-(([012][0-9])|(3[01]))\s((([01]\d)|(2[0-3])):[0-5]\d:[0-5]\d)$#';
        $date = '#^(21|20|19)\d{2}-((0[1-9])|(1[0-2]))-(([012][0-9])|(3[01]))$#';
        if (!preg_match($date, $sourceDate) && !preg_match($dateTime, $sourceDate)) {
            new \phpDocumentor\Reflection\DocBlock\Tags\Throws("Error", "日期格式错误");
        }
    } else {
        $sourceDate = date('Y-m-d H:i:s');
    }
    // 原始日期时间戳
    $timestamp = strtotime($sourceDate);
    $sourceDay = date('d', $timestamp);

    // 获取原始日期月份第一天:无论加减,月份第一天都不会有bug
    $monthFirstDay = date('Y-m-01 H:i:s', $timestamp);

    // 月份增减
    $newDate = strtotime($month . ' month', strtotime($monthFirstDay));
    $newMonthDays = date('t', $newDate);
    if ($sourceDay > $newMonthDays) {
        $sourceDay = $newMonthDays;
    }

    if ($type == 'date') {
        return date('Y-m-' . $sourceDay, $newDate);
    } else {
        return date('Y-m-' . $sourceDay . ' H:i:s', $newDate);
    }
}

评论区

励志做一条安静的咸鱼,从此走上人生巅峰。

0

0

0

举报