日付を指定すると、土日、祝祭日(国民の祝日)かどうかをチェックするサブルーチンです。
このサブルーチンは、土日と、日本における「国民の祝日」とが対象です。海外の祝祭日や、あなたの会社の設立記念日など、あなたが休みだとしても、それは対象となりませんので注意してください。
祝祭日(国民の祝日)は「国民の祝日に関する法律」で定められており、内閣府のホームページ http://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html で公開されています。このサブルーチンは、国民の祝日に関する法律 平成17年5月20法律第43号(平成19年1月1日施行)に対応しています。
CheckHoliday()
休日かどうかをチェックしたい日付を西暦、月、日に分けて指定します。
指定日が土日もしくは祝祭日であれば「1」が、そうでなければ「0」が返ります。また不適切な引数を与えると、-1 が返ります。
まず、このサブルーチンを使うスクリプトのはじめのほうに、
use Time::Local;
use Date::Pcalc;
を記述してください。お使いのサーバに、Perl モジュール Time::Local がインストールされていないと、このサブルーチンはご利用いただけませんので、ご注意さい。Perl モジュール Time::Local は、Perl5 の標準モジュールですので、ほとんどのサーバでご利用いただけるはずです。Perl モジュール Date::Pcalc は標準モジュールではありませんので、事前にインストールが必要です。
では、たとえば という日付を評価する場合には、
my $year = 2010;
my $month = 10;
my $day = 11;
my $holiday = &CheckHoliday($year, $month, $day);
とします。
は春分の日で祝日なので、$holiday には 1 が与えられます。もし、平日を指定すると、$horiday には 0 が与えられます。使い方としては、以下のように if 文や unless 文の評価式で使うのがよいでしょう。
if(&CheckHoliday($year, $month, $day)) {
#休日の場合の処理
} else {
#平日の場合の処理
}
sub CheckHoliday {
my($year, $mon, $day) = @_;
#指定日が存在する日かをチェックする
my $time;
eval {$time = timelocal(0, 0, 0, $day, $mon-1, $year);};
if($@) {return -1;}
#当日を特定する。
my @list = localtime($time);
my $today = sprintf("%02d", $mon).sprintf("%02d", $day);
my $youbi = $list[6];
my $order = int(($day-1) / 7) + 1;
#当日が日曜日かどうかをチェック
#日曜日であれば、無条件で1を返す。
if($youbi == 0) {return 1;}
#1970年より前であれば終了
if($year < 1970) { return 0; }
#「国民の祝日に関する法律」が施工された1948年7月20日より前であれば終了
#if( $year < 1948 || ( $year == 1948 && $today lt "0720") ) { return 0; }
#----------------------------------------------------------------
#国民の祝日(国民の祝日に関する法律 第二条)
#----------------------------------------------------------------
#日付が決まっている祝日を定義
my @fix_horidays = (
'0101', #元日
'0429', #1988年以前は「天皇誕生日」、1989年~2006年までは「みどりの日」、2007年~は「昭和の日」と改名
'0503', #憲法記念日
'0505', #こどもの日
'1103', #文化の日
'1123' #勤労感謝の日
);
#成人の日 - ~ 1999年は1月15日、2000年以降はハッピーマンデー適用のため1月の第2月曜日
if($year <= 1999) {
push(@fix_horidays, '0115');
} elsif($year >= 2000) {
my($y, $m, $d) = Date::Pcalc::Nth_Weekday_of_Month_Year($year, 1, 1, 2);
$m = sprintf("%02d", $m);
$d = sprintf("%02d", $d);
push(@fix_horidays, "${m}${d}");
}
#建国記念日 - 1967年(昭和42年)~
if($year >= 1967) {
push(@fix_horidays, '0211');
}
#昭和天皇の大喪の礼 2月24日 - 1989年(平成元年)のみ
if($year == 1989) {
push(@fix_horidays, '0224');
}
#皇太子明仁親王の結婚の儀 4月10日 - 1959年(昭和34年)のみ
if($year == 1959) {
push(@fix_horidays, '0410');
}
#みどりの日 - 2007年~
if($year >= 2007) {
push(@fix_horidays, '0504');
}
#皇太子徳仁親王の結婚の儀 6月9日 - 1993年(平成5年)のみ
if($year == 1993) {
push(@fix_horidays, '0609');
}
#海の日 - 1996年~2002年は7月20日、2003年以降はハッピーマンデー適用のため7月の第3月曜日
if($year >= 1996 && $year <= 2002) {
push(@fix_horidays, '0720');
} elsif($year >= 2003) {
my($y, $m, $d) = Date::Pcalc::Nth_Weekday_of_Month_Year($year, 7, 1, 3);
$m = sprintf("%02d", $m);
$d = sprintf("%02d", $d);
push(@fix_horidays, "${m}${d}");
}
#敬老の日 - 1966年(昭和42年)~ 2002年は9月15日、2003年以降はハッピーマンデー適用のため9月の第3月曜日
if($year >= 1966 && $year <= 2002) {
push(@fix_horidays, '0915');
} elsif($year >= 2003) {
my($y, $m, $d) = Date::Pcalc::Nth_Weekday_of_Month_Year($year, 9, 1, 3);
$m = sprintf("%02d", $m);
$d = sprintf("%02d", $d);
push(@fix_horidays, "${m}${d}");
}
#体育の日 - 1966年(昭和42年)~ 1999年は10月10日、2000年以降はハッピーマンデー適用のため10月の第2月曜日
if($year >= 1966 && $year <= 1999) {
push(@fix_horidays, '1010');
} elsif($year >= 2000) {
my($y, $m, $d) = Date::Pcalc::Nth_Weekday_of_Month_Year($year, 10, 1, 2);
$m = sprintf("%02d", $m);
$d = sprintf("%02d", $d);
push(@fix_horidays, "${m}${d}");
}
#即位礼正殿の儀 11月12日 - 1990年(平成2年)のみ
if($year == 1990) {
push(@fix_horidays, '1112');
}
#今上天皇誕生日(平成) - 1989年~
if($year >= 1989) {
push(@fix_horidays, '1223');
}
#春分の日と秋分の日を挿入する。
if($year % 4 == 0) {
#春分の日
if($year <= 1956) {
push(@fix_horidays, '0321');
} elsif($year <= 2088) {
push(@fix_horidays, '0320');
} else {
push(@fix_horidays, '0319');
}
#秋分の日
if($year <= 2008) {
push(@fix_horidays, '0923');
} else {
push(@fix_horidays, '0922');
}
} elsif($year % 4 == 1) {
#春分の日
if($year <= 1989) {
push(@fix_horidays, '0321');
} else {
push(@fix_horidays, '0320');
}
#秋分の日
if($year <= 1917) {
push(@fix_horidays, '0924');
} elsif($year <= 2041) {
push(@fix_horidays, '0923');
} else {
push(@fix_horidays, '0922');
}
} elsif($year % 4 == 2) {
#春分の日
if($year <= 2022) {
push(@fix_horidays, '0321');
} else {
push(@fix_horidays, '0320');
}
#秋分の日
if($year <= 1946) {
push(@fix_horidays, '0924');
} elsif($year <= 2074) {
push(@fix_horidays, '0923');
} else {
push(@fix_horidays, '0922');
}
} elsif($year % 4 == 3) {
#春分の日
if($year <= 1923) {
push(@fix_horidays, '0322');
} elsif($year <= 2055) {
push(@fix_horidays, '0321');
} else {
push(@fix_horidays, '0320');
}
#秋分の日
if($year <= 1979) {
push(@fix_horidays, '0924');
} else {
push(@fix_horidays, '0923');
}
}
#当日が「国民の祝日」であれば、1を返す。
if(grep(/^$today$/, @fix_horidays)) {return 1;}
#----------------------------------------------------------------
#振替休日(国民の祝日に関する法律 第三条2)
#1973年に、祝日が日曜日の場合はその翌日を休日とする振替休日を制定。
#初適用日は同年4月30日
#2007年に規定が変更され、「国民の祝日」が日曜日に当たるときは、
#その日後においてその日に最も近い「国民の祝日」でない日を休日とす
#ることとなった。
#----------------------------------------------------------------
if($year >= 1973 && $year <= 2006) {
my($s, $m, $h, $D, $M, $Y, $w) = localtime($time-86400);
my $yesterday = sprintf("%02d", $M+1).sprintf("%02d", $D);
#前日が「国民の祝日」で、かつ日曜日の場合には、当日は休日
if( grep(/^${yesterday}$/, @fix_horidays) && $w == 0 ) {return 1;}
} elsif($year >= 2007) {
for(my $i=1; $i<=7; $i++) {
my($s, $m, $h, $D, $M, $Y, $w) = localtime( $time - $i*86400 );
my $md = sprintf("%02d", $M+1).sprintf("%02d", $D);
my $hflag = grep(/^${md}$/, @fix_horidays);
if($hflag) {
if($w == 0) {
return 1;
}
} else {
last;
}
}
}
#----------------------------------------------------------------
#国民の休日(国民の祝日に関する法律 第三条3)
#1985年に、二つの祝日に挟まれた平日を休日とする国民の休日を制定。
#初適用日は1988年5月4日
#----------------------------------------------------------------
if($year >= 1988) {
#前日を特定する
my @ysd = localtime($time-86400);
my $yesterday = sprintf("%02d", $ysd[4]+1).sprintf("%02d", $ysd[3]);
#翌日を特定する
my @tmr = localtime($time+86400);
my $tomorrow = sprintf("%02d", $tmr[4]+1).sprintf("%02d", $tmr[3]);
#昨日と明日がともに「国民の祝日」の場合には、当日は休日。
if( grep(/^$yesterday$/, @fix_horidays) && grep(/^$tomorrow$/, @fix_horidays) ) {return 1;}
}
#以上のチェックにひっかからなかったら、休日でない。
return 0;
}