かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

PHP 1年後の今月末を知りたいにハマる。

PHPでnヶ月後の月末を取得したい場合、(n+1)ヶ月後の1日を取得して1日引けばOKというのをよく見かけるので、1年後なら13ヶ月後の1日を取得して...と思いコードを書いていました。

<?php
// 今日の日付
$today = $date();
// 13ヶ月後の日付
$after13m = strtotime('+13 month', strtotime($today));
$year = date('Y', $after13m);
$month = date('m', $after13m);
// 13ヶ月後の1日
$firstDate = $year . '-' . $month . '-01'; 
// 1年後 (12ヶ月後) の月末の日
$after12EndDate = date('Y-m-d', strtotime('-1 day', strtotime($firstDate));

コレでほしい日付が取得できていました。
しかし!
本日2015-03-31にこのプログラムを動かした所、本来であれば1年後の月末は2016-03-31が取得される想定だったのですが2016-04-30と表示されてしまいました。
オォォーーー!! w(゚ロ゚;w(゚ロ゚)w;゚ロ゚)w オォォーーー!!
な、なぜ...

なんとなく一ヶ月の日数が30日だったり31日する辺りが関係しているような気がしました。

13ヶ月後の日付を調べてみる

取得されている13ヶ月後の日付をチェックしてみます。

<?php
// 今日の日付
$today = $date();
var_dump($today); // 2015-03-31

// 13ヶ月後の日付
$after13m = strtotime('+13 month', strtotime($today));

var_dump($after13m); // 2016-05-01

$year = date('Y', $after13m);
$month = date('m', $after13m);
// 13ヶ月後の1日
$firstDate = $year . '-' . $month . '-01';

var_dump($firstDate); // 2016-05-01
 
// 1年後 (12ヶ月後) の月末の日
$after12EndDate = date('Y-m-d', strtotime('-1 day', strtotime($firstDate));

var_dump($after12EndDate); // 2016-04-30

13ヶ月後が2016-05-01と表示されていました。。。
本来ほしいのは2016-04-30なのですが、3月が31日まであるので、2016-04-31となってしまい、自動的に翌月1日の2016-05-01に変換されているのではないかと想像します。

解決方法

月末を取得する作業の中で13ヶ月後の1日の日付を取得する必要があるので、今日からではなく今月の1日から13ヶ月後としてしまえば間違いがなさそうです。
コードを修正します。

<?php
// 今月の1日を取得
$currentM01 = $date( 'Y-m-01' );
var_dump($currentM01); // 2015-03-01

// 13ヶ月後の日付 
$after13m1stDate = strtotime('+13 month', strtotime($after13m));
// 1日から13ヶ月後なので取得できるのは13ヶ月後の1日になる
var_dump(after13m1stDate); // 2016-04-01

// 1年後 (12ヶ月後) の月末の日
$after12EndDate = date('Y-m-d', strtotime('-1 day', after13m1stDate);
var_dump($after12EndDate); // 2016-03-31

問題も解決して、コードの量も減りました!
урааааааааа!!


[参考]