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

标签 php datetime

我需要在 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/

相关文章:

php - 如何检测mySQL数据库的分组结果是否有相关值?

php - 在 laravel 中找到集合?例子

javascript - 在另一个 div 中显示选项值

sql-server - 将日期时间评估为时间窗口

c# - 在 C# 中创建特定时区的 DateTime

迄今为止的 bash 字符串

javascript - 使用 Ajax 更新 href ID

PHP:试图弄清楚如何从字符串中提取单词

带有内部连接的 2 个表的 mysql 查询

r - 如何使用 dplyr 和 RPostgreSQL 将字符日期时间转换为可用?