2012-01-09 110 views
1

我看到很奇怪的行为,与DateTime选择有时添加一天,而不是其他人。PHP的日期时间跳过添加

<?php 
// If you're running this after Jan 2012, use: new DateTime(date('Y-m-d', strtotime('2012-01-09'))); 
$month_end_date = new DateTime(); 
$month_end_date->modify('last day of this month'); 

$event_end_date = new DateTime('2012-03-15'); 

if ($event_end_date > $month_end_date) { 
    // Using this line a day is never added on below and the date stays as 31 Jan 2012 
    $event_end_date = clone $month_end_date; 
    // This line allows the ->add() call to work, and gives 1 Feb 2012 as output: 
    #$event_end_date = new DateTime($month_end_date->format('Y-m-d')); 
} 

$event_end_date->add(new DateInterval('P1D')); 

// Date should now be 1st Feb 
echo "Should be 1 Feb: ". $event_end_date->format('Y-m-d'); 
?> 

它似乎是->modify('last day of this month')线,它打破了我的代码;它会打印2012年2月1日,如果我有$month_end_date = new DateTime('2011-01-31');

$month_end_date = new DateTime('last day of this month'); 
$month_end_date = new DateTime($month_end_date->format(DateTime::W3C)); 

替换前两行或使用我的替代$event_end_date = new DateTime($month_end_date->format('Y-m-d'));

是否有意义,我需要在进行第二次修改之前调用格式?

+0

“行不通” 是发生了什么事的一个很模糊的描述。你能提供更多细节吗? – 2012-01-09 10:42:55

+0

我修改了我的帖子:破码输出2012-01-31,当它应该给2012-02-01。 – PeterB 2012-01-09 11:01:35

回答

1

它看起来直接在DateTime对象的构造函数中使用“first”或“last”会导致它变成不可变的。这看起来像一个错误。

例如

date_default_timezone_set('Europe/London'); 
ini_set('display_errors', 1); 
error_reporting(E_ALL); 

$interval = new DateInterval('P1D'); 

$date1 = new DateTime('last day of this month'); 
var_dump($date1); 
$date1->add($interval); 
var_dump($date1); 

echo "-------------------------------\n\n"; 

$lastDayOfMonth = date('Y-m-d H:i:s', strtotime('last day of this month')); 
$date2 = new DateTime($lastDayOfMonth); 
var_dump($date2); 
$date2->add($interval); 
var_dump($date2); 

echo "-------------------------------\n\n"; 

$date3 = new DateTime('2012-01-31 '.date('H:i:s')); 
var_dump($date3); 
$date3->add($interval); 
var_dump($date3); 

结果:

object(DateTime)[2] 
    public 'date' => string '2012-01-31 11:40:10' (length=19) 
    public 'timezone_type' => int 3 
    public 'timezone' => string 'Europe/London' (length=13) 

object(DateTime)[2] 
    public 'date' => string '2012-01-31 11:40:10' (length=19) 
    public 'timezone_type' => int 3 
    public 'timezone' => string 'Europe/London' (length=13) 

------------------------------- 

object(DateTime)[3] 
    public 'date' => string '2012-01-31 11:40:10' (length=19) 
    public 'timezone_type' => int 3 
    public 'timezone' => string 'Europe/London' (length=13) 

object(DateTime)[3] 
    public 'date' => string '2012-02-01 11:40:10' (length=19) 
    public 'timezone_type' => int 3 
    public 'timezone' => string 'Europe/London' (length=13) 

------------------------------- 

object(DateTime)[4] 
    public 'date' => string '2012-01-31 11:40:10' (length=19) 
    public 'timezone_type' => int 3 
    public 'timezone' => string 'Europe/London' (length=13) 

object(DateTime)[4] 
    public 'date' => string '2012-02-01 11:40:10' (length=19) 
    public 'timezone_type' => int 3 
    public 'timezone' => string 'Europe/London' (length=13) 
1

我已经缩短到一个简单的测试用例:

<?php 
date_default_timezone_set('Europe/Berlin'); 

$date = new DateTime('last day of this month'); 

$original_date = clone($date); 

$date->add(new DateInterval('P1D')); 

if ($date == $original_date) { 
    echo 'Fail' . PHP_EOL; 
} 

echo 'Original: ' . $original_date->format(DateTime::W3C) . PHP_EOL; 
echo 'Date:  ' . $date->format(DateTime::W3C) . PHP_EOL; 
echo 'Diff:  ' . $original_date->diff($date)->format('%d %H:%i:%s') . PHP_EOL; 

它提供:

[[email protected]][/tmp/php]$ php -v 
PHP 5.3.6 with Suhosin-Patch (cli) (built: Sep 8 2011 19:34:00) 
Copyright (c) 1997-2011 The PHP Group 
Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend Technologies 

[[email protected]][/tmp/php]$ php test.php 
Fail 
Original: 2012-01-31T11:47:47+01:00 
Date:  2012-01-31T11:47:47+01:00 
Diff:  0 00:0:0 

的“失败”行不应该是输出,如果日期递增。此外,请注意差异为0.这看起来像一个bug :)