Skip to main content

Calendar モジュールが参照する既定のタイムゾーンについて

ここしばらく Calendar モジュールを調べている。
http://drupal.org/project/calendar
そしてハマっている(涙)

Calendar は、ノードの日付フィールドにもとづいて一種の View としてカレンダーを表示するという極めて有用なモジュール。ViewsCCK を組み合わせて、さまざまな用途のカレンダーを作ることができる。

日付フィールドを持つノードタイプを自分で作らなくても、全ノードがデフォルトで持っている更新日時などのフィールドに基づいて各ノードへのリンクをカレンダー表示できるというので、実際にやってみてわかったことをメモ。

まず、ノードの更新日付をフィールドとして認識するカレンダーのビューを作る。具体的には、/admin/build/views の "Administer views" ページで calendar の行の [Add] をクリックして、オーバーライド版の calendar ビューを作成。"Fields" の一覧に "Node: Updated Time" のエントリを追加、Label は適当に指定する。作成したビューを保存した後、/calendar にアクセスすると見事なカレンダーが表示される。各ノードを表すボックスが、対応する日付の位置に配置されている。
すばらしい。

ところが、よくよく見ると、日付の表示がおかしい。
カレンダーの中に表示される更新時刻の値がちょうど 9 時間さかのぼった値になっている。
サイトのタイムゾーンが GMT のままだったかと思い、/admin/settings/date-time で設定を確認するが、ちゃんと +0900 になっている。さらに、今日の日付を表す赤い背景の位置が、昨日の位置にずれて表示されている。OS の設定で日付と時刻をいろいろ変えて再表示してみると、どうやら、この日付の切り替わりもちょうど 9 時間ずれているらしい。サイトのタイムゾーンを変えたり、アカウント固有のタイムゾーンを変えたり、有効にしたり、無効にしたり、いろいろやっても結果は同じ。

このカレンダーの時刻表示は GMT で固定なのか???

ソースを調べてみると、カレンダーに表示するノードのデータは、calendar.module の 126 行目あたりから始まる calendar_get_nodes() という関数で用意しているようだ。さらに進んでいくと、227 行目あたりにこんなコードを発見。

$timezone = variable_get('date_default_timezone_name', 'UTC');
$node->start_offset = date_offset(date_unix2array($node->calendar_start), $timezone);
$node->end_offset   = date_offset(date_unix2array($node->calendar_end), $timezone);

もしかして、デフォルトのタイムゾーンを取り損ねて、$timezone が UTC になっているのか?
デバッガで variable_get にもぐってみる。

function variable_get($name, $default) {
  global $conf;
 
  return isset($conf[$name]) ? $conf[$name] : $default;
}

連想配列 $conf の中身を調べるも date_default_timezone_name なんてキーの要素は見つからない。date_default_timezone ならあるけど。
variable_get とペアをなす設定用の variable_set 関数の実装を見ると、値は variable テーブルに書き込まれるらしい。ふむ、mysql で variable テーブルの name 列を select してみると、なるほど date_default_timezone はあるが date_default_timezone_name はない。

じゃあ、date_default_timezone_name を variable_set するはずの場所っていうのはどこなんだ?
全ソースを date_default_timezone_name で検索してみると、Date モジュールの date.inc にある date_set_site_timezone という関数で行っていることがわかる。さらに、この関数を呼び出しているのは、date_field_settings という関数のみ。コメントを見ると、この関数は hook_field_settings() フックの実装らしい。ということは、CCK で Date 型のフィールドの設定をしないと、このタイムゾーンの既定値は設定されないんじゃないのか?

試しに、Page コンテンツタイプに CCK で Date 型のフィールドを追加してみる。
フィールドの設定ページで Data settings のところに Time zone handling というオプションを発見。
さらに、こんなところに Site timezone などというオプションが?
とりあえず保存して、再度 mysql で variable テーブルを select してみると、案の定 date_default_timezone_name の行が追加されている。
Calendar モジュールが使用するデフォルトのタイムゾーンってのは、/admin/settings/date-time で設定する値のことでも、php.ini の date.timezone の値でもなく、Date フィールドモジュールの管理画面で設定する "Site timezone" の値のことなんだぁ・・・

ここを Asia/Tokyo に設定してから、カレンダーを表示してみると、、、
おおお、正しい日本の時刻で表示されている!
今日を表す赤い表示部分も、ちゃんと午前零時に切り替わるようになった。
ただし、今日を表す赤い表示部分の問題については、本家の下記ポストの修正を適用することで解決した。
http://drupal.org/node/99223#comment-631328

試しに、上で追加した Date フィールドを Page コンテンツタイプから削除しても、variable テーブルの date_default_timezone_name の行はそのまま残っている。複数のコンテンツタイプに別々の Date フィールドを追加して、一方で Site timezone の設定を変更すると、その設定が別の Date フィールドにも反映されるのか。うーむ。

CCK でどこかに日付のフィールドを設定していれば、顕在化しない問題なのかもしれない。
本家で質問してみようかとも思ったが、もう少し調べてからにしよう。

pending bug reports
http://drupal.org/project/issues/calendar?categories=bug

こんにちは。ryo@drupal.

こんにちは。ryo@drupal.org です。
「Drupal 日本語プロジェクト」のほうでいただいたコメントにレスしたのですが、本家記事へのリンクを張ったためかどうもスパムの嫌疑がかかっているらしく、
モデレーション中になってますのでこちらのサイトに書かせていただきます。
こちらのサイトについては何度か読ませていただいた記憶があるのですが、ついさっき、
http://www.drupal-module.info/
で話がつながりました。

ところで
Time zone handling:
Site's time zone
Site timezone:
Asia/Tokyo

をやってみたのですが、やはり日付が正しく表示されません。何故なんでしょうね。。。

コメントありがとうございます

コメントが承認待ちになってしまい、失礼しました。

うーん、ダメでしたか、、、役に立たないコメントですみません。

私の環境では、次のように、データベースの variable テーブルに
name 列の値が 'date_default_timezone_name' の行があれば
うまくオフセットが設定される動きになっていました。

mysql> select * from variable where name='date_default_timezone_name';
+----------------------------+--------------------+
| name                       | value              |
+----------------------------+--------------------+
| date_default_timezone_name | s:10:"Asia/Tokyo"; |
+----------------------------+--------------------+

なお、テスト環境ですが、
Windows、xampplite (Apache 2.2.4、MySQL 5.0.45、PHP 5.2.3)、
Drupal 5.3、Views 5.x-1.6、Calendar 5.x-1.7、Date 5.x-1.7 でした。

役に立たないなんて

役に立たないなんて、そんなこと言わんでください。レスありがとうございます。
私は技術面は全く素人なので原理的なことは全くわからないのですが、ともかく初めからdate フィールドをあのように設定しているのですが、ダメなんです。
phpMyAdmin を見てみましたが、date_default_timezone_name というのはなく、date_default_timezone までだったような気がします。
もしよろしければメールでコンタクト下さいませ。

すみません、たびた

すみません、たびたび。
date_default_timezone_name というのはなく、date_default_timezone までだったような気がします。
はウソかもしれません、よくわかりません。

赤色表示の件を訂正します

まっさらの環境を作り直して確認してみたところ、
赤色表示の問題は、date_default_timezone_name の話とは別件で、
本家にポストされた修正コードで解決したものでした。
http://drupal.org/node/99223#comment-631328

試行錯誤の中で混乱して勘違いしておりました。
申し訳ありません。

記事の該当箇所を修正しました。

バッチリです

上記の修正コードでバッチリ解決しました。

よかったです!

よかったです!