2

strotime如果您需要可靠且准确的日期操作,您似乎无法使用。例如,如果该月有 31 天,那么看起来strtotime只是减去 30 天,而不是一整月。

因此,例如,如果$event["EndDate"]等于“2013-10-31 00:00:01”,则以下代码:

echo date("Y/n/j", strtotime('-1 month', strtotime($event["EndDate"]));

输出:2013/10/1而不是2013/09/30.

问题:现在我怎么知道如何不这样做,是否有另一种更准确的方法来使 PHP 减去(或添加)整整一个月,而不仅仅是 30 天?

4

2 回答 2

2

主要问题是2013/09/31不存在因此更好的方法是使用first daylast day上个月的。

$date = new DateTime("2013-10-31 00:00:01");
$date->modify("last day last month");
echo $date->format("Y/n/j"); // 2013/9/30

当日期是2013-10-15

$date = new DateTime("2013-10-15 00:00:01");
$day = $date->format("d");
$year = $date->format("Y");

$date->modify("last day last month");
$month = $date->format("m");

if (checkdate($month, $day, $year)) {
    $date->setDate($year, $month, $day);
}

echo $date->format("Y/n/j"); // 2013-9-15
于 2013-05-08T17:41:37.833 回答
1

你说:-

如果您需要可靠且准确的日期操作,您似乎无法使用 strotime

你可以,你只需要知道它的行为方式。您的问题促使我进行了几次测试。


PHP 不只是在减去一个月时从日期中减去 30 天,尽管它似乎是从您正在查看的单个案例中得出的。事实上,我在这里的测试表明,在这种情况下,它比上个月的开始增加了 31 天(3 月 3 日的结果向我表明了这一点)。

$thirtyOnedayMonths = array(
    1, 3, 5, 7, 8, 10, 12
);

$oneMonth = new \DateInterval('P1M');
$format = 'Y-m-d';

foreach($thirtyOnedayMonths as $month){
    $date = new \DateTime("2013-{$month}-31 00:00:01");
    var_dump($date->format($format));
    $date->sub($oneMonth);
    var_dump($date->format($format));
}

2013-11-12 和 2013-10-12 之间有 31 天,PHP 可以正确计算月份减法,如下所示

$date = new \DateTime('2013-11-12 00:00:01');
var_dump($date);
$interval = new DateInterval('P1M');
$date->sub($interval);
var_dump($date);

在您的特定情况下 2013-10-31 - 1 month 是 2013-09-31 ,它不存在。任何日期/时间函数都需要返回有效日期,而 2013-09-31 则不是。

在这种情况下,正如我上面所说的,PHP 似乎在上个月的开始时间增加了 31 天才能到达有效日期。

一旦你知道了预期的行为,你就可以进行相应的编程。如果当前行为不适合您的用例,那么您可以扩展 DateTime 类以提供适合您的行为。

我已经假设strtotime并且DateTime::sub()行为相同,这个测试表明他们这样做。

$thirtyOnedayMonths = array(
    1, 3, 5, 7, 8, 10, 12
);

$format = 'Y-m-d';

foreach($thirtyOnedayMonths as $month){
    $date = date($format, strtotime('-1 month', strtotime("2013-{$month}-31 00:00:01")));
    var_dump($date);
}
于 2013-05-08T18:15:43.437 回答