休日かどうかをチェックする

日付を指定すると、土日、祝祭日(国民の祝日)かどうかをチェックするサブルーチンです。

このサブルーチンは、土日と、日本における「国民の祝日」とが対象です。海外の祝祭日や、あなたの会社の設立記念日など、あなたが休みだとしても、それは対象となりませんので注意してください。

祝祭日(国民の祝日)は「国民の祝日に関する法律」で定められており、内閣府のホームページ http://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html で公開されています。このサブルーチンは、国民の祝日に関する法律 平成17年5月20法律第43号(平成19年1月1日施行)に対応しています。

サブルーチン名

CheckHoliday()

引数

休日かどうかをチェックしたい日付を西暦、月、日に分けて指定します。

  1. 西暦(1970 ~ 2023)
  2. 月(1 ~ 12)
  3. 日(1 ~ 31)

戻値

指定日が土日もしくは祝祭日であれば「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;
 }