CakePHP3:日付のフォーマット、YYYY vs yyyy

CakePHP3のi18nFormatはとても便利な関数ですが、年の指定をyyyyと書くべきところをYYYYと記述すると落とし穴があります

yyyyは、カレンダー上の年です。例えば、2017年12月31日の場合、yyyyの値は2017です:

        $timezone_string = 'America/Los_Angeles';
        $year  = 2017;
        $month = 12;
        $day   = 30;

        $raw_post_date = Time::createFromFormat(
            'Y-m-d',
            implode('-',[$year, $month, $day]),
            $timezone_string
        );

        echo $raw_post_date->i18nFormat("yyyy/MM/dd",$timezone_string);

→2017/12/31と出力されます。

上のコードのyyyyYYYYに変更すると、2018/12/31になります。

原因ですが、YYYYはその日が何年であるかではなく、 その日が含まれる週の土曜日(木曜日という説もあり…)が何年であるかを返すためです。

念のため、2017年12月31日をカレンダーで見てみます:

f:id:thebaker:20180102122757p:plain

31日は日曜日、その週の土曜日は2018年1月6日なのでYYYYが2018を返却するわけですね。

ソース:

ICU 60.2: icu::SimpleDateFormat Class Reference