🐘

CakePHP(i18nFormat)の'y'と'Y'の話。

2022/09/03に公開

はじめに

変な挙動をたまたま見つけたので、メモった次第。

何が起きたか

CakePHPを使っている中で、日付周りで変な挙動を見つけた。ひとまず再現する。

i18n-format.php
$time = new FrozenTime('2021-12-26 11:22:33', 'Asia/Tokyo');
echo $time->i18nFormat('YYYY/MM/dd') . PHP_EOL;
echo $time->i18nFormat('yyyy/MM/dd');

// 結果
2022/12/26
2021/12/26

?!
Cake\I18n\FrozenTime::i18nFormatを使う際のフォーマットとしてYYYYyyyyで年数が違う。ちょっとよく分からないので色々調べてみた結果、i18nFormatIntlDateFormatterでフォーマットしていることが判明した。下の_formatObjectにそれが書かれてた。
以下のソースコードを参照
https://github.com/cakephp/cakephp/blob/4.x/src/I18n/DateFormatTrait.php#L182-L200

で、最後の引数はUnicodeになっており、年数に関して指定できるパターンがyYとがある、他にもuとかもいけると書いてあるが一旦無視。

Pettern Meaning
y year
Y year of “Week of Year”

Week of Yearって考え方があるようで、概要は以下。

ある年における「最初の木曜日を含む週が、その年の第1週である」というルールで年(西暦)を出力。

なので年末の日付を入力値にした時、次の年が返される。

まとめ

結論、yyyyとすれば、西暦通りの出力となるので、一件落着。

参考ページ

https://stackoverflow.com/questions/27695883/i18nformat-with-cakephp-3-why-does-yyyy-produce-a-different-year-than-yyyy
https://book.cakephp.org/4/ja/core-libraries/time.html#Cake\I18n\FrozenTime::i18nFormat
https://nakamura001.hatenablog.com/entry/20150102/1420213850
https://man.plustar.jp/php/intldateformatter.create.html
https://unicode-org.github.io/icu/userguide/format_parse/datetime/#date-field-symbol-table

Discussion