読者です 読者をやめる 読者になる 読者になる

php5.2.6からstrtotime関数の挙動が変わる

先日リリースした php5.2.6で、64ビットマシン上で、strtotime関数の挙動が変わるという現象がありました。


ChangeLogを見たところ
http://www.php.net/ChangeLog-5.php#5.2.6

Fixed bug #44209 (strtotime() doesn't support 64 bit timestamps on 64 bit platforms). (Derick)

http://bugs.php.net/bug.php?id=44209
bug fixとして、64ビットマシン対応がされているようです。
詳しく中まで見ていないので詳細はわかりませんが。

実際の現象

32ビットマシンの php5.2.5
$ php -v
PHP 5.2.5 (cli) (built: Feb 24 2008 20:45:22)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
    with Xdebug v2.0.0RC3, Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, by Derick Rethans

$ php -r 'var_dump(strtotime("0000-00-00"));'
bool(false)
32ビットマシンの php5.2.6
$ php -v
PHP 5.2.6 (cli) (built: May  9 2008 21:03:54)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies

$ php -r 'var_dump(strtotime("0000-00-00"));'
bool(false)
64ビットマシンの php5.2.6
$ php -v
PHP 5.2.6 (cli) (built: May  9 2008 13:10:59)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
    with XCache v1.2.2, Copyright (c) 2005-2007, by mOo

$ php -r 'var_dump(strtotime("0000-00-00"));'
int(-62170016400)


64ビットマシンの php5.2.5の環境が手元に無いのですが、バージョンアップ前は、この関数呼び出しで、falseで動作していました。

ドキュメント上は

http://jp.php.net/manual/ja/function.strtotime.php

注意: タイムスタンプの有効な範囲は、通常、Fri, 13 Dec 1901 20:45:54 GMT から Tue, 19 Jan 2038 03:14:07 GMT までです (これらは、32 ビット符号付整数の最大及び最小に一致します)。 さらに全てのプラットフォームが負のタイムスタンプをサポートしている わけではありませんので、日付の範囲は Unix エポック以前にはならないかも知れません。 これは、例えば Windows やいくつかの Linux ディストリビューション、 いくつかの他のオペレーティングシステムでは 1970 年 1 月 1 日以前の日付では動作しない事を意味しています。 PHP 5.1.0 以降のバージョンでは、この制限はなくなっています。

つまり、負のタイムスタンプはOS依存ということみたいです。

Ethnaでも

Ethnaでも、Ethna_ActionFormで日付の形式チェックに使用している箇所がありました。
http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi/ethna/tags/ETHNA_2_3_5/class/Ethna_ActionForm.php?rev=528&root=ethna&view=markup

_validateメソッドのところ

<?php //色づけ
} else if ($type == VAR_TYPE_DATETIME) {
    $r = strtotime($var);
    if ($r == -1 || $r === false) {
        if ($test == false) {
            $this->handleError($name, E_FORM_WRONGTYPE_DATETIME);
        }
        return false;
    }
} else if ($type == VAR_TYPE_BOOLEAN) {

で、結局

strtotimeの戻り値で、日付の判断をするのが間違いなのでしょうか?
ローカルの開発環境で 64ビットマシンとか用意していないので、本番反映後に発覚するバグとして苦しめられたら嫌だなぁ。。。