• HOME
  • CODE
  • PHPで祝日判定して処理したい場合の参考コード

2020/07/28 9:15

PHPで祝日判定して処理したい場合の参考コード

「祝日だけ判定して処理をしたい」という時用に何か良い方法がないか調べてみたら、いい記事がありましたのでご紹介です。

PHPのみで書けますのでWordpressを使ってる方にも便利ですね。

ある程度の日付指定は事前に必要になりますが、祝日って毎年けっこう例外も多いので、管理はしやすいんじゃないかなと思います。

 

ちなみに私はこちらを参考にWPのACFプラグインを使って処理しましたが、紹介するのは生のコードそのままです。

備忘録として残しておきます。

 

 

コード

 

【PHP】

<?php

 

$datetime = new HolidayDateTime();

$datetime->holiday();

 

// 祝日の場合:"勤労感謝の日"

// 平日の場合:false

/**

 * 祝日かどうか判定できるDateTime拡張クラス

 * usage: $holidayDateTime->holiday();

 */

class HolidayDateTime extends DateTime

{

    /** 祝日一覧 */

    // 種別:

    //   fixed=日付固定

    //   happy=指定の週の月曜日

    //   spring=春分の日専用

    //   autumn=秋分の日専用

    private static $holidays = [

        // 種別, 月, 日or週, 開始年, 終了年, 祝日名

        ['fixed',   1,  1, 1949, 9999, '元日'],

        ['fixed',   1, 15, 1949, 1999, '成人の日'],

        ['happy',   1,  2, 2000, 9999, '成人の日'],

        ['fixed',   2, 11, 1967, 9999, '建国記念の日'],

        ['fixed',   2, 23, 2020, 9999, '天皇誕生日'],

        ['spring',  3,  0, 1949, 9999, '春分の日'],

        ['fixed',   4, 29, 1949, 1989, '天皇誕生日'],

        ['fixed',   4, 29, 1990, 2006, 'みどりの日'],

        ['fixed',   4, 29, 2007, 9999, '昭和の日'],

        ['fixed',   5,  3, 1949, 9999, '憲法記念日'],

        ['fixed',   5,  4, 1988, 2006, '国民の休日'],

        ['fixed',   5,  4, 2007, 9999, 'みどりの日'],

        ['fixed',   5,  5, 1949, 9999, 'こどもの日'],

        ['happy',   7,  3, 2021, 9999, '海の日'],

        ['fixed',   7, 23, 2020, 2020, '海の日'],

        ['happy',   7,  3, 2003, 2019, '海の日'],

        ['fixed',   7, 20, 1996, 2002, '海の日'],

        ['fixed',   8, 11, 2021, 9999, '山の日'],

        ['fixed',   8, 10, 2020, 2020, '山の日'],

        ['fixed',   8, 11, 2016, 2019, '山の日'],

        ['autumn',  9,  0, 1948, 9999, '秋分の日'],

        ['fixed',   9, 15, 1966, 2002, '敬老の日'],

        ['happy',   9,  3, 2003, 9999, '敬老の日'],

        ['fixed',  10, 10, 1966, 1999, '体育の日'],

        ['happy',  10,  2, 2000, 2019, '体育の日'],

        ['fixed',   7, 24, 2020, 2020, 'スポーツの日'],

        ['happy',  10,  2, 2021, 9999, 'スポーツの日'],

        ['fixed',  11,  3, 1948, 9999, '文化の日'],

        ['fixed',  11, 23, 1948, 9999, '勤労感謝の日'],

        ['fixed',  12, 23, 1989, 2018, '天皇誕生日'],

        //以下、1年だけの祝日

        ['fixed',   4, 10, 1959, 1959, '皇太子明仁親王の結婚の儀'],

        ['fixed',   2, 24, 1989, 1989, '昭和天皇の大喪の礼'],

        ['fixed',  11, 12, 1990, 1990, '即位礼正殿の儀'],

        ['fixed',   6,  9, 1993, 1993, '皇太子徳仁親王の結婚の儀'],

        ['fixed',   5,  1, 2019, 2019, '天皇の即位の日'],

        ['fixed',  10, 22, 2019, 2019, '即位礼正殿の儀'],

    ];

 

   /**

    * 祝日を取得

    */

   public function holiday()

   {

       // 設定された休日チェック

       $result = $this->checkHoliday();

       if ($result !== false) return $result;

 

       // 振替休日チェック

       $result = $this->checkTransferHoliday();

       if ($result !== false) return $result;

 

       // 国民の休日チェック

       $result = $this->checkNationalHoliday();

 

       return $result;

   }

 

