PHP
CakePHP
I18n
cakephp3

CakePHP3のi18nFormat関数で大文字Yを使ってハマった


何が起こったか?

CakePHP3にて、「(FrozenTime型)日付」から「年」を取得する処理に怪しい動作を発見しました。


date.php

use Cake\I18n\FrozenTime;

:
$time = new FrozenTime('2019-03-12');
echo $time->i18nFormat('YYYY-MM-dd')."\n"; # => 2019-03-12 が表示される

$time = new FrozenTime('2019-12-31');
echo $time->i18nFormat('YYYY-MM-dd')."\n"; # => 2020-12-31 が表示される!?


実際のコードでは年度を $time->i18nFormat('YYYY') で取得しようとしていて、年末12/29~12/31あたりにおいて想定通りの年が取得できていませんでした。


CakePHP公式マニュアルでは?

日付を取得するには $time->i18nFormat('yyyy-MM-dd') というふうに y を小文字にするのが正しそうです。

大文字 Y を使ったサンプルはみつかりません。

とはいえ $time->i18nFormat('YYYY-MM-dd') でもそれっぽい値が取得できていますね。何が違うのでしょうか?


'y' と 'Y' の違い


"Uppercase Y is the year that the week of the timestamp in, in "Week of Year" based calendars. "

→ (大文字のYは、「Week of Year」ベースのカレンダーで、タイムスタンプの週が入った年です。)


2019年12月29日は、カレンダーで表示させると2020年の第1週でもあるため、大文字Yが2020を返したようです。


まとめ

CakePHP3のi18nFormat関数を使って日付を取得したいときは、$time->i18nFormat('YYYY-MM-dd') ではなく $time->i18nFormat('yyyy-MM-dd') を使いましょう!


確認環境

CakePHP 3.4.7

PHP 7.0.32