Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从一个日期中减去整整一个月_Php_Datetime_Strtotime - Fatal编程技术网

Php 从一个日期中减去整整一个月

Php 从一个日期中减去整整一个月,php,datetime,strtotime,Php,Datetime,Strtotime,如果您需要可靠和准确的日期操作,那么似乎无法使用strotime。例如,如果一个月有31天,那么strotime似乎只是减去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 问题:现在我怎么知道怎么不做,有没有另一种更

如果您需要可靠和准确的日期操作,那么似乎无法使用
strotime
。例如,如果一个月有31天,那么
strotime
似乎只是减去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天?

主要问题是不存在
2013/09/31
,因此更好的方法是使用上个月的
第一天
最后一天

$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
你说:-

如果您需要可靠和准确的日期操作,那么您似乎无法使用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可以正确计算月份减法

在您的特殊情况下,2013年10月31日-1个月是2013年9月31日,该日期不存在。任何日期/时间函数都需要返回有效日期,而2013-09-31不是

在本例中,正如我前面所述,PHP似乎比上个月的开始时间多了31天,以获得一个有效日期

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

我假设strotime和
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);
}

如果你正在处理带有日期和时间的事件,那么就让自己的生活更轻松,并使用DateTime对象。我认为真正的问题是,它从10月31日减去一个月,返回9月31日,而9月31日并不存在,而是转换为10月1日。“如果我在10月29日获取你的代码并输入它,我会像预期的那样得到9月29日。”Blazemonger说,这将被严重破坏。我不敢相信strotime()(它实际上不是PHP的一部分,它是一个底层的通用C库)有这样的缺陷,因为2013/09/31不存在,问问你自己你希望返回什么。显然,任何语言的日期/时间函数都不能接受9月31日。在这种情况下,我认为你不能说9月30日比10月1日更正确。重要的是,这种行为是一致的和可预测的,我相信是的,尽管我还没有测试过它,尽管我可能会在有时间的时候做,因为这激发了我的好奇心。如果日期是2013-10-15,那就不好了——但我现在看到了这个问题。该死<代码>日期时间非常灵活。。我会更新我的代码,以显示如何实现这一点。。。
$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);
}