【问题标题】:PHP: date functions' results related to NEXT month are not correct (PHP bugs or sg. else?)PHP:与下个月相关的日期函数结果不正确(PHP 错误或 sg.else?)
【发布时间】:2012-05-31 13:12:15
【问题描述】:

我尝试了一些日期函数,因为我想用 PHP 获取下个月的一些日期,但是我遇到了一些问题。

作为 MySQL 兼容时间戳 (date('Y-m-d H:i:s');) 的当前日期如下:
'2012-05-31 14:59:19'

  • date('t', strtotime('next month')); 给出 下个月的天数,结果返回 31...这是不正确的,因为 June 仅包含 30天(好像它输出了七月的日子)。
  • date('Y-m-d H:i:s', strtotime('next month'));,给出下个月的时间戳格式,返回'2012-07-01 14:59:19',但我希望得到以下结果:
    '2012-06-30 14:59:19'

所以我尝试了一些代码,这是我的实验,使用date()strtotime()DateTime classhttp://pastebin.com/3iaH4iSZ

输出如下所示 (you can also see it here!):

这些是 PHP 错误,还是我误解了什么?


我希望得到与使用 MySQL 的日期函数时相同的结果,仅举几个例子:

SELECT NOW( )

2012-05-31 17:51:15

SELECT DATE_ADD(NOW(), INTERVAL 1 MONTH)

2012-06-30 17:51:15

SELECT DATE_ADD( '2013-01-30 17:51:15', INTERVAL 1 MONTH )

2013-02-28 17:51:15

SELECT DATE_ADD( '2013-01-31 17:51:15', INTERVAL 1 MONTH )

2013-02-28 17:51:15

【问题讨论】:

标签: php datetime date timestamp


【解决方案1】:

好的,我想我找到了解决方案,它的行为类似于 MySQL 的 DATE_ADD 函数和 INTERNAL 1 MONTH
我用所有可能有问题的情况测试了我的功能,它似乎工作正常。
我把它贴在这里,也许有人会觉得它有用。我在这段代码中放了一些cmets,所以我觉得已经够清楚了。

该函数称为getOneMonthLaterTimestamp。一个例子:

echo getOneMonthLaterTimestamp('2012-05-31 17:51:15');

输出:2012-06-30 17:51:15

函数

/**
 * Test function for dumping variables in a readable way
 * 
 * @param mixed $stuff
 * @param string $text
 * @return string 
 */
function my_var_export($stuff, $text = '...') {
    return '<p>' . $text . ' (' . gettype($stuff) . '):</p><pre>' . var_export($stuff, TRUE) . '</pre>';
}

/**
 * Get timestamp format of the date one month later 
 * than the date given in the argument/current date if left empty.
 * 
 * Behaves similar to MySQL's DATE_ADD function with INTERVAL 1 MONTH:
 * SELECT DATE_ADD('2012-05-31 17:51:15', INTERVAL 1 MONTH)
 * --> 2012-06-30 17:51:15
 * SELECT DATE_ADD('2013-01-30 17:51:15', INTERVAL 1 MONTH )
 * --> 2013-02-28 17:51:15
 * 
 * these are equivalent to:
 * echo getOneMonthLaterTimestamp('2012-05-31 17:51:15');
 * echo getOneMonthLaterTimestamp('2013-01-30 17:51:15');
 * 
 * You can also call it without an argument. This way, the current date is taken as a basis.
 * echo getOneMonthLaterTimestamp();
 * 
 * @param string $DateTime_param date/time string
 * @see http://www.php.net/manual/en/datetime.formats.php
 * @see http://www.php.net/manual/en/datetime.construct.php
 * 
 * @return string Date one month later as a MySQL-compatible timestamp format
 */
function getOneMonthLaterTimestamp($DateTime_param = NULL) {
    // if argument is left empty, the current date is taken as a basis
    if (empty($DateTime_param)) {
        $DateTime_param = date('Y-m-d H:i:s');
    }

    $lastDayOfNextMonth = new DateTime($DateTime_param);
    $lastDayOfNextMonth->modify('last day of next month');

    $nextMonth = new DateTime($DateTime_param);
    $nextMonth->modify('next month');

    if ($lastDayOfNextMonth->format('n') < $nextMonth->format('n')) {
        $oneMonthLaterTimestamp = $lastDayOfNextMonth->format('Y-m-d H:i:s');
    }
    else {
        $oneMonthLaterTimestamp = $nextMonth->format('Y-m-d H:i:s');
    }

    return $oneMonthLaterTimestamp;
}

测试用例

$timestamps_to_test_array = array(
  date('Y-m-d H:i:s'),   // 1. current date
  '2011-01-28 23:59:59', // 2.
  '2011-01-29 23:59:59', // 3.
  '2011-01-30 23:59:59', // 4.
  '2011-01-31 23:59:59', // 5.
  '2012-01-28 23:59:59', // 6.
  '2012-01-29 23:59:59', // 7.
  '2012-01-30 23:59:59', // 8.
  '2012-01-31 23:59:59', // 9.
  '2012-02-29 23:59:59', // 10.
  '2012-03-30 23:59:59', // 11.
  '2012-03-31 23:59:59', // 12.
  '2012-04-30 23:59:59', // 13.
  '2012-05-31 23:59:59', // 14.
  '2012-12-31 23:59:59', // 15.
  '2013-01-31 23:59:59', // 16.
  '2013-02-28 23:59:59', // 17.
);

