gmmktime()の挙動の違い2008年03月01日 00時43分08秒

ここしばらくgelatoがマイブームなのでこにょこにょといじっていたりするのだが、JSAスクリプトからPOSTした場合とadminページからPOSTした場合で時差がでることに気がついた。

自宅やら会社の実験サーバやら開発用PCやら何箇所かgelatoを入れているのだが、このうちあるホストだけ時差が発生する。 調べてみると時差の源は、gelatoが新規エントリを追加する際のタイムスタンプを「gmmktime」で生成している部分らしかった。

このあたりはまたgelatoネタとして別エントリにする予定なのだが、なんで違いが出たり出なかったりするんだろうかといろいろ試したところ、PHP4とPHP5で挙動が違う場合があることが判明した。(ひょっとして有名なネタかしら?)

問題のgelatoのコードでは

gmmktime()
と、パラメータなしで使用している。ここがミソ。

こんな検証コードを書いてみた。

<?php
    $current_time = mktime();
    $d = array();
    foreach( split(',', 'H,i,s,m,d,Y') as $key ) {
        $d[ $key ] = date( $key, $current_time );
    }
    foreach( array(
        array(
            'name' => 'mktime()',
            'value' => $current_time
        ),
        array(
            'name' => 'gmmktime()',
            'value' => gmmktime()
        ),
        array(
            'name' => 'gmmktime(mktime())',
            'value' => gmmktime(
                $d['H'], $d['i'], $d['s'], $d['m'], $d['d'], $d['Y']
            )
        )
    ) as $conf ) {
        $date = date('Y-m-d H:i:s', $conf['value']);
        echo "{$conf['name']} --> $date\n";
    }
?>
mktime()で基準のタイムスタンプを取得し、
  • パラメータなしのgmmktime()
  • 基準タイムスタンプを元にしたgmmktime()
を出力しているだけだ。

これをPHP5で実行するとこんな感じ。

-sh-2.05b$ php test.php
mktime() --> 2008-03-01 00:22:57
gmmktime() --> 2008-03-01 00:22:57
gmmktime(mktime()) --> 2008-03-01 09:22:57
同じコードをPHP4で実行するとこんな感じ。
-sh-2.05b$ php4 test.php
mktime() --> 2008-03-01 00:23:01
gmmktime() --> 2008-03-01 09:23:01
gmmktime(mktime()) --> 2008-03-01 09:23:01

これを見ると、パラメータなしでgmmktimeを実行すると、PHP4では現在のローカル時刻が与えられたものとして動作し、PHP5ではmktime()と同じ動作をすることがわかった。

これ、マニュアルには特に何も書いてないので、もうちょっと細かいバージョンの違いがでるのかもしれない。

mktime()はパラメータなしの場合に「現在時刻を与えられたもの」として振舞っているので、どっちかっていうとPHP4の挙動のほうが正しい感じはするんだけどね。

しかし、普段はZend_Dateばっかり使っているのであんまり役に立たない発見な気が。