ソフトウェア開発者の日常

こだわりなく書きたいことを書いていきます。

年が変わると発覚する不具合

新年になって他部署が開発中のシステムをチェックするために、入力画面を表示しました。
表示された入力画面は、入力可能な期間が過ぎたら表示される「締め切り後」の画面が表示されています。

締め切られていた理由

「締め切り後」の画面が表示されている理由を調べました。
管理用の画面から締切日を設定できるようになっています。
管理用の画面上では、2018年4月30日に締め切る設定になっていることがわかりました。

締切日の設定はデータベースに保存されています。
データベースから取得した値は変数に、"2018-04-30 00:00:00"と代入されていました。

「締め切り前」か「締め切り後」かを判定する部分を確認すると、現在の日時を取得してフォーマットする部分が、

$now = date("Y/m/d H:i:s");

となっていました。
フォーマットされた現在の日時の値は、"2018/01/04 09:00:00"になります。

現在の日時の値とデータベースから取得した値は、"2018"までは一緒ですが、区切り文字が"/"と"-”で違います。
UFT-8での文字コードは、"-"はU+002D、"/"はU+0x002Fです。
2017年の間は2018より小さいので「締め切り前」、2018年になった途端、区切り文字の"/"が"-"より文字コード上大きいため、「締め切り後」の画面が表示されるということです。

f:id:AJYA:20180112233846j:plain
photo credit: Global Water Partnership - a water secure world GWP Virtual Network Meeting 2015 via photopin (license)

対処方法

$now = date("Y/m/d H:i:s");

$now = date("Y-m-d H:i:s");

に直したら、「締め切り前」と判定するようになりました。


別の対処方法としては、

// 実際はデータベースから取得
$limit = "2018-04-30 00:00:00";
$now = date("Y/m/d H:i:s");

if (strtotime(date($now)) > strtotime($limit)){

のように、strtotime()関数を使って、Unix タイムスタンプに変換して比較する方法があります。
PHP: strtotime - Manual
こちらの方が、区切り文字が違っていても変換されて関係なくなるので、安全なコードだと考えます。