ルモーリン

Perlサンプル13 日付と時刻処理

投稿:2019-12-31

実行時の日時をベースに処理したり、入手した文字列を日時のベースにしたり、日付と時刻を使った処理のサンプルです。

Windowsでは「time_zone => "local"」を「time_zone => "Asia/Tokyo"」に自動変換できず、実行時にエラーで終了する場合があります。 ローカル時刻の取得にはプラグイン的なモジュールのインストールが必要です。 インストールできない環境でしたら"local"を"Asia/Tokyo"に書き替えるのも手です。 ここで言う「プラグイン的」というのは、プログラム実行時にモジュール未定義であっても未解決にならず、実行を開始してしまい、 ローカル時刻を取得する処理中に未定義が判明して実行を停止するタイプのものです。
DateTime::TimeZone::Local::Win32 - Determine the local system's time zone on Windows - metacpan.org
インストール済のチェックはこんな感じで実行してみてください。 メッセージなしで終了すればインストール済です。

perl -MDateTime::TimeZone::Local::Win32 -e ""


未インストールの場合の表示です。
Can't locate DateTime/TimeZone/Local/Win32.pm in @INC (you may need to install the DateTime::TimeZone::Local::Win32 module) (@INC contains: C:/Perl64/site/lib C:/Perl64/lib).
BEGIN failed--compilation aborted.

DateTimeを使います。
DateTime - A date and time object for Perl - metacpan.org

#!/usr/bin/env perl

use v5.26;
use utf8;
use warnings;
use strict;

use feature "say";
use open IO => ":utf8";

use DateTime;
use DateTime::Format::Strptime;
use DateTime::Format::ISO8601;
use Encode::Argv;
use Encode::Locale;

binmode STDOUT, ":encoding(console_out)";
binmode STDERR, ":encoding(console_out)";

$| = 1;

{
	my $dist = 15;
	my $now_dt = DateTime->now(time_zone => "local");
	my $after_dt = $now_dt->clone->add(days => $dist);
	my $before_dt = $now_dt->clone->subtract(days => $dist);
	my $adjust_dt = $now_dt->clone->subtract(days => 1)->add(minutes => 13)->truncate(to => "hour");
	say $now_dt->strftime("今は%F %Tです。");
	say $after_dt->strftime("${dist}日後は%F %Tです。");
	say $before_dt->strftime("${dist}日前は%F %Tです。");
	say $adjust_dt->strftime("日時調整後は%F %Tです。");
}

{
	my $sp = DateTime::Format::Strptime->new(
		pattern => "%F",
		time_zone => "local",
	);
	my $gantan_str = "2020-01-01";
	my $gantan_dt = $sp->parse_datetime($gantan_str);
	say $gantan_dt->strftime("元旦は%F %Tです。");
}

{
	my $iso_str = "2019-12-31T12:34:56+09:00";
	my $iso_dt = DateTime::Format::ISO8601->parse_datetime($iso_str);
	say $iso_dt->strftime("ISOの日時は%F %Tです。");
	my $tz = "UTC";
	say "タイムゾーンを${tz}に切替";
	$iso_dt->set_time_zone($tz);
	say $iso_dt->strftime("変更後の日時は%F %Tです。");
}
今は2019-12-31 16:37:03です。
15日後は2020-01-15 16:37:03です。
15日前は2019-12-16 16:37:03です。
日時調整後は2019-12-30 16:00:00です。
元旦は2020-01-01 00:00:00です。
ISOの日時は2019-12-31 12:34:56です。
タイムゾーンをUTCに切替
変更後の日時は2019-12-31 03:34:56です。

まあ、ソースを見たまんまです(笑)。 なお、Perlのクラスでは珍しい動作をしますので、時刻の計算を行うメソッドに注目してください。 計算結果のオブジェクトを返しますが、これは元のオブジェクトが持つ時刻を変更して、元のオブジェクトを返しています。 変更後のオブジェクトは生成されません。 別のオブジェクトとして受け取る際は、まずcloneを呼び出して同じ時刻の別オブジェクトを生成してから変更しています。