2016-05-25 10 views
2

いくつかのレポートでは、次の6ヶ月間をループして計算を開始/終了範囲を計算しています。毎月、これはループし、setDate()は最初の1ヶ月間は正しく動作します。PHP DateTime :: setDate()はDatePeriodの最初の繰り返しでは機能しません

# Loop over the next 6 months (from start of this month) 
$now = new DateTime("first day of this month", new DateTimeZone("Pacific/Auckland")); 

$end = clone $now; 
$end->modify("+6 month"); 

$int = new DateInterval("P1M"); 
$period = new DatePeriod($now, $int, $end); 

# For each month, work out the start/end dates and times for the reports 
foreach ($period as $month) { 
    $start = clone $month; 
    $start->setDate($start->format("Y"), $start->format("m"), 1); 
    $start->setTime(0, 0, 0); 

    $end = clone $month; 
    $end->setDate($end->format("Y"), $end->format("m"), $end->format("t")); 
    $end->setTime(23, 23, 59); 

    # Dumping out data here shows weirdness below 
} 

最初の月末は第1位になります。私が他の有効な日の整数に手動で設定したとしても。私は裸の例にこれを取り除きました、そして、それはまだそれをやっています。

string(19) "2016-05-01 00:00:00" 
string(19) "2016-05-01 23:23:59" <- Huh? This should be 31 
=========== 
string(19) "2016-06-01 00:00:00" 
string(19) "2016-06-30 23:23:59" 
=========== 
string(19) "2016-07-01 00:00:00" 
string(19) "2016-07-31 23:23:59" 
...etc... 

特定relative formatsを使用してDateTimeオブジェクトを作成するとき、私はPHPでPHPに5.5.26

+1

[重複](https://eval.in/577274) –

+0

私は '2016年5月1日午後12時00 '' 'に "今月の最初の日" を変更した場合:それが誰かに何か考えを与える場合には、期待通りに動作します。 – Mike

+0

'$ now-> setDate($ now-> format(" Y ")、$ now-> format(" m ")、1); $ period = new DatePeriod( 'R6 /' .$ now-> format( 'Ymd \ TH:i:s') 'Z/P1M'); ' – Mike

答えて

1

バグです。これは、このような'last day of next month''first day of this month'として、DateTimeオブジェクトを作成するために、一定の相対的なフォーマットを使用する場合にのみ起こるようです

PHP Bug #63863 DateTime:setDate() date not used after modify("last day of...")

、しかし'last sat of July 2008'エラーが発生することはありません。

コメントの中でMikeに感謝します。

単純な回避策を使用するには、別の方法を使用して、$nowのDateTimeオブジェクトを作成します。

https://eval.in/577984

# Loop over the next 6 months (from start of this month) 
$now = new DateTime("now", new DateTimeZone("Pacific/Auckland")); 
$now->setDate($now->format("Y"), $now->format("m"), 1); 

$end = clone $now; 
$end->modify("+6 month"); 

$int = new DateInterval("P1M"); 
$period = new DatePeriod($now, $int, $end); 

# For each month, work out the start/end dates and times for the reports 
foreach ($period as $month) { 
    $start = clone $month; 
    $start->setDate($start->format("Y"), $start->format("m"), 1); 
    $start->setTime(0, 0, 0); 

    $end = clone $month; 
    $end->setDate($end->format("Y"), $end->format("m"), $end->format("t")); 
    $end->setTime(23, 23, 59); 

    echo $start->format('Y-m-d H:i:s') . "\n"; 
    echo $end->format('Y-m-d H:i:s') . "\n"; 
} 
+0

明らかに、 'new'の使用法が最適化されていなければなりません。実際にその動作を引き起こしているのはまだ不思議です。 –

+1

実際にはクローニングのバグではなく、特定の[相対フォーマット](http://php.net/manual/en/datetime.formats.relative.php)を使用して作成されたオリジナルオブジェクトのバグです(今月の初日)」(バグレポート:https://bugs.php.net/bug.php?id=63863)を参照してください。 – Mike

+0

@Mike Ahh!今はすべて理にかなっています。良い見つけて、ありがとう。 (編集) –

関連する問題