ニュースモジュールの日付がずれる

わけあってタイトルの現象を追ってみた。(間抜けなオチつき)
環境

  • xoops2.0.16a
  • CentOS4.4final
  • php 5.1.6
  • Apache2.0.59

xoopsの一般設定でサーバのタイムゾーンを設定できるのだが、
これをAsia/Tokyo(GMT+9h)に設定するとニュースモジュールでの投稿時刻がずれる。
なぜかタイムゾーンGMTに設定すると正しい日本標準時間が取れる。

問題が露呈するのは管理者メニューNewsモジュールの管理者画面の投稿画面
ここで投稿する時に現在時刻が表示されている。だがこれがズレているのだ。
まずはこの画面を表示しているphpからスタート
これはURLから容易にうかがい知ることができる。

  • [xoops_root]/modules/news/admin/index.php

になる。

中をのぞいてみると$opという変数に格納される値によってswitch分で処理が分岐している。
新規ニュースを投稿するときは$op = "newarticle"になるので、
読むべき場所はindex.phpの428行目〜445行目となる。
そこの中に

include "storyform.inc.php";

という記述がある。
なので次に見るべきは同じディレクトリにあるstoryform.inc.phpになる。
で、次にstoryform.inc.phpをのぞいてみる。
すると114行目〜127行目の記述がそれっぽい。
どうも120行目と125行目の以下の記述が当たりのようだ。

printf(_AM_CURRENTTIME,formatTimestamp($time));

$timeは114行目を見ればわかるが

$time = time();

なのでphpのtime関数であることがわかる。

まずここでこのtime関数が何を返すか気になったので簡単なphpを書いて調べてみた。
するとtime()関数は日本標準時を取得してきた。

phpinfo()を見るとデフォルトのタイムゾーン設定がAsia/Tokyoになっているのでこれは問題ないだろう。

すると当然formatTimestamp($time)が怪しい。
なのでこの関数の定義を探す。

すると[xoops_root]/include/functions.phpにあることを発見
この189行目〜218行目までがそれの模様。
この関数は1〜3個の引数があるが今回は最初の1つしか渡されていない。
つまり残りは定義されたデフォルト値に従うわけだ。

この関数は主にswitch文による分岐処理が大半を占めるが、それはどのフォーマットで表示するかなので関係はない。
つまり192行目の以下の文が当たりだ

$usertimestamp = xoops_getUserTimestamp($time, $timeoffset);

で、$timeは第一引数なのでphpのtime()関数で取った値となる。
$timeoffsetは第三引数なのだが、今回は指定がないのでデフォルト値""が入る。

で、このxoops_getUserTimestamp関数はどこにあるかというと直上に定義されていた。
同ファイル内の170行目〜182行目がそれだ。

ここで各ユーザのタイムゾーンの設定を読み込み、

・・・まてよ。ひょっとして管理者のタイムゾーン設定がGMTになってたらどうなる?

180行目に以下のように書いてある。

$usertimestamp = intval($time) + (intval($timeoffset) - $xoopsConfig['server_TZ'])*3600;

問題はこの$timeoffsetの値だ。
これは173行目からの

    if ($timeoffset == '') {
        if ($xoopsUser) {
            $timeoffset = $xoopsUser->getVar("timezone_offset");
        } else {
            $timeoffset = $xoopsConfig['default_TZ'];
        }
    }

と記述されている。
つまり、ユーザのタイムゾーン設定がGMTなら0になる。。。
それを踏まえて180行目の引き算をすると。。。

(現在時刻)+((GMT)-(Asia/Tokyo(+9)))= (現在時刻)- 9

ということで原因判明。。。
結局設定ミスというオチ orz...