4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Apexで日本の祝日を判定する

Posted at

Salesforce(Apex + Visualforce)でカレンダーを作る際に、祝日判定の機能がなかったのでApexクラスでつくりました。
祝日は大きく分けて次のパターン

  • 国民の休日
  • 固定祝日 ex. 元旦、建国記念の日、憲法記念日など
  • 春分の日
  • 秋分の日
  • ハッピーマンデー ex. 成人の日、海の日、敬老の日、体育の日
  • 振替休日

しかしここで気をつけなれけば行けないのが、当年だけに存在する固定祝日がある

  • 新天皇即位日
  • 即位礼正殿の儀

そのため、固定祝日を設定できるようオブジェクト化したほうがよいが、今回はApexクラス内で管理している。

春分の日と秋分の日

これは簡単、日付の計算方法が決まっているので、それをApexにするだけ

/**
 * 春分の日かどうか
 *
 * @params Date d 調べたい日付
 * @return boolean true:春分の日 / false:春分の日ではない
 **/
private static boolean isSpringHoliday(Date d) {
    return d.month() == 3 && d.day() == checkFourSeasons(20.8431, d.year());
}

/**
 * 秋分の日かどうか
 *
 * @params Date d 調べたい日付
 * @return boolean true:秋分の日 / false:秋分の日ではない
 **/
private static boolean isAutumnHoliday(Date d) {
    return d.month() == 9 && d.day() == checkFourSeasons(23.2488, d.year());
}

ハッピーマンデー

これも簡単、日付が固定されているのでそれにあわせるだけ

/**
 * ハッピーマンデーかどうか
 *
 * @params Date d 調べたい日付
 * @return boolean true:ハッピーマンデー / false:ハッピーマンデーではない
 **/
@TestVisible
private static boolean isHappyMonday(Date d) {
    Integer year = d.year();
    Integer month = d.month();
    Integer day = d.day();
    List<List<Integer> > holiday  = new List<List<Integer> > {
        //                             月 第N曜日 開始年 終了年
        new List<Integer> {1, 2, 2000, 9999}, // 成人の日
        new List<Integer> {7, 3, 2003, 9999}, // 海の日
        new List<Integer> {9, 3, 2003, 9999}, // 敬老の日
        new List<Integer> {10, 2, 2000, 9999} // 体育の日(スポーツの日)
    };

    Integer dow = getDayOfWeek(Date.newInstance(year, month, 1));
    Integer mondayOfWeek = 1;
    Integer happyDay = mondayOfWeek - dow < 0 ? 7 + mondayOfWeek - dow : mondayOfWeek - dow;
    happyDay++;

    for (List<Integer> variable : holiday) {
        if (month == variable[0]  && year >= variable[2] && year <= variable[3]) {
            happyDay = happyDay + 7 * (variable[1] - 1);
            if (happyDay == day) {
                return true;
            }
        }
    }

    return false;
}

固定祝日

固定もハッピーマンデーと似ており、処理を別にする必要は無いが、祝日分類のため別々のメソッドで管理している

/**
 * 固定祝日かどうか
 *
 * @params Date d 調べたい日付
 * @return boolean true:固定休日 / false:固定休日ではない
 **/
@TestVisible
private static boolean isFixedHoliday(Date d) {
    Integer year = d.year();
    Integer month = d.month();
    Integer day = d.day();
    List<List<Integer> > holiday  = new List<List<Integer> > {
        //                             月 日 開始年 終了年
        new List<Integer> {1, 1, 1949, 9999},    // 元旦
        new List<Integer> {2, 11, 1967, 9999},   // 建国記念の日
        new List<Integer> {2, 23, 2020, 9999},   // 天皇誕生日
        new List<Integer> {4, 29, 2007, 9999},   // 昭和の日
        new List<Integer> {5, 3, 1949, 9999},   // 憲法記念日
        new List<Integer> {5, 4, 2007, 9999},   // みどりの日
        new List<Integer> {5, 5, 1949, 9999},   // こどもの日
        new List<Integer> {8, 11, 2016, 9999},   // 山の日
        new List<Integer> {11, 3, 1948, 9999},   // 文化の日
        new List<Integer> {11, 23, 1948, 9999},   // 勤労感謝の日
        // 以下、指定した年月日のみの祝日
        new List<Integer> {5, 1, 2019, 2019},  // 新天皇即位日
        new List<Integer> {10, 22, 2019, 2019}  // 即位礼正殿の儀
    };

    for (List<Integer> variable : holiday) {
        if (month == variable[0] && day == variable[1] && year >= variable[2] && year <= variable[3]) {
            return true;
        }
    }

    return false;
}

振替休日と国民の休日?

ここがめんどくさい、いわゆる振替系

/**
 * 国民の休日かどうか
 *
 * @see https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html
 * @params Date d 調べたい日付
 * @return boolean true:国民の休日 / false:国民の休日ではない
 **/
@TestVisible
private static boolean isNationalHoliday(Date d) {
    Date yesterday = d - 1;
    Date tomorrow = d + 1;

    return checkHoliday(yesterday) && checkHoliday(tomorrow) && !new List<Integer> {0, 6}.contains(getDayOfWeek(d));
}

/**
 * 振替休日かどうか
 *
 * @params Date d 調べたい日付
 * @return boolean true:振替休日 / false:振替休日ではない
 **/
@TestVisible
private static boolean isTransferHoliday(Date d) {
    // 当日が祝日または日曜日ならfalse
    if (checkHoliday(d) || getDayOfWeek(d) == 0) {
        return false;
    }

    Date yesterday = d - 1;
    for (Integer i = getDayOfWeek(d); i >= 0; i--) {
        if (!checkHoliday(yesterday)) {
            return false;
        } else if (getDayOfWeek(yesterday) == 0) {
            return true;
        }
        yesterday = yesterday - 1;
    }

    return false;
}

祝日前後が平日か日曜日で判定をおこなう

全てをまとめたクラスはこちら

https://gist.github.com/akiyoshisamukawa/4a02a95e09522a23925376c498fc4d98
もっと効率よく処理を作成できるはずですので、あくまで参考として...

4
2
0

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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?