LoginSignup
22
22

More than 5 years have passed since last update.

祝日・休日算出クラス

Last updated at Posted at 2015-03-23

オレオレ・フレームワークに組み込んでいるクラスなんで、ガチガチの密結合です。多少環境に合わせて書き換え必要です。すんません…

よくよく見直してみると、Datetime() 使っていながら、所々 timestamp 使っているなあ…、気持ち悪いからそのうち修正しておきます修正しました。

<?php

namespace common\Date;

/**
 * Holiday
 */
class Holiday
{

    /**
     * 月を表す英語表記
     * @var array
     */
    static protected $_arrMonth = array(
        0 => ''
        , 1 => 'January'
        , 2 => 'February'
        , 3 => 'March'
        , 4 => 'April'
        , 5 => 'May'
        , 6 => 'June'
        , 7 => 'July'
        , 8 => 'August'
        , 9 => 'September'
        , 10 => 'October'
        , 11 => 'November'
        , 12 => 'December'
    );

    /**
     * 曜日配列
     * @var array
     */
    static protected $_arrWeek = array(
        0 => 'Sunday'
        , 1 => 'Monday'
        , 2 => 'Tuesday'
        , 3 => 'Wednesday'
        , 4 => 'Thursday'
        , 5 => 'Friday'
        , 6 => 'Saturday'
    );

    /**
     * 休日配列
     * @var array
     */
    static protected $_holidayDefinition = array(
        array('title' => '元日', 'start' => 1948, 'end' => null, 'month' => 1, 'day' => 1, 'weekNum' => null, 'week' => null)
        , array('title' => '成人の日', 'start' => 1949, 'end' => 1999, 'month' => 1, 'day' => 15, 'weekNum' => null, 'week' => null)
        , array('title' => '成人の日', 'start' => 2000, 'end' => null, 'month' => 1, 'day' => null, 'weekNum' => 2, 'week' => \Constants\Common::T_MONDAY)
        , array('title' => '建国記念の日', 'start' => 1967, 'end' => null, 'month' => 2, 'day' => 11, 'weekNum' => null, 'week' => null)
        , array('title' => '春分の日', 'start' => 1948, 'end' => null, 'month' => 3, 'day' => null, 'weekNum' => null, 'week' => null)
        , array('title' => '天皇誕生日', 'start' => 1948, 'end' => 1988, 'month' => 4, 'day' => 29, 'weekNum' => null, 'week' => null)
        , array('title' => 'みどりの日', 'start' => 1989, 'end' => 2006, 'month' => 4, 'day' => 29, 'weekNum' => null, 'week' => null)
        , array('title' => '昭和の日', 'start' => 2007, 'end' => null, 'month' => 4, 'day' => 29, 'weekNum' => null, 'week' => null)
        , array('title' => '憲法記念日', 'start' => 1948, 'end' => null, 'month' => 5, 'day' => 3, 'weekNum' => null, 'week' => null)
        , array('title' => 'みどりの日', 'start' => 2007, 'end' => null, 'month' => 5, 'day' => 4, 'weekNum' => null, 'week' => null)
        , array('title' => 'こどもの日', 'start' => 1948, 'end' => null, 'month' => 5, 'day' => 5, 'weekNum' => null, 'week' => null)
        , array('title' => '海の日', 'start' => 1996, 'end' => 2002, 'month' => 7, 'day' => 20, 'weekNum' => null, 'week' => null)
        , array('title' => '海の日', 'start' => 2003, 'end' => null, 'month' => 7, 'day' => null, 'weekNum' => 3, 'week' => \Constants\Common::T_MONDAY)
        , array('title' => '山の日', 'start' => 2016, 'end' => null, 'month' => 8, 'day' => 11, 'weekNum' => null, 'week' => null)
        , array('title' => '敬老の日', 'start' => 1956, 'end' => 2002, 'month' => 9, 'day' => 15, 'weekNum' => null, 'week' => null)
        , array('title' => '敬老の日', 'start' => 2003, 'end' => null, 'month' => 9, 'day' => null, 'weekNum' => 3, 'week' => \Constants\Common::T_MONDAY)
        , array('title' => '秋分の日', 'start' => 2003, 'end' => null, 'month' => 9, 'day' => null, 'weekNum' => null, 'week' => null)
        , array('title' => '体育の日', 'start' => 1966, 'end' => 1999, 'month' => 10, 'day' => 10, 'weekNum' => null, 'week' => null)
        , array('title' => '体育の日', 'start' => 2000, 'end' => null, 'month' => 10, 'day' => null, 'weekNum' => 2, 'week' => \Constants\Common::T_MONDAY)
        , array('title' => '文化の日', 'start' => 1948, 'end' => null, 'month' => 11, 'day' => 3, 'weekNum' => null, 'week' => null)
        , array('title' => '勤労感謝の日', 'start' => 1948, 'end' => null, 'month' => 11, 'day' => 23, 'weekNum' => null, 'week' => null)
        , array('title' => '天皇誕生日', 'start' => 1989, 'end' => null, 'month' => 12, 'day' => 23, 'weekNum' => null, 'week' => null)
    );

