我需要在 PHP 中创建函数,让我可以在给定的日期时间单位上调/下调。具体来说,我需要能够从当前月份转到下一个月/上一个月。
我想我可以使用 DateTime::add/sub(P1M) 来做到这一点。但是,当尝试获取上个月时,如果日期值 = 31,它就会出错 - 看起来它实际上是在倒数 30 天而不是递减月份值!:
$prevMonth = new DateTime('2010-12-31');
尝试减少月份:
$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'
这看起来确实是错误的行为。任何人有任何见解? 谢谢-
注意:PHP 版本 5.3.3
最佳答案
(信用实际上属于亚历克斯在评论中指出这一点)
问题不是 PHP 问题而是 GNU 问题,如下所述:
Relative items in date strings
这里的关键是区分“上个月的这个日期”的概念,因为月份是具有不同日期数量的“模糊单位”,所以不可能为像 12 月 31 日这样的日期定义(因为 11 月 31 日没有' t 存在),以及“上个月,与日期无关”的概念。
如果我们只对前一个月感兴趣,那么保证 DateInterval 计算正确的唯一方法是将日期值重置为 1 号,或者每个月都会有的其他数字。
真正让我印象深刻的是这个问题在 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;
}
关于php - 无法从 PHP 中的 DateTime 获取上个月 - 这是一个(相当大的)错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4279634/