Perl で日付 X から日付 Y まで何営業日あるかの計算

Posted by
ぴろり
Posted at
2016/08/04 12:21
Trackbacks
関連記事 (0)
Post Comment
コメントできます
Category
開発メモ カテゴリ
カバーイメージ

 Perl において、週末や祝祭日、振替休日を考慮して n 営業日前後の日付を求めることができましたが、続いて、日付 X から日付 Y までの営業日を数えるための覚書きです。

この記事を Delicious に追加する   このエントリーをはてなブックマークに追加  

#!/usr/bin/perl
use v5.10;
use Calendar;
use Calendar::Japanese::Holiday;

### 任意指定の休日 MM/DD/YYYY
my %special_holiday = map{ $_ => 1 } qw{
    12/29/2015
    12/30/2015
    12/31/2015
    01/04/2016
};

### $_[0] から $_[1] まで何営業日あるか
sub business_days {
    my $dt1 = shift || die;
    my $dt2 = shift || die;

    # 月末/年末をまたぐ計算が面倒なので Calendar モジュールを使う
    my( $y, $m, $d ) = $dt1 =~ /^(\d+)\D+(\d+)\D+(\d+)/;
    my $c = Calendar->new_from_Gregorian( $m, $d, $y );
    # 日付比較が便利なので Calendar モジュールを使う
    my( $y2, $m2, $d2 ) = $dt2 =~ /^(\d+)\D+(\d+)\D+(\d+)/;
    my $c2 = Calendar->new_from_Gregorian( $m2, $d2, $y2 );

    my $days = 0;
    while( my $offset_dir = $c2 <=> $c ){
        $c += $offset_dir;
        # 土日はカウントしない
        next if $c->weekday == 0; # 日曜
        next if $c->weekday == 6; # 土曜
        # 日本の祝祭日はカウントしない(振替休日も考慮する)
        next if isHoliday( $c->year, $c->month, $c->day, 1 );
        # 特別休日はカウントしない
        next if $special_holiday{$c};
        $days += $offset_dir;
    }
    $days;
}

# 年末年始で動作確認
say business_days( '2015-12-31', '2016-01-07' ); # +3
say business_days( '2016/01/04', '2015-12-24' ); # -3
# 成人の日前後(振替休日あり)で動作確認
say business_days( '2016-01-08', '2016-01-14' ); # +3
say business_days( '2016-01-13', '2016-01-07' ); # -3

メモ

  • 基本ロジックは dt2offset と同じです。
  • 土日は単純に曜日で判定します
  • 日本の祝祭日の判定には、Calendar::Japanese::Holiday モジュールを使用します
  • 創立記念日など任意の休日を配列(special_holiday)に設定しておきます
  • 基準日や目的の日付が営業日でない場合、その分だけ日数が減ります
20~24 行目
日付の増減に際して、月末・年末・うるう年の面倒を避けるため、Calendar オブジェクトにしておきます。
27~28 行目
Calendar オブジェクトの <=> 演算子で、基準の日付(c)と目的の日付(c2)の前後関係を求めます。例えば、c2c より後日の場合、offset_dir1 になります。coffset_dir 方向に動かしていき、cc2 が等しくなった時、ループを抜けます。
33 行目
Calendar::Japanese::Holiday::isHoliday で振替も考慮した祝祭日の判定。isHoliday 関数は、その日が祝祭日だった場合、その名前を返します。振替休日だった場合、振替と返します。
35 行目
Calendar のインスタンスをスカラ コンテクストで評価すると、MM/DD/YYYY 形式で日付を返すので、%special_holiday に特別休日の指定がないか調べています。
36 行目
これらの条件に当てはまらない場合にのみ、営業日数のカウントを進めます。
この記事を Delicious に追加する   このエントリーをはてなブックマークに追加  


この記事を読んだ人はこんな記事も読んでいます記事リコメンデーションについて

カバー画像:Perl で n 営業日前後の計算

関連記事/トラックバック

関連記事/トラックバックはまだありません

この記事にトラックバックを送るには?

コメントを投稿する

 
 (必須, 匿名可, 公開, トリップが使えます)
 (必須, 匿名可, 非公開, Gravatar に対応しています)
 (必須)
スパム コメント防止のため「投稿確認」欄に ランダムな数字 CAPTCHAについて を入力してから送信してください。お手数ですがご協力のほど宜しくお願いいたします。