    /**
     * 曜日から日付を取得する
     * @param integer $y
     * @param integer $m
     * @param integer $n
     * @param integer $w
     * @return string
     */
    static protected function getDateFromWeek($y, $m, $n, $w)
    {
        $time = sprintf("%04d-%02d-%02d", $y, $m, 1);
        $objDate = new \DateTime($time);

        // 指定曜日の最初の日付を取得して指定週の日付を算出
        $first_weekday = $objDate->format('w');
        $result_day = $w - $first_weekday + 1;
        if ($result_day < 1) {
            $result_day += 7;
        }
        $result_day = $result_day + ($n - 1) * 7;
        if ($result_day > 31) {
            return 0;
        }
        return sprintf("%04d-%02d-%02d", $y, $m, $result_day);
    }

    /**
     * 年から休日の配列を取得する
     * @param integer $intYear
     * @return array
     * @throws \common\InvalidErrorException
     */
    static public function get($intYear)
    {
        if (1851 > $intYear || 2099 < $intYear) {
            $msg = '[year]パラメータが不正です。';
            throw new \common\InvalidErrorException($msg);
        }
        $res = array();
        $alt = null;
        $arrHoliday = self::$_holidayDefinition;
        foreach ($arrHoliday as $i => $holiday) {
            if ($holiday['start'] <= $intYear &&
                ($intYear <= $holiday['end'] || null == $holiday['end'])
            ) {
                if (!is_null($holiday['day'])) {
                    $res[] = array(
                        'title' => $holiday['title']
                        , 'year' => (int) $intYear
                        , 'month' => $holiday['month']
                        , 'day' => $holiday['day']
                        , 'date' => sprintf("%04d-%02d-%02d"
                            , $intYear
                            , $holiday['month']
                            , $holiday['day']
                        )
                    );
                } else if (!is_null($holiday['weekNum']) &&
                    !is_null($holiday['week'])) {
                    //  第○週×曜日
                    $intMonth = $holiday['month'];
                    $weekNum = $holiday['weekNum'];
                    $week = $holiday['week'];
                    $timestamp = self::getDateFromWeek(
                            $intYear
                            , $intMonth
                            , $weekNum
                            , $week
                    );
                    $objDate = new \DateTime($timestamp);
                    $res[] = array(
                        'title' => $holiday['title']
                        , 'year' => (int) $objDate->format('Y')
                        , 'month' => (int) $objDate->format('m')
                        , 'day' => (int) $objDate->format('d')
                        , 'date' => $timestamp
                    );
                } else if (3 == $holiday['month']) {
                    //  春分の日
                    $res[] = array(
                        'title' => $holiday['title']
                        , 'year' => (int) $intYear
                        , 'month' => (int) $holiday['month']
                        , 'day' => (int) self::springHoliday($intYear)
                        , 'date' => sprintf("%04d-%02d-%02d"
                            , $intYear
                            , $holiday['month']
                            , self::springHoliday($intYear)
                        )
                    );
                } else if (9 == $holiday['month']) {
                    //  秋分の日
                    $res[] = array(
                        'title' => $holiday['title']
                        , 'year' => (int) $intYear
                        , 'month' => (int) $holiday['month']
                        , 'day' => (int) self::autumnHoliday($intYear)
                        , 'date' => sprintf("%04d-%02d-%02d"
                            , $intYear
                            , $holiday['month']
                            , self::autumnHoliday($intYear)
                        )
                    );
                }
            }
        }
        $resHoliday = array();
        foreach ($res as $i => $holiday) {
            $resHoliday[] = $holiday;
            //  振替休日
            $alt = self::alternativeHoliday(
                    $intYear
                    , $holiday['month']
                    , $holiday['day']
            );
            if (isset($alt) && !is_null($alt) && isset($res[$i + 1])) {
                $nextHolidy = $res[$i + 1];
                if ($nextHolidy['month'] != $alt['month'] ||
                    $nextHolidy['day'] != $alt['day']) {
                    $resHoliday[] = $alt;
                }
            }

            //  国民の休日
            $objHoliday = new \DateTime;
            $objHoliday->setDate(
                $holiday['year']
                , $holiday['month']
                , $holiday['day']
            );
            $objTomorrow = $objHoliday->add(new \DateInterval('P1D'));
            $objDayaftertomorrow = $objHoliday->add(new \DateInterval('P1D'));

            if (isset($res[$i + 1])) {
                $nextHolidy = $res[$i + 1];
                if ((int) $nextHolidy['month'] == (int) $objDayaftertomorrow->format('m') &&
                    (int) $nextHolidy['day'] == (int) $objDayaftertomorrow->format('d')) {
                    $resHoliday[] = array(
                        'title' => '国民の休日'
                        , 'year' => (int) $intYear
                        , 'month' => (int) $objTomorrow->format('m')
                        , 'day' => (int) $objTomorrow->format('d')
                        , 'date' => sprintf(
                            "%04d-%02d-%02d"
                            , $intYear
                            , (int) $objTomorrow->format('m')
                            , (int) $objTomorrow->format('d')
                        )
                    );
                }
            }
        }
        return $resHoliday;
    }

