4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHP - 翌月の同じ日の日付を返す

Posted at

PHP では次のようなコードで翌月の同じ日の日付を取得することができます。

$date = new DateTime('2017-01-1');
echo $date->modify('next month')->format('Y-m-d'); // 2017-02-01

これを日付を変えて次のようにすると、意図した日付を取得することができません。

$date = new DateTime('2017-01-31');
echo $date->modify('next month')->format('Y-m-d'); // 2017-03-03

ここでいう「意図した日付」=「翌月の同じ日の日付」とは次のとおりです。

  • 翌月に同じ日の日付が存在する場合、その日付
    • たとえば 1 月 1 日の場合、2 月 1 日は存在するので、2 月 1 日を翌月の同じ日の日付とする
  • 翌月に同じ日の日付が存在しない場合、翌月末日の日付
    • たとえば 1 月 31 日の場合、2 月 31 日は存在しないので、2 月 28 日を翌月の同じ日の日付とする(うるう年の場合は 2 月 29 日)

この仕様を実装したのが以下のコードです。

$date = new DateTime();
$date->setDate(2017, 1, 31);
$next = getNextMonth($date);
echo $next->format('Y-m-d');

function getNextMonth($baseDate)
{
    $date = clone $baseDate;
    $day = (int)$date->format('d');
    if ($day <= 28) {
        $date->modify('next month');
        return $date;
    }

    $date->modify('first day of next month');
    $year  = (int)$date->format('Y');
    $month = (int)$date->format('m');
    if (!checkdate($month, $day, $year)) {
        $day = (int)$date->format('t');
    }
    
    $date->setDate($year, $month, $day);
    return $date;
}

28 日までは単純に

$date->modify('next month')

で OK ですが、29 日以降は翌月に同じ日がない場合があるので、

checkdate($month, $day, $year)

で日付が存在するか確認して、存在しなければ末日を返すようにしています。

このコードは翌月固定ですが、n ヶ月後としたい場合は引数に月数を追加して少し修正すれば OK です。

なお、PHP: DateTime::modify - Manual にはこれとは違った実装方法が載っています。

4
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?