Perlテックラボ

経過日数の計算

time関数の利用方法について説明します。
例えば、どのようにしたら20日前の日付を得られるか、特定の日付から今日までの経過日数を算出するのはどのようにすればいいのかを考えていきたいと思っています。

現在の日付を求める

my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= localtime(time);
my $yyyymmddJ = sprintf("%04d年%02d月%02d日", $year + 1900, $mon +1, $mday);
print "$yyyymmddJです";

現在の時刻を日本語で表示させています。

それでは20日後の日付を求めるには、どうのようにしたらよいのでしょうか。

X日前後の日付を求める

time は現在の日時・時刻を1970年1月1日0時0分0からの経過秒で現すのでしたね。

print time, "<br>";
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= localtime(time);
my $yyyymmddJ = sprintf("%04d年%02d月%02d日", $year + 1900, $mon +1, $mday);
print "$yyyymmddJです";

先ほどのスクリプトの前にprint timeを入れてみました。

1005634570
2001年11月13日です

上の行が1970年01月01日0時0分0秒からの経過秒です。
下の行は上の経過秒を元にして得られた日付となります。

20日後の日付を求めるなら
60秒×60分×24時間×20日=1728000秒前を求めることになります。そこで

my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= localtime(time - 1728000);
my $yyyymmddJ = sprintf("%04d年%02d月%02d日", $year + 1900, $mon +1, $mday);
print "$yyyymmddJです";

下のように20日前の日付が得られました。20日後ならtimeに1728000秒をプラスすればいいのです。

2001年10月24日です

経過日数を求める

特定の日付から現在までの経過日数を求めるにはどうしたらいいでしょうか。経過秒から86,400秒(60秒×60分×24時間)で割れば日数を得られます。しかし今回は日付から経過日数を割り出さなければなりません。そんな時に便利な機能があります。timelocalです。これはperlのモジュールにある特殊な関数です。先ずモジュールの使い方から説明をします。

use Time::Local;

use でモジュールを使用することを宣言します。ここではTime::Localがモジュール名です。Time::Localのモジュールを宣言したことによりtimelocal関数を使用することができるようになりました。

use Time::Local;
$year=2001;
$mon =10;
$mday=24;
$hours = 0;
$min   = 0;
$sec   = 0;
$time = timelocal($sec, $min, $hours, $mday, $mon - 1, $year);
print $time, "<br>";

1003849200

先ほど秒数を使って20日前の日付(2001年10月24日)を求めましたが、ここでは2001年10月24日を指定して現在までの経過秒を求めました。それがtimelocal( )、モジュールで使用できる関数です。残念ながら、この値が正しいのか分かりませんので、localtimeを使って検証してみましょう。

use Time::Local;
$year=2000;
$mon =10;
$mday=24;
$hours = 0;
$min   = 0;
$sec   = 0;
$time = timelocal($sec, $min, $hours, $mday, $mon - 1, $year);
print $time, "<br>";
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time);
$yyyymmddJ = sprintf("%04d年%02d月%02d日", $year + 1900, $mon + 1, $mday);
$hhmmssJ = sprintf("%02d時%02d分%02d秒", $hour, $min, $sec);
print "$yyyymmddJで$hhmmssJです";

1003849200
2000年10月24日で00時00分00秒です

正しい経過秒を取得できたようです。経過秒から経過日数を算出できました。

ついでに1970年1月1日0時0分0秒から現在までの経過秒と、2000年10月24日0時0分0秒までの経過秒も表示しておきます。

use strict;
use Time::Local;
# 2011/7/24
my $y	= 2011;
my $m	= 7;
my $d	= 24;
my $time	= timelocal( 0, 0, 0, $d, $m-1, $y );
my $time1	= time;
my $lap		= int( abs(($time1 - $time) / 60 / 60 / 24) );
print "Content-Type:text/html\n\n";
print "$lap";

timelocalで求めた2001年10月24日0時0分0秒までの経過秒を $time に、現在までの経過秒を $time1 に代入しました。

my $lap		= int( abs(($time1 - $time) / 60 / 60 / 24) );

現在までの経過秒($time1)から指定の日付までの経過秒($time1)を引き、それを一日の秒数(60秒×60分×24時間)で割っています。abs で絶対値にし int で整数にしています。

関連記事