日向夏特殊応援部隊

俺様向けメモ

Time::Piece::MySQL とタイムゾーン (訂正あり)


重要

id:holidays-l さんがこの記事の誤りと、ちゃんとした解説を書いてくれているので、そっちを参照して下さいませ。

以下、そのつもりで読んで下さい。

MySQL から UNIX_TIMESTAMP() と NOW() の値をこんな感じで出します。

[12:13:13 root@bopobo/test :4] SELECT UNIX_TIMESTAMP(), NOW();
+------------------+---------------------+
| UNIX_TIMESTAMP() | NOW()               |
+------------------+---------------------+
|       1288926767 | 2010-11-05 12:12:47 |
+------------------+---------------------+
1 row in set (0.00 sec)

最近 Time::Piece を使っているので、MySQL の datetime 型を扱う際には Time::Piece::MySQL を使ってこんな感じにします。

$ perl -MTime::Piece -MTime::Piece::MySQL -e 'my $t = Time::Piece->from_mysql_datetime("2010-11-05 12:12:47"); warn $t;'
Fri Nov  5 12:12:47 2010 at -e line 1.

これは正しいんですけど、

$ perl -MTime::Piece -MTime::Piece::MySQL -e 'my $t = Time::Piece->from_mysql_datetime("2010-11-05 12:12:47"); warn $t->epoch;'
1288959167 at -e line 1.

は元の timestamp と異なる値 (gmtime) になっちゃうと。これは $ENV{TZ} を変更しても全然変わらない。

$ perl -MTime::Piece -MTime::Piece::MySQL -e 'my $t = Time::Piece->from_mysql_datetime("2010-11-05 12:12:47"); warn $t->epoch - 9 * 60 * 60;'
1288926767 at -e line 1.

なら正しいけどかっこわるい。

$ perl -MTime::Piece -MTime::Piece::MySQL -e 'my $t = Time::Piece->from_mysql_datetime("2010-11-05 12:12:47"); warn $t->strftime("%s")'
1288926767 at -e line 1.

これなら正しいみたい。詳しくは man strftime すれば分かります。

余談ですが DateTime::Format::MySQL だと、

$ perl -MDateTime::Format::MySQL -e 'my $dt = DateTime::Format::MySQL->parse_datetime("2010-11-05 12:12:47"); warn $dt->set_time_zone("Asia/Tokyo")->epoch'
1288926767 at -e line 1.

とかで書けます。