唯物是真 @Scaled_Wurm

プログラミング(主にPython2.7)とか機械学習とか

PHP関連で読んだドキュメントの翻訳が間違っていて(?)日付の書式に%Gを書いてハマった話

日付を表す書式文字列の一つに%Gというものがあります(意味するところはツールや関数によって違うかもしれません)
PHPの日本語ドキュメントと、テンプレートエンジンのSmartyのドキュメントがわかりづらくて、西暦の4桁の年を表示する%Yと間違えて%Gを使ってしまい年末年始に値がずれておかしくなるという罠にハマりました
年末年始にだけ起こるわかりにくいバグを仕込みたい方におすすめです

どんな罠があるか

ほとんどの期間は%Yと%Gは等しいのですが、年末年始にだけ%Gは通常の年と1つずれた値を出力することがあります
たとえば2017年1月1日は%Gでは2016を出力します

echo strftime('%G-%m-%d', strtotime('2017-01-01')); // 2016-01-01

何故こうなるかというと%Gは週番号を基づいて表記するときの年を表しているらしいからです
この表記法ではある日付はユニークな年と週番号(月曜始まり)、曜日のセットで表されるようになっていて、年末年始の日は週の中で多い方の年に割り振られます
つまり年末の数日が翌年になったり年始の数日が前年になったりします

以下あたりの記事の説明が分かりやすかったです

年をまたぐ週は、日数が多い方の年に属するものとする

http://d.hatena.ne.jp/casualstartup/20130908/iso_weeknum

最初の木曜日を含む週が、その年の第1週である
その年の第1週は、1月4日を含む週である

https://ja.wikipedia.org/wiki/ISO_8601

わかりづらいドキュメント

Smarty

冒頭でドキュメントがわかりづらかったと書きましたが、実際にPHPのテンプレートエンジンのSmartyの日本語版ドキュメントを見てみましょう
f:id:sucrose:20161222003254p:plain
%Gの説明は以下のようになっています

%G - 西暦 [0000,9999]

http://www.smarty.net/docsv2/ja/language.modifier.date.format.tpl

同様に%Yは以下のようになっています

%Y - 世紀を含む年を10進数で表現

http://www.smarty.net/docsv2/ja/language.modifier.date.format.tpl

違いがわかりましたか?
自分にはよくわかりませんでした

この疑問は英語版のドキュメントを見ると氷解します
f:id:sucrose:20161222003841p:plain
英語版には%Gの説明にWeek-based yearと書かれていて、この情報が日本語版のドキュメントでは抜け落ちていることがわかります

%G - Week-based year, including the century [0000,9999]

http://www.smarty.net/docsv2/en/language.modifier.date.format.tpl

PHP公式

テンプレートエンジンのドキュメントだけでなくPHP公式のドキュメントにも間違いがあります
f:id:sucrose:20161222004330p:plain
以下のように%Gについて例が書かれていますが

2009 年 1 月 3 日の場合は 2009

http://php.net/manual/ja/function.strftime.php

英語版を見ると
f:id:sucrose:20161222004528p:plain
2009 年 1 月 3 日の場合は 2008と書かれていて、%Gが通常の年を表すわけではない例になっています
つまり日本語版の翻訳は1年ずれていて%Yの場合の値を表示しており間違っています

2008 for the week of January 3, 2009

http://php.net/manual/en/function.strftime.php

まとめ

うっかり%Gを使わないように気をつけましょう

翻訳されたドキュメントは必ずしも信用してはいけないという教訓を得ました(?)

余談

今回検索してみたら同様の問題が昔Twitterでも起こっていたっぽくてログインできなくなっていたという記事を見つけたのでついでに貼っておきます

http://weblog.bulknews.net/post/106956075184/rebuild-73-it-is-2015-already-n-naan
weblog.bulknews.net
dechnostick.hatenablog.com