Perlで日時のタイムゾーンを変更する

前回はPHPでの日時情報のタイムゾーン操作を取り上げましたが、今度はPerlで同じことをしてみます。

Perlでの日時操作は5.10からコアに組み込まれたTime::Pieceを利用するケースが一般的ですが、タイムゾーン操作を伴う場合はDateTimeとDateTime::TimeZoneを利用します。

use strict;
use warnings;
use utf8;
use DateTime;
use DateTime::TimeZone;

my $tz = DateTime::TimeZone->new('name' => 'local');
my $dt = DateTime->now('time_zone' => $tz);

print $dt->datetime, "\n"; # YYYY-MM-DD HH:mm:ssで表示
print $dt->strftime('%G-%m-%dT%T%z'), "\n"; # タイムゾーンを表示に含める場合

# UTCへ変換
$dt->set_time_zone('UTC');
print $dt->datetime, "\n";

# ロンドンのタイムゾーンへ変換
$dt->set_time_zone('Europe/London');
print $dt->datetime, "\n";

# N.Y.のタイムゾーンへ変換
$dt->set_time_zone('America/New_York');
print $dt->datetime, "\n";
1;

もちろんサマータイムは考慮してくれます。

前のサンプルのように前もってDateTime::TimeZoneオブジェクトを作成して、DateTimeのコンストラクトの際に引数としてDateTime::TimeZoneオブジェクトを渡してやる方が処理が早いのですが、単純に任意のタイムゾーンの現在時刻を表示させるなら

print DateTime->now('time_zone' => 'Europe/Paris')->datetime;

という書き方もできます。


PerlのDateTimeの場合も当然のように、現在日時でなくてもオブジェクトが作成できます。DateTimeでオブジェクトを作成する場合、

use strict;
use warnings;
use utf8;
use DateTime;

$dt = DateTime->new(
    time_zone => 'Asia/Tokyo',
    year      => 2011,
    month     => 9,
    day       => 15,
    hour      => 9,
    minute    => 0,
    second    => 0
);

print $dt->datetime, "\n";
1;

としますが、インターネット上でよく使われる日時記述からDateTimeオブジェクトを作成する場合はDateTime::Format::HTTPを利用して、

use strict;
use warnings;
use utf8;
use DateTime::Format::HTTP;

my $dt = DateTime::Format::HTTP->parse_datetime('2011-09-15T09:00:00Z');
print $dt->set_time_zone('Asia/Tokyo')->datetime, "\n";
1;

と書くと、いちいち日付情報を分割せずに済むので便利です。

特定の用途のために任意の書式で出力したい場合、strftimeメソッドでちまちま指定すれば目的が適いますが、よく使いそうな書式はCPANで公開されてることがよくあります。

例えばメールヘッダー用。

use strict;
use warnings;
use utf8;
use DateTime::Format::HTTP;
use DateTime::Format::Mail;

my $dt = DateTime->now('time_zone' => 'Asia/Tokyo');
my $mail_format = 'DateTime::Format::Mail';
print $mail_format->format_datetime, "\n";
1;

こんな感じに書けます。

参考ページ