    /**
     * 振替休日
     * @param integer $intYear
     * @param integer $intMonth
     * @param integer $intDay
     * @return array
     */
    static protected function alternativeHoliday($intYear, $intMonth, $intDay)
    {
        $objDate = new \DateTime(
            sprintf("%04d-%02d-%02d", $intYear, $intMonth, $intDay)
        );
        if (0 == $objDate->format('w')) {
            $objDate->add(new \DateInterval('P1D'));
            return array(
                'title' => '振替休日'
                , 'year' => (int) $intYear
                , 'month' => (int) $objDate->format('m')
                , 'day' => (int) $objDate->format('d')
                , 'date' => $objDate->format('Y-m-d')
            );
        } else {
            return null;
        }
    }

    /**
     * 春分の日
     * @param integer $intYear
     * @return string
     */
    static protected function springHoliday($intYear)
    {
        if (1851 <= $intYear && 1899 >= $intYear) {
            $day = 19.8277 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
        } else if (1900 <= $intYear && 1979 >= $intYear) {
            $day = 20.8357 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
        } else if (1980 <= $intYear && 2099 >= $intYear) {
            $day = 20.8431 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
        } else if (2100 <= $intYear && 2150 >= $intYear) {
            $day = 21.8510 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
        }
        return floor($day);
    }

    /**
     * 秋分の日
     * @param integer $intYear
     * @return string
     */
    static protected function autumnHoliday($intYear)
    {
        if (1851 <= $intYear && 1899 >= $intYear) {
            $day = 22.2588 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
        } else if (1900 <= $intYear && 1979 >= $intYear) {
            $day = 23.2588 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
        } else if (1980 <= $intYear && 2099 >= $intYear) {
            $day = 23.2488 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
        } else if (2100 <= $intYear && 2150 >= $intYear) {
            $day = 24.2488 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
        }
        return floor($day);
    }

}
22
22
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
22