祝日・振替休日を取得するには、メンテナンスも楽なので、 PEAR::Date_Holidays_Japan
にお任せする。
インストールは以下のコマンドで。
sh
1# pear install Date_Holidays_Japan-alpha
Calendar クラス(Calendar.class.php
)の実装は以下のように。
php
1<?php
2
34 * カレンダークラス
5 * Calendar.class.php
6
7final class Calendar
8{
9
10 11 * 日曜日
12
13 const T_SUNDAY = 0;
14
15 16 * 月曜日
17
18 const T_MONDAY = 1;
19
20 21 * 火曜日
22
23 const T_TUESDAY = 2;
24
25 26 * 水曜日
27
28 const T_WEDNESDAY = 3;
29
30 31 * 木曜日
32
33 const T_THURSDAY = 4;
34
35 36 * 金曜日
37
38 const T_FRIDAY = 5;
39
40 41 * 土曜日
42
43 const T_SATURDAY = 6;
44
45 46 * キャッシュに使用する祝日配列
4748
49 static private $_arrHolidays = array();
50
51 52 * 祝日を取得する
535455
56 private static function getHolidays($year)
57 {
58 // 取得済みならキャッシュを使う
59 if (isset(static::$_arrHolidays[$year])) {
60 return static::$_arrHolidays[$year];
61 }
62
63 // 未取得のとき
64 $errorLevel = error_reporting(); // エラー出力レベルを取得
65 error_reporting(E_NOTICE); // PHP Deprecated: Non-static method... を抑止
66
67 require_once 'Date/Holidays.php';
68 $dh = Date_Holidays::factory('Japan', $year, 'ja_JP');
69 $holidays = array();
70 foreach ($dh->getHolidays() as $h) {
71 $holidays[$h->getDate()->format('%Y-%m-%d')] = $h->getTitle();
72 }
73 error_reporting($errorLevel); // エラー出力レベルを戻す
74
75 ksort($holidays);
76
77 static::$_arrHolidays[$year] = $holidays;
78 return static::$_arrHolidays[$year];
79 }
80
81 82 * 祝日かどうかを判定する
838485
86 public static function isHoliday(\DateTime $objDate)
87 {
88 $year = $objDate->format('Y');
89 $holidays = self::getHolidays($year);
90 return array_key_exists($objDate->format('Y-m-d'), $holidays);
91 }
92
93 94 * 定休日かどうかを判定する
959697
98 public static function isRegularHoliday(\DateTime $objDate)
99 {
100 //定休日リスト
101 $arrRegularHoliday = array(
102 self::T_SUNDAY
103 , self::T_SATURDAY
104 );
105 return in_array($objDate->format('w'), $arrRegularHoliday);
106 }
107
108 109 * ○日後の営業日を取得する
110111112113
114 public static function getWeekdayAfter($dateAfter = 1, \DateTime $objDate = null)
115 {
116 $date = (is_null($objDate)) ? new \DateTime() : $objDate;
117 $interval = new \DateInterval("P1D");
118 for ($i = 0; $i < $dateAfter; $i++) {
119 $date->add($interval);
120
121 // 定休日・祝日のときはカウントしないので、$dateAfterをインクリメント
122 if (self::isRegularHoliday($date) || self::isHoliday($date)) {
123 $dateAfter++;
124 }
125 }
126 return $date;
127 }
128
129}
130
利用する時はこんな感じ。
php
1<?php
2
3require 'Calendar.class.php';
4
5// usage
6// 2015-10-10(Friday) -> 2015-10-12(Monday) 体育の日
7$res = Calendar::getWeekdayAfter(1, new \DateTime('2015-10-10'));
8var_dump($res); // 2015-10-13
9
10// 2015-05-01(金)
11// 2015-05-02(土)
12// 2015-05-03(日・憲法記念日)
13// 2015-05-04(みどりの日)
14// 2015-05-05(こどもの日)
15// 2015-05-06(振替休日)
16$res = Calendar::getWeekdayAfter(1, new \DateTime('2015-05-01'));
17var_dump($res); // 2015-05-07
例
スタートの日付
本日10月17日土曜にアクセス
10月19日月曜と処理したい
今のプログラムだと
3営業後は
21日水曜日になってしまいますが、狙っている結果は22日木曜日です。
この条件おかしいのでは???
10/17(土)基準日
10/18(日)
10/19(月)1営業日後 - 引数には1を渡す(または未指定のときは暗黙的に翌営業日として扱う)
10/20(火)2営業日後 - 引数には2を渡す
10/21(水)3営業日後 - 引数には3を渡す
10/22(木)4営業日後 - 引数には4を渡す
このように考えたほうが、利用場面で自然だと思いますが…