无法从PHP中的DateTime获取上个月 - 这是一个(相当大的)错误吗?

Yar*_*rin 3 php datetime

我需要在PHP中创建函数,让我在给定的日期时间单位上升/下移.具体来说,我需要能够从当前月份进入下一个/上个月.

我想我可以使用DateTime :: add/sub(P1M)来做到这一点.然而,当试图获得前一个月时,如果日期值= 31-看起来它实际上试图倒数30天而不是递减月值,则会变得混乱!:

$prevMonth = new DateTime('2010-12-31'); 
Run Code Online (Sandbox Code Playgroud)

尝试减少月份:

$prevMonth->sub(new DateInterval('P1M')); // = '2010-12-01'
$prevMonth->add(DateInterval::createFromDateString('-1 month')); // = '2010-12-01'
$prevMonth->sub(DateInterval::createFromDateString('+1 month')); // = '2010-12-01'
$prevMonth->add(DateInterval::createFromDateString('previous month')); // = '2010-12-01'
Run Code Online (Sandbox Code Playgroud)

这肯定是错误的行为.有人有任何见解吗?谢谢-

注意: PHP版本5.3.3

Yar*_*rin 6

(信用实际上属于亚历克斯在评论中指出这一点)

问题不是PHP,而是GNU,如下所述:

日期字符串中的相对项

这里的关键是区分"上个月这个日期"的概念,因为月份是具有不同日期数量的"模糊单位",因此无法定义12月31日这样的日期(因为11月31日不存在) ,以及"上个月,不论日期"的概念.

如果我们感兴趣的只是前一个月,那么保证正确的DateInterval计算的唯一方法是将日期值重置为1st,或者每个月将有一些其他数字.

真正令我印象深刻的是这个问题在PHP和其他地方没有记录 - 考虑到它可能影响的日期相关软件的数量.

这是一种安全的方法来处理它:

/*
Handles month/year increment calculations in a safe way,
avoiding the pitfall of 'fuzzy' month units.

Returns a DateTime object with incremented month/year values, and a date value == 1.
*/
function incrementDate($startDate, $monthIncrement = 0, $yearIncrement = 0) {

    $startingTimeStamp = $startDate->getTimestamp();
    // Get the month value of the given date:
    $monthString = date('Y-m', $startingTimeStamp);
    // Create a date string corresponding to the 1st of the give month,
    // making it safe for monthly/yearly calculations:
    $safeDateString = "first day of $monthString";
    // Increment date by given month/year increments:
    $incrementedDateString = "$safeDateString $monthIncrement month $yearIncrement year";
    $newTimeStamp = strtotime($incrementedDateString);
    $newDate = DateTime::createFromFormat('U', $newTimeStamp);
    return $newDate;
}
Run Code Online (Sandbox Code Playgroud)