$i = 1;

foreach ($timestamps_to_test_array as $timestamp_to_test) {
    $oneMonthLaterTimestamp = getOneMonthLaterTimestamp($timestamp_to_test);
    echo my_var_export($timestamp_to_test, '[' . $i . ']. Timestamp to test ($timestamp_to_test)');
    echo my_var_export($oneMonthLaterTimestamp, 'Timestamp + 1 month (getOneMonthLaterTimestamp($timestamp_to_test))');
    echo '<hr />';
    $i++;
}

测试用例的输出

我在此处粘贴了输出:http://pastebin.com/rY5ZRBs9
这是它的截图:http://i.imgur.com/KwlJq.png

获取下个月的天数

/**
 * Get number of days in the next month
 *
 * @param string $DateTime_param date/time string
 * @return int Number of days in the next month
 */
function getNumberOfDaysInNextMonth($DateTime_param = NULL) {
    // if argument is empty, the current date is taken as a basis
    if (empty($DateTime_param)) {
        $DateTime_param = date('Y-m-d H:i:s');
    }

    // DateTime instance
    $dateCurrent = new DateTime($DateTime_param);
    $dateCurrent->modify('last day of next month');
    return (int)$dateCurrent->format('t');
}

/**
 * It's identical to getNumberOfDaysInNextMonth()
 *
 * @see getNumberOfDaysInNextMonth
 */
function getLastDayOfNextMonth($DateTime_param = NULL) {
    return getNumberOfDaysInNextMonth($DateTime_param);
}

测试用例

$lastDayOfNextMonth = getLastDayOfNextMonth('2012-05-31 03:50:27');
echo my_var_export($lastDayOfNextMonth, "Get last day of next month (getLastDayOfNextMonth('2012-05-31 03:50:27'))");

输出

Get last day of next month (getLastDayOfNextMonth('2012-05-31 03:50:27')) (integer):
30

【讨论】:

    【解决方案2】:

    截至目前:

    获取下个月作为时间戳 [ date('Y-m-d H:i:s', strtotime('next month')); ]:
    '2012-07-01 14:59:19'

    使用 DateTime 类 [ $dateObj->add(new >DateInterval('P1M')); 获取下个月的最后一天作为时间戳$dateObj->format('Y-m-d H:i:s'); ]:
    '2012-07-01 14:59:19'

    很明显,“下个月”输出的日期是 7 月...

    改用strtotime('+1 month')

    编辑:解释: 今天是5月31日。如果您致电strtotime('next month'),它会尝试获取不正确的 6 月 31 日日期,因此它会非常正确地输出 7 月 1 日的日期...因此我猜strtotime('+1 month') 也会失败...

    因此更好的解决方案是获取当月第 15 天的日期并使用“下个月”或“+1 个月”到该日期...

    【讨论】:

    • 不这么认为...我想它只会增加+31天并将日期更正为有效日期...二月也是如此...如果您认为这是一个错误然后将其发布到 PHP bugtracker,你会看到...
    • 今天早上就这个主题引用@rasmus:“这是本月的 31 号。在提交有关 PHP 中相对日期的错误之前,请阅读 gnu.org/software/tar/manual/html_node/…
    • @MarkBaker 我读过它。但也许他们可以做一些工作,而不是为底层 C 函数提供简单的 API。就像 strftime 在 windows 上使用不同的修饰符(%#d 而不是 %e):我认为 php 应该抽象这种怪癖。
    • @shadyyx:好的,但我真的很惊讶在实际月份的第 31 天(如果该月的 31 号是有效日期)“下个月”增加了 31 天,这是实际月份的天数,这会打乱整个计算。因此,正如您所提到的,我认为这不是“正确”的行为。 :) 但感谢您的帮助!所以,总结一下:这样,你是否应该检查实际日期是否是当月的 31 日,如果是,你应该在这个日期上加一天,然后计算那个月的月底,这样你就得到了 30 日本月?
    • 对了,如果是 2 月 28 日呢?
    【解决方案3】:

    你可以通过一些小的操作来实现你想要的(即如果我的问题是正确的)

    $next_month = mktime(0, 0, 0, date("m")+1, 1, date("Y"));
    //gets next month
    echo "<br />".date("D jS M, Y", $next_month);
    //sets the value
    echo "<br />".date("t", $next_month);
    //number of days next month
    

    这应该可以让您访问所需的月份,因为每个月都有 first 一天。 换句话说,要获得第二年,您只需更改适当的值

    【讨论】:

    • 好的,谢谢,这是获取下个月天数的一个很好的例子,但是如果我只想在当前日期上简单地增加一个月呢?那么,在当前日期加上一个月而不是获得'2012-07-01 18:26:19' 时,我将如何获得'2012-06-30 18:26:19'?顺便说一句,我赞成你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多