    /**

     * 設定された休日のみチェック

     * 国民の休日と振替休日はチェックしない

     */

    public function checkHoliday()

    {

        $result = false;

 

        // 全ての祝日を判定

        foreach(self::$holidays as $holiday) {

            list($method, $month, $day, $start, $end, $name) = $holiday;

            $method .= 'Holiday';

            $result = $this->$method($month, $day, $start, $end, $name);

            if ($result) {

                return $result;

            }

        }

        return $result;

    }

 

    /**

     * 振替休日チェック

     */

    public function checkTransferHoliday()

    {

        // 施行日チェック

        $d = new DateTime('1973-04-12');

        if ($this < $d) return false;

 

        // 当日が祝日の場合はfalse

        if ($this->checkHoliday()) return false;

 

        $num = ($this->year <= 2006) ? 1 : 7; //改正法なら最大7日間遡る

 

        $d = clone $this;

        $d->modify('-1 day');

        $isTransfer = false;

        for ($i = 0 ; $i < $num ; $i++) {

            if ($d->checkHoliday()) {

                // 祝日かつ日曜ならば振替休日

                if ($d->dayOfWeek == 0) {

                    $isTransfer = true;

                    break;

                }

                $d->modify('-1 day');

            } else {

                break;

            }

        }

        return $isTransfer ? '振替休日' : false;

    }

 

    /**

     * 国民の休日かどうかチェック

     */

    public function checkNationalHoliday()

    {

        // 施行日チェック

        $d = new DateTime('2003-01-01');

        if ($this < $d) return false;

 

        $before = clone $this;

        $before->modify('-1 day');

        if ($before->checkHoliday() === false) return false;

 

        $after = clone $this;

        $after->modify('+1 day');

        if ($after->checkHoliday() === false) return false;

 

        return '国民の休日';

    }

 

    /**

     * 固定祝日かどうか

     */

    private function fixedHoliday($month, $day, $start, $end, $name)

    {

        if ($this->isWithinYear($start, $end) === false) return false;

        if ($this->month != $month) return false;

 

        if ($this->day != $day) return false;

        return $name;

    }

 

   /**

    * ハッピーマンデー

    */

   private function happyHoliday($month, $week, $start, $end, $name)

   {

       if ($this->isWithinYear($start, $end) === false) return false;

       if ($this->month != $month) return false;

 

       // 第*月曜日の日付を求める

       $w = 1; // 月曜日固定

       $d1 = new HolidayDateTime($this->format('Y-m-1'));

       $w1 = intval($d1->dayOfWeek);

       $day  = $w - $w1 < 0 ? 7 + $w - $w1 : $w - $w1;

       $day++;

       $day = $day + 7 * ($week - 1);

 

       if ($this->day != $day) return false;

       return $name;

   }

 

    /**

     * 春分の日

     */

    private function springHoliday($month, $dummy, $start, $end, $name)

    {

        if ($this->isWithinYear($start, $end) === false) return false;

        if ($this->month != $month) return false;

 

        $year = $this->year;

        $day = floor(20.8431 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));

 

        if ($this->day != $day) return false;

        return $name;

    }

 

    /**

     * 秋分の日

     */

    private function autumnHoliday($month, $dummy, $start, $end, $name)

    {

        if ($this->isWithinYear($start, $end) === false) return false;

        if ($this->month != $month) return false;

 

        $year = $this->year;

        $day = floor(23.2488 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));

 

        if ($this->day != $day) return false;

        return $name;

    }

 

    /**

     * 年が祝日適用範囲内であるか

     */

    private function isWithinYear($start, $end)

    {

        if ($this->year < $start || $end < $this->year) {

            return false;

        }

        return true;

    }

 

    // 以下Carbonを継承している場合は削除すべし

    public function __get($name)

    {

        switch (true) {

        case array_key_exists($name, $formats = [

            'year' => 'Y',

            'month' => 'n',

            'day' => 'j',

            'hour' => 'G',

            'minute' => 'i',

            'second' => 's',

            'micro' => 'u',

            'dayOfWeek' => 'w',

            'dayOfYear' => 'z',

            'weekOfYear' => 'W',

            'daysInMonth' => 't',

            'timestamp' => 'U',

        ]):

            return (int) $this->format($formats[$name]);

        }

    }

}

 

とても分かりやすくてありがたいです。

 

参考サイト記事 : https://qiita.com/chiyoyo/items/539dc2840a1b70a8e2c3

 

4139