1年と言っても必ずしも365日とはならないです。4年に1回のうるう年は366日となります。さて、この1年というあいまいな定義をデータベースのSQLあるいはプログラムで計算するとどういう結果になるかという話です。

SQLで計算

こういうときは、もちろんtinkerを使います。
一番最近のうるう年の2020-02-29を起点として、まずDBでの1年後の計算。

> DB::select(DB::raw('select DATE_ADD("2020-02-29", INTERVAL 1 YEAR)'));
= [
    {#30074
      +"DATE_ADD("2020-02-29", INTERVAL 1 YEAR)": "2021-02-28",
    },
  ]

1年の代わりに365日を足しても同じです。

> DB::select(DB::raw('select DATE_ADD("2020-02-29", INTERVAL 365 DAY)'));
= [
    {#30059
      +"DATE_ADD("2020-02-29", INTERVAL 365 DAY)": "2021-02-28",
    },
  ]

今度は引き算で1年前の計算。

> DB::select(DB::raw('select DATE_SUB("2020-02-29", INTERVAL 1 YEAR)'));
= [
    {#30062
      +"DATE_SUB("2020-02-29", INTERVAL 1 YEAR)": "2019-02-28",
    },
  ]

1年の代わりに、365日を引くと、

> DB::select(DB::raw('select DATE_SUB("2020-02-29", INTERVAL 365 DAY)'));
= [
    {#30090
      +"DATE_SUB("2020-02-29", INTERVAL 365 DAY)": "2019-03-01",
    },
  ]

1日分の差が出ました。最初のは2月の最後から1年前の2月の最後という計算ですね。

※ちなみにこれはmysqlの結果です。

phpの関数で計算

今度は、Carbonを使用して計算です。

> use Carbon\Carbon;
> Carbon::parse('2020-02-29')->addYear(1)->format('Y-m-d');
= "2021-03-01"

あれ、365日計算でないですね。

> Carbon::parse('2020-02-29')->addDays(366)->format('Y-m-d');
= "2021-03-01"

366日の計算です。

今度は引き算で1年前の計算。

> Carbon::parse('2020-02-29')->subYear(1)->format('Y-m-d');
= "2019-03-01"

むむ。今度は365日の計算となりました。

> Carbon::parse('2020-02-29')->subDays(365)->format('Y-m-d');
= "2019-03-01"

By khino