01. 12月 2012 · [PHP] PHP5 の strtotime の年またぎの挙動が変わってた → 時限爆弾になってハマったこと はコメントを受け付けていません。 · Categories: WEB制作 · Tags: ,

PHP
参考:PHP: strtotime – Manual

strtotime は、特定の書式の日付(文字列)を UNIX タイムスタンプに変換する関数です。
PHP4 では、下記のような引数を入れても正常に動作していました。

これが PHP5 になると、まったく動作しません。

strtotime(‘2012-13-00’) の結果が FALSE になるためです。
引数に存在しない日付を入れてるからだろうと思うなかれ、下記は PHP4 でも PHP5 でも同じ挙動です。(2012年はうるう年です)

要するに、年が増えると FALSE になってしまうのですね。これについてはこの辺が参考になると思います。

参考:PHP: 日付の書式 – Manual

注意:

シンボル dd と DD について、 オーバーフローやアンダーフローすることができます。 つまり、 0 日は先月の最終日の意味になりますし、 オーバーフローすると翌月に繰り越しになります。 このルールにより、”2008-08-00″ は “2008-07-31” と同一になり、 “2008-06-31” は “2008-07-01” と同一になります ( 6 月は 30 日までしかないので)。

また、シンボル mm と MM についても 0 を用いてアンダーフローすることができます。 0 月は前年の 12 月を意味します。 たとえば “2008-00-22” は “2007-12-22” と同一です。

もしこれらを併用し、日も月もアンダーフローした場合は次のようになります。 “2008-00-00” は、まず “2007-12-00” へと変換され、 さらに “2007-11-30” へと変換されます。 文字列 “0000-00-00” についても同様に “-0001-11-30” へと変形されます。 (ISO 8601 における -1 年は、予測的グレゴリオ暦 (proleptic Gregorian calendar) で言うところの紀元前 2 年になります。)

「アンダーフロー」というのは、0より小さくなった場合に繰り上げて処理すること、「オーバーフロー」というのは、例えば月だったら12より大きくなった場合に繰り越して処理すること。
2行目の「シンボル mm と MM についても~」という部分。アンダーフローについては記載がありますが、オーバーフローについては可とも不可とも記載がありません。

ただまあ、「使えてたから使った」というのは「無知は罪である」というのと通じるところがありますね。strtotime のマニュアルに、下記のような記載があります。

注意:

この関数を使って日付の足し算や引き算を行うことはおすすめできません。 PHP 5.3 以降なら DateTime::add() や DateTime::sub() を、そして PHP 5.2 なら DateTime::modify() を使いましょう。

「おすすめできません」とあるのだから、使うほうが間違っているのです。
上記は PHP5 以上ならという制限があるので、PHP4でも挙動が変わらない mktime を使うべきですね。こっちなら間違いありません。

これだからデザイナー上がりの自称 PHPer は!とか随所から聞こえてきそうですが、自戒を込めての post でした。


Comments closed