AddinBox(Title_Logo)

  -- Page 6 --

      VBAおよびVB用の祝日判定用マクロ[関数](『kt関数アドイン/kt祝日名取得』の
  ロジックと同じものです)を公開しています。また、VBA用の祝日判定用マクロ[関数]を
  基にして、他言語向けに編集移植したコードを頂きましたので、併せて、このページで
  公開します。

      なお、祝日に関する詳細情報こちらのページをご覧下さい。

      VBA用コードは純粋にVB構文だけ(エクセル独自の機能は使ってません)で作って
    ありますので、エクセルだけでなくアクセスや、その他のVBAを使うアプリケーション
    でも利用できます。
  ※ 重要 ※
    ・ [ 東京五輪 臨時祝日 / 体育の日 改名 ]
      「体育の日」が2020年から「スポーツの日」に改名となります。
      東京五輪特措法により2020年の「海の日/山の日/スポーツの日」が移動となります。
      (2018/6/21)

    ・ [ 生前退位/皇位継承 ]
      平成31年 ( 2019年 ) 4月30日 退位 / 翌5月1日 即位 で決定しました。
      天皇誕生日が [ 12/23 ⇒ 2/3 ] へ変わります(2019年に 天皇誕生日はありません)。
      また、[ 即位礼 正殿の儀 ] は10月22日です。
      (2018/2/15)

 
  ※ 訂正案内 2018/6/21 ※
    下記の言語で 「振替休日の判定」等に誤り がありましたので修正しました。

            [ C , C# , Perl , AWK , Transact-SQL , Python , Go ]

    修正箇所の説明は各言語版の項に記してあります。



※VBA以外に移植したコードも紹介しています※
 ・ 「東京五輪 臨時祝日/体育の日 改名」 改正への対応済みです。 (2018/6/21)
 ・ 「天皇誕生日の変更」 改正への対応済みです。 (2018/2/15)

   [ 旧サイト ( DIONサーバー ) の Internet Archive ( Page 6 ) ]
--言語-- -- 移  植 -- -公開日- -頁-
  ・ 祝日判定マクロ の 設計方針について
  ・ And / Or 演算子 : 完全評価( Complete )型 と 短絡評価( Short-circuit )型
  ・ オーソドックス な 「表引き」 手法との比較
  ・ 祝日判定の拡張 ( 土日も含める 等 ) について
  ・ 拡張マクロ : 銀行休日の判定
  ・ 5月6日 ( 振替休日 ) の判定方法について
 
1
VB/VBA AddinBox(角田) 2002/ 3/16 1
Delphi AddinBox(角田) 2002/11/22
JavaScript AddinBox(角田) 2003/ 5/ 9
OOoBasic AddinBox(角田) 2005/ 4/15

VB2005 Fukuchi さん 2006/ 7/ 4 2
VBS 立野 徹 さん 2003/ 3/ 2
PHP 代理店どっとこむ「中野」 さん 2003/ 5/ 6

C こほろぎ AsaPi! さん 2003/ 3/ 2 3
C# 小山 隆史 さん 2005/12/17
Perl 富士ソフトサービスビューロ(株)
    BS部 「稲葉」 さん
2003/ 6/ 9
AWK 富士ソフトサービスビューロ(株)
    BS部 「稲葉」 さん
2003/ 6/11

Apollo たけ(tk) さん 2003/ 9/24 4
Ruby たけ(tk) さん 2005/ 4/15
JAVA 阿蛭 栄一 さん 2003/12/21

Transact-SQL シリコンブレス  有方 公一 さん 2006/ 8/ 1 5
PL/SQL 菅 康明 さん 2006/12/ 1
Python 瀬戸口 光宏 さん 2007/ 5/28

ActionScript 3 stocksrc.com  2010/ 3/23 6
Go 言語 杉田 臣輔 さん 2015/ 1/ 6
       
      自由に各自のプログラムに組み込んで利用して下さい。なお、フリー/シェアソフト
    開発での利用も可(フリー/シェアでの利用の場合、事後で結構ですので一言
    お知らせください)です。ただし、引用に当たっては、マクロの先頭に記述してある
        コメント(CopyRight )を必ず一緒に引用する事

    を条件とします。

      なお、他サイト上で本コードを直接引用する事は、ご遠慮願います。本ページへの
    リンクによる紹介で対応して下さい。

      [ktHolidayName]という関数名そのものは、各自の環境における命名規則に沿って
    変更しても構いません
      VBA(VB含む)で利用する場合はマクロのコード構成を一切変更しないでください。
    VBAというレスポンス的に不利な言語でも出来る限りレスポンスを良くする事を前提に
    設計してある為、コード内容を変更するとレスポンスが低下する可能性があります

      VBA以外の言語に移植する場合は、その言語の特性に合わせたベストなコード構成
    変更しても構いません。

    また、出来上がったものをご連絡頂ければ、このページにて紹介させて貰います。

    尚、移植に際しては、And/Orによる条件演算、および[春分の日/秋分の日]算出式の
    INT演算について各言語特性に留意して下さい。また、表引き手法を採らない理由
    御一読ください。



[ Note ]
  Access などで、[Null値]を受け取る/返すといった必要がある場合には、下記のように
『ktHolidayName 』の外側に、もうひとつ関数を被せるようにする事で『ktHolidayName 』
自体は変更せずに利用する事ができます(この場合には、ktHolidayName は'Private'に
して下さい)。尚、下記はVBA(VB)コードによる例です。

Public Function 祝日名(ByVal 日付 As Variant) As Variant
  If IsDate(日付) Then
        祝日名 = ktHolidayName(CDate(日付))
    Else
        祝日名 = Null
    End If
End Function

  その他に「銀行休日」で「土日休み」部分も一緒にフォローしたいといった場合でも
同様の方法で対応できます。

Public Function 祝日_土日(ByVal 日付 As Date) As String
    祝日_土日 = ktHolidayName(日付)
    If (祝日_土日 = "") Then
        Select Case Weekday(日付)
            Case vbSunday: 祝日_土日 = "日"
            Case vbSaturday: 祝日_土日 = "土"
            Case Else
        End Select
    End If
End Function

  このようにする事で[ktHolidayName]のロジック自体を変更せずに、様々な条件を付け加える
事が可能です。引用する際には[ktHolidayName]そのものには手を加えずに、コメントを含めて
丸々コピーするようにしてください。
  ktHolidayName/prv祝日 の内部に処理を追加してしまうと、将来再び祝日法が変更された
場合に、新しいktHolidayName/prv祝日上書き修正により、追加した処理が消えてしま
います。そうならない為にも、ktHolidayName/prv祝日には手を加えずに、その外側にプロシ
ジャーを用意して、そこで機能追加を施すようにして下さい。




[ この場所へのリンク ]


Action Script 3 用祝日判定コード 】    [ 検証用データ ( 祝日一覧 ) は JavaScript 版による ツール で取得できます ]
  2010/3/23 追記 ( [昭和の日] 改正 対応済 )
  2014/5/29 [山の日]改正の修正
  2018/2/15 [天皇誕生日の変更]改正の修正
  2018/6/21 一部修正( 下記参照 )
  2018/6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動] 改正の修正


    VBAコードのロジックを、そのまま[ Action Script 3 ]用に書き直したものです。
    stocksrc.com さんによる編集です。

    土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。

    『祝日について

    「昭和の日」に伴う「振替休日(5月6日)」改正への修正方針もお読みください。


  --- 修正内容の説明 --------------------------------------
  2018/6/21     : 修正前ソースコード ( Internet Archive )
        不具合修正ではありません。
        成人の日/海の日/敬老の日/スポーツの日 のハッピーマンデー判定式が他言語版と異なって、
        [ 日の範囲 ]式になっているのを、他言語版に合わせた式に変更します。

        成人の日/スポーツの日 ( 第2月曜日 )
            (myDate >= 8 && myDate <= 14) && ( myDay == MONDAY )
                ⇒ (int((myDate - 1) / 7) == 1) && ( myDay == MONDAY )
        海の日/敬老の日 ( 第3月曜日 )
            (myDate >= 15 && myDate <= 21) && ( myDay == MONDAY )
                ⇒ (int((myDate - 1) / 7) == 2) && ( myDay == MONDAY )
  ---------------------------------------------------------------------------------


    ----------- Action Script における 曜日値について -----------
        曜日の値は [ 日(0), 月(1), 火(2), 水(3), 木(4), 金(5), 土(6) ] です。
        システム定数は用意されていません。


----------------------------------------------------------------------------------------

package {

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //_/
    //_/  --- ActionScript3 移植版 ---
    //_/
    //_/  CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
    //_/  ( AddinBox  http://addinbox.sakura.ne.jp/index.htm )
    //_/  (  旧サイト  http://www.h3.dion.ne.jp/~sakatsu/index.htm )
    //_/
    //_/  この祝日マクロは『kt関数アドイン』で使用しているものです。
    //_/  このロジックは、レスポンスを第一義として、可能な限り少ない
    //_/  【条件判定の実行】で結果を出せるように設計してあります。
    //_/
    //_/  この関数では以下の祝日変更までサポートしています。
    //_/  ・2019年施行の「天皇誕生日の変更」 12/23⇒2/23 (補:2019年には[天皇誕生日]はありません)
    //_/  ・2020年施行の「体育の日の改名」⇒スポーツの日
    //_/  ・五輪特措法による2020年の「祝日移動」
    //_/      海の日:7/20(3rd Mon)⇒7/23, スポーツの日:10/12(2nd Mon)⇒7/24, 山の日:8/11⇒8/10
    //_/
    //_/  下記2つについては未だ法整備自体が行なわれていませんので未対応です。
    //_/  ・2019年の退位日(4/30)/即位日(5/1)
    //_/  ・2019年の「即位の礼 正殿の儀 (10/22) 」
    //_/
    //_/  (*1)このマクロを引用するに当たっては、必ずこのコメントも
    //_/      一緒に引用する事とします。
    //_/  (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。
    //_/      【 http://addinbox.sakura.ne.jp/holiday_logic.htm 】
    //_/      へのリンクによる紹介で対応して下さい。
    //_/  (*3)[ktHolidayName]という関数名そのものは、各自の環境に
    //_/      おける命名規則に沿って変更しても構いません。
    //_/
    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //
    // 2014/5/29 [山の日]改正の修正
    // 2018/2/15 [天皇誕生日の変更]改正の修正
    // 2018/6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動] 改正の修正
    //

    // ActionScript3用 (http://www.stocksrc.com/)


    public class KtHoliday{
        // 月は [ 0 - 11 ] です
        private static const IMPLEMENT_THE_LAW_OF_HOLIDAY:Date = new Date( 1948, 6, 20 );  // 祝日法施行
        private static const AKIHITO_KEKKON:Date = new Date( 1959, 3, 10 );    // 明仁親王の結婚の儀
        private static const SHOWA_TAISO:Date = new Date( 1989, 1, 24 );      // 昭和天皇大喪の礼
        private static const NORIHITO_KEKKON:Date = new Date( 1993, 5, 9 );    // 徳仁親王の結婚の儀
        private static const SOKUIREI_SEIDEN:Date = new Date( 1990, 10, 12 );  // 即位礼 正殿の儀(平成天皇)
        private static const IMPLEMENT_HOLIDAY = new Date( 1973, 3, 12 );      // 振替休日施行

        private static const MONDAY = 1;      // [ 日(0), 月(1) ... 土(6) ]
        private static const TUESDAY = 2;
        private static const WEDNESDAY = 3;

        //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        //
        //                  Constructor
        //
        //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

        public function KtHoliday() {}



        //
        // 祝日かどうか判定
        // @param  date 日付
        // @default null nullの場合は現在のローカルの日付で判定を行う
        // @return 祝日の場合は祝日名、祝日以外の場合は空文字("")を返す
        //

        public static function ktHolidayName( date:Date ):String {
            var _date:Date;
            var _date2:Date;
            var yesterday:Date;
            var dayName:String;
            var holidayName:String;

            if ( date != null ) {
                _date2 = date;
            } else {
                _date2 = new Date();
            }
            _date = new Date( _date2.getFullYear(), _date2.getMonth(), _date2.getDate() )  // 時間部の除去

            holidayName = KtHoliday.holidayChk( _date );

            // ----- 振替休日の判定 (振替休日施行日:1973/4/12) -----
            // [ 対象日≠祝日/休日 & 対象日=月曜日 ]のみ、前日(=日曜日)を祝日判定する。
            // 前日(=日曜日)が祝日の場合は”振替休日”となる。
            // 尚、5月6日の扱いを
            //     「火曜 or 水曜(みどりの日(5/4) or 憲法記念日(5/3)の振替休日)」⇒5月ブロック内で判定済
            //     「月曜(こどもの日(5/5)の振替休日」⇒ここの判定処理で判定
            // とする事により、ここでの判定対象は『対象日が月曜日』のみ となります。

            if ( holidayName == "" ) {
                if ( _date.getDay() == MONDAY ) {
                    if ( _date.time >= IMPLEMENT_HOLIDAY.time ) {
                        yesterday = new Date(_date.getFullYear(), _date.getMonth(), (_date.getDate() - 1));
                        holidayName = KtHoliday.holidayChk( yesterday );
                        if ( holidayName != "" ) {
                            dayName = "振替休日";
                        } else {
                            dayName = "";
                        }
                    } else {
                        dayName = "";
                    }
                } else {
                    dayName = "";
                }
            } else {
                dayName = holidayName;
            }
            return dayName;
        }

        //
        // 基本の祝日判定
        //

        private static function holidayChk( date:Date ):String
        {
            var dayName:String = "";
            var myYear:int = date.getFullYear();    // 4桁 西暦年
            var myMonth:int = date.getMonth() + 1;  // 月:1-12 ( +1 加算 )
            var myDate:int = date.getDate();        // 日:1-31
            var myDay:int = date.getDay();          // 曜日:日(0),月(1) ... 土(6)

            if ( date.time < IMPLEMENT_THE_LAW_OF_HOLIDAY.time ) {  // 祝日法施行以前
                return dayName;
            }

            switch( myMonth ) {
            // ---- 1月 ----
            case 1:
                if ( myDate == 1 ){
                    dayName = "元日";
                } else{
                    if ( myYear >= 2000 ){
                        if (int((myDate - 1) / 7) == 1) && ( myDay == MONDAY ) {   // 2nd Monday
                            dayName = "成人の日";
                        }
                    } else {
                        if ( myDate == 15 ) {
                            dayName = "成人の日";
                        }
                    }
                }
                break;

            // ---- 2月 ----
            case 2:
                if ( myDate == 11 ) {
                    if ( myYear >= 1967 ){
                        dayName = "建国記念の日";
                    }
                } else if ( myDate == 23 ) {
                    if ( myYear >= 2020 ){
                        dayName = "天皇誕生日";
                    }
                } else if ( date.time == SHOWA_TAISO.time ){
                    dayName = "昭和天皇の大喪の礼";
                }
                break;

            // ---- 3月 ----
            case 3:
                if ( myDate == SpringEquinox( myYear ) ){    // 1948〜2150以外は[99]が返るので、必ず≠になる
                    dayName = "春分の日";
                }
                break;

            // ---- 4月 ----
            case 4:
                if ( myDate == 29 ) {
                    if ( myYear >= 2007 ){
                        dayName = "昭和の日";
                    } else if ( myYear >= 1989 ) {
                        dayName = "みどりの日";
                    }else {
                        dayName = "天皇誕生日";  // 昭和天皇
                    }
                } else if ( date.time == AKIHITO_KEKKON.time ) {
                    dayName = "皇太子明仁親王の結婚の儀";
                }
                break;

            // ---- 5月 ----
            case 5:
                if ( myDate == 3 ){
                    dayName = "憲法記念日";
                } else if ( myDate == 4 ) {
                    if( myYear >= 2007 ){
                        dayName = "みどりの日";
                    } else if ( myYear >= 1986 ) {
                        // 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』(〜2006年)
                        if ( myDay > MONDAY ) {     // 火曜 以降(火〜土)
                            dayName = "国民の休日";
                        }
                    }
                } else if ( myDate == 5 ) {
                    dayName = "こどもの日";
                } else if ( myDate == 6 ) {
                    if ( myYear >= 2007 ){
                        if ( myDay == TUESDAY || myDay == WEDNESDAY ) {
                            dayName = "振替休日";    // [5/3,5/4が日曜]ケースのみ、ここで判定
                        }
                    }
                }
                break;

            // ---- 6月 ----
            case 6:
                if ( date.time == NORIHITO_KEKKON.time ) {
                    dayName = "皇太子徳仁親王の結婚の儀";
                }
                break;

            // ---- 7月 ----
            case 7:
                if ( myYear >= 2021 ){
                    if (int((myDate - 1) / 7) == 2) && ( myDay == MONDAY ) {     // 3rd Monday
                        dayName= "海の日";
                    }
                } else if ( myYear == 2020 ){
                    // 2020年はオリンピック特措法により
                    // 「海の日」が 7/23 , 「スポーツの日」が 7/24 に移動
                    if ( myDate == 23 ){
                        dayName= "海の日";
                    } else if ( myDate == 24 ){
                        dayName= "スポーツの日";
                    }
                } else if ( myYear >= 2003 ){
                    if (int((myDate - 1) / 7) == 2) && ( myDay == MONDAY ) {     // 3rd Monday
                        dayName= "海の日";
                    }
                } else if ( myYear >= 1996 ) {
                    if ( myDate == 20 ) {
                        dayName= "海の日";
                    }
                }
                break;

            // ---- 8月 ----
            case 8:
                if ( myYear >= 2021 ){
                    if ( myDate == 11 ) {
                        dayName = "山の日";
                    }
                } else if ( myYear == 2020 ){
                    // 2020年はオリンピック特措法により「山の日」が 8/10 に移動
                    if ( myDate == 10 ) {
                        dayName = "山の日";
                    }
                } else if ( myYear >= 2016 ){
                    if ( myDate == 11 ) {
                        dayName = "山の日";
                    }
                }
                break;

            // ---- 9月 ----
            case 9:
                // 第3月曜日(15〜21)と秋分日(22〜24)が重なる事はない
                if ( myDate == AutumnEquinox( myYear ) ){    // 1948〜2150以外は[99]が返るので、必ず≠になる
                    dayName = "秋分の日";
                } else {
                    if ( myYear >= 2003 ){
                        if (int((myDate - 1) / 7) == 2) && ( myDay == MONDAY ) {   // 3rd Monday
                            dayName = "敬老の日";
                        } else if ( myDay == TUESDAY ) {
                            if ( myDate == (AutumnEquinox( myYear ) - 1) ) {
                                dayName = "国民の休日";    // 火曜日&[秋分日の前日]
                            }
                        }
                    } else if ( myYear >= 1966 ) {
                        if ( myDate == 15 ) {
                            dayName = "敬老の日";
                        }
                    }
                }
                break;

            // ---- 10月 ----
            case 10:
                if( myYear >= 2021 ){
                    if (int((myDate - 1) / 7) == 1) && ( myDay == MONDAY ) {   // 2nd Monday
                        dayName = "スポーツの日";  // 2020年より改名
                    }
                } else if ( myYear == 2020 ){
                    // 2020年はオリンピック特措法により「スポーツの日」が 7/24 に移動
                } else if ( myYear >= 2000 ){
                    if (int((myDate - 1) / 7) == 1) && ( myDay == MONDAY ) {   // 2nd Monday
                        dayName = "体育の日";
                    }
                } else if ( myYear >= 1966 ) {
                    if ( myDate == 10 ) {
                        dayName = "体育の日";
                    }
                }
                break;

            // ---- 11月 ----
            case 11:
                if(  myDate == 3  ){
                    dayName = "文化の日";
                } else if ( myDate == 23 ) {
                    dayName = "勤労感謝の日";
                } else if( date.time == SOKUIREI_SEIDEN.time  ) {
                    dayName = "即位礼正殿の儀";   // 平成天皇
                }
                break;

            // ---- 12月 ----
            case 12:
                if ( myDate == 23 ) {
                    if (( myYear >= 1989 ) && ( myYear <= 2018 )) {
                        dayName = "天皇誕生日";   // 平成天皇
                    }
                }
                break;
            }
            return dayName;
        }

        // 春分/秋分日の略算式は
        //   海上保安庁水路部 暦計算研究会編 新こよみ便利帳』
        // で紹介されている式です。


        // 春分の日
        private static function SpringEquinox( year:int ):int {
            var springEquinox:int;
            if ( year <= 1947 ) {
                springEquinox = 99;  // 祝日法施行前
            } else if ( year <= 1979 ) {
                springEquinox = int(20.8357 + 0.242194 * ( year - 1980)) - int((year - 1983) / 4) ;
            } else if ( year <= 2099 ) {
                springEquinox = int(20.8431 + 0.242194 * ( year - 1980)) - int((year - 1980) / 4) ;
            } else if ( year <= 2150 ) {
                springEquinox = int(21.851 + 0.242194 * ( year - 1980)) - int((year - 1980) / 4) ;
            } else {
                springEquinox = 99;  // 2151年以降は略算式が無いので不明
            }
            return springEquinox;
        }

        // 秋分の日
        private static function AutumnEquinox( year:int ):int {
            var autumnEquinox:int;
            if ( year <= 1947 ) {
                autumnEquinox = 99;  // 祝日法施行前
            } else if ( year <= 1979 ) {
                autumnEquinox = int(23.2588 + 0.242194 * ( year - 1980)) - int((year - 1983) / 4) ;
            } else if ( year <= 2099 ){
                autumnEquinox = int(23.2488 + 0.242194 * ( year - 1980)) - int((year - 1980) / 4);
            } else if ( year <= 2150 ) {
                autumnEquinox = int(24.2488 + 0.242194 * ( year - 1980)) - int((year - 1980) / 4) ;
            } else {
                autumnEquinox = 99;  // 2151年以降は略算式が無いので不明
            }
            return autumnEquinox;
        }

    }

}




[ この場所へのリンク ]


Go 用祝日判定コード 】    [ 検証用データ ( 祝日一覧 ) は JavaScript 版による ツール で取得できます ]
  2015/1/6 追記  ([山の日] 改正 対応済み)
  2018/2/15 [天皇誕生日の変更]改正の修正
  2018/6/21 不具合修正( 下記参照 )
  2018/6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動] 改正の修正


    VBAコードのロジックを元にした Python 版から[ Go 言語 ]用に書き直したものです。
    「杉田 臣輔」さんによる編集です。[ GitHub / jcalender ]

    土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
    『祝日について

    「昭和の日」に伴う「振替休日(5月6日)」改正への 修正方針 もお読みください。

    --- Go 言語について補足 ---
    Go 言語は Google によって開発されたプログラミング言語です。
    詳しくは下記サイトを参照して下さい。
          [ Wikipedia - Go (プログラミング言語) ]
          [ 実践 Go 言語 ]

  --- 修正内容の説明 --------------------------------------
  2018/6/21     : 修正前ソースコード ( Internet Archive )
        曜日値のコンスタント定義を取り止め、Time パッケージの定義を利用するように修正します( MONDAY ⇒ time.Monday )。
        また、曜日値のコンスタント定義の値 ( MONDAY(0), TUESDAY(1), WEDNESDAY(2) ) そのものが誤っていました。
        Go 言語では [ 日(0), 月(1), 火(2), … 土(6) ] です。
        const (
                MONDAY = 0
                TUESDAY
                WEDNESDAY
        )


        振替休日の判定処理に誤りがありました ( 元にした Python 版 のコード [ not name ] の意味を誤解したようです )。
            if name != "" && p.Date.Weekday() == MONDAY {
        正しい判定処理は「祝日名が得られなかった ( == "" ) 場合、月曜日に限り、前日の祝日判定を行なう」です。
        また、振替休日の施行日判定も漏れていました。以下のように修正します。
            (誤) if name != "" && p.Date.Weekday() == MONDAY {
            (正) if name == "" && p.Date.Weekday() == time.Monday 
                    && p.Date.Sub(time.Date(1973, 4, 12, 0, 0, 0, 0, now.Location())) >= 0 {


        5月4日(国民の休日:1986〜2006年)の判定処理に誤りがありました ( 元にした Python 版 のバグを引き継いだようです )。
        } else if p.Date.Day() == 4 {
                if p.Date.Year() >= 2007 {
                        name = "みどりの日"
                } else if p.Date.Year() >= 1986 && p.Date.Weekday() != MONDAY {
                        name = "国民の休日"

        [ p.Date.Weekday() != MONDAY ] が間違っていました。元々の判定式は、
                [ 曜日値が 『 日,月,火 〜 土 』の並びで 『 曜日 > 月曜日 』 ]
        です。つまり、火曜〜土曜の範囲が対象です。
        更に Go 言語では [ 日(0), 月(1), 火(2), … 土(6) ] のところを、前述の通り [ MONDAY : 0 ] でコンスタント定義して
        いますので、結局のところ [ 日曜日ではない ] という条件式になっています。以下のように修正します。
          (誤) } else if p.Date.Year() >= 1986 && p.Date.Weekday() != MONDAY {
          (正) } else if p.Date.Year() >= 1986 && p.Date.Weekday() > time.Monday {

  ---------------------------------------------------------------------------------

    ----------- Go 言語 における 曜日値について -----------
        曜日の値は [ 日(0), 月(1), 火(2), 水(3), 木(4), 金(5), 土(6) ] です。
        システム定数の [ time.Sunday, time.Monday, … time.Saturday ] が利用できます。


----------------------------------------------------------------------------------------
※※ Tab インデントの ファイル( Go_Holiday.txt ) を用意してありますのでダウンロードして使って下さい※※

package jcalender

/*
※※ このコードは「空白4文字」でインデントしてあります ※※

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
_/
_/  --- Go 言語 移植版 ---
_/
_/  CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
_/  ( AddinBox  http://addinbox.sakura.ne.jp/index.htm )
_/  (  旧サイト  http://www.h3.dion.ne.jp/~sakatsu/index.htm )
_/
_/  この祝日マクロは『kt関数アドイン』で使用しているものです。
_/  このロジックは、レスポンスを第一義として、可能な限り少ない
_/  【条件判定の実行】で結果を出せるように設計してあります。
_/
_/  この関数では以下の祝日変更までサポートしています。
_/  ・2019年施行の「天皇誕生日の変更」 12/23⇒2/23 (補:2019年には[天皇誕生日]はありません)
_/  ・2020年施行の「体育の日の改名」⇒スポーツの日
_/  ・五輪特措法による2020年の「祝日移動」
_/      海の日:7/20(3rd Mon)⇒7/23, スポーツの日:10/12(2nd Mon)⇒7/24, 山の日:8/11⇒8/10
_/
_/  下記2つについては未だ法整備自体が行なわれていませんので未対応です。
_/  ・2019年の退位日(4/30)/即位日(5/1)
_/  ・2019年の「即位の礼 正殿の儀 (10/22) 」
_/
_/  (*1)このマクロを引用するに当たっては、必ずこのコメントも
_/      一緒に引用する事とします。
_/  (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。
_/      【 http://addinbox.sakura.ne.jp/holiday_logic.htm 】
_/      へのリンクによる紹介で対応して下さい。
_/  (*3)[ktHolidayName]という関数名そのものは、各自の環境に
_/      おける命名規則に沿って変更しても構いません。
_/
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
*/


import (
    "math"
    "time"
)

// コンスタント定義を止め、time パッケージの定義( time.Monday 等 )を使用する
// const (
//     MONDAY = 0
//     TUESDAY
//     WEDNESDAY
// )


func Main() {
}

// 整数で年を与えると、その年の春分の日が3月の何日であるかを返す
func VernalEquinox(y int) int {
    d := 0

    if y <= 1947 {
        d = 99      // 祝日法施行前
    } else if y <= 1979 {
        d = int(math.Floor(20.8357 + 0.242194 * float64(y - 1980) - math.Floor(float64(y - 1980) / 4.0)))
    } else if y <= 2099 {
        d = int(math.Floor(20.8431 + 0.242194 * float64(y - 1980) - math.Floor(float64(y - 1980) / 4.0)))
    } else if y <= 2150 {
        d = int(math.Floor(21.8510 + 0.242194 * float64(y - 1980) - math.Floor(float64(y - 1980) / 4.0)))
    } else {
        d = 99      // 2151年以降は略算式が無いので不明
    }

    return d
}

// 整数で年を与えると、その年の秋分の日が9月の何日であるかを返す
func AutumnEquinox(y int) int {
    d := 0

    if y <= 1947 {
        d = 99      // 祝日法施行前
    } else if y <= 1979 {
        d = int(math.Floor(23.2588 + 0.242194 * float64(y - 1980) - math.Floor(float64(y - 1980) / 4.0)))
    } else if y <= 2099 {
        d = int(math.Floor(23.2488 + 0.242194 * float64(y - 1980) - math.Floor(float64(y - 1980) / 4.0)))
    } else if y <= 2150 {
        d = int(math.Floor(24.2488 + 0.242194 * float64(y - 1980) - math.Floor(float64(y - 1980) / 4.0)))
    } else {
        d = 99      // 2151年以降は略算式が無いので不明
    }

    return d
}

// GetHolidayName() の呼び出し方法は2通りあります。
// 1つ目の方法は、3つの引数 Year, Month, Day に整数を渡したParamsを渡す方法です。
// もうひとつの方法は引数 Date に time.Date のオブジェクトを渡す方法です。
// この場合は Year, Month, Day を渡す必要はなく、また、渡したとしても無視されます。
// GetHolidayName() は、その日が祝日であれば祝日名を返します。
// 指定した日が祝日でなければ、 "" を返します。


// year = nil, month = nil, day = nil, p.Date = nil
type Params struct {
    Year  int
    Month time.Month
    Day  int
    Date  time.Time
}

func GetHolidayName(p Params) string {
    name := ""
    //if p.Date == nil {
    now := time.Now()

    // [ Date ]引数が省略された場合は [ Year, Month, Day ]引数で日付を作成し [ Date ]引数を差し替える。
    if p.Date.IsZero() {
        // func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
        p.Date = time.Date(p.Year, p.Month, p.Day, 0, 0, 0, 0, now.Location())
    }

    //if p.Date < time.Date(1948, 7, 20, 0, 0, 0, 0, now.Location()) {
    if p.Date.Sub(time.Date(1948, 7, 20, 0, 0, 0, 0, now.Location())) < 0 {
        return ""    // 祝日法 施行以前
    } else {
        name = ""    // name の初期値は[ "" ]
    }

    //-- 1月 --
    if p.Date.Month() == time.January {
        if p.Date.Day() == 1 {
            name = "元日"
        } else {
            if p.Date.Year() >= 2000 {
                if int((p.Date.Day() - 1) / 7) == 1 && p.Date.Weekday() == time.Monday {    // 2nd Monday
                    name = "成人の日"
                }
            } else {
                if p.Date.Day() == 15 {
                    name = "成人の日"
                }
            }
        }

    //-- 2月 --
    } else if p.Date.Month() == time.February {
        if p.Date.Day() == 11 && p.Date.Year() >= 1967 {
            name = "建国記念の日"
        } else if p.Date.Day() == 23 && p.Date.Year() >= 2020 {
            name = "天皇誕生日"
        } else if p.Date.Year() == 1989 && p.Date.Month() == 2 && p.Date.Day() == 24 {
            name = "昭和天皇の大喪の礼"
        }

    //-- 3月 --
    }  else if p.Date.Month() == time.March {
        if p.Date.Day() == VernalEquinox(p.Date.Year()) {    // 1948〜2150以外は[99]が返るので、必ず≠になる
            name = "春分の日"
        }

    //-- 4月 --
    } else if p.Date.Month() == time.April {
        if p.Date.Day() == 29 {
            if p.Date.Year() >= 2007 {
                name = "昭和の日"
            } else if p.Date.Year() >= 1989 {
                name = "みどりの日"
            } else {
                name = "天皇誕生日// 昭和天皇
            }
        } else if p.Date.Year() == 1959 && p.Date.Month() == 4 && p.Date.Day() == 10 {
            name = "皇太子明仁親王の結婚の儀"
        }

    //-- 5月 --
    } else if p.Date.Month() == time.May {
        if p.Date.Day() == 3 {
            name = "憲法記念日"
        } else if p.Date.Day() == 4 {
            if p.Date.Year() >= 2007 {
                name = "みどりの日"
            } else if p.Date.Year() >= 1986 && p.Date.Weekday() > time.Monday {     // 火曜 以降(火〜土)
                name = "国民の休日"
            }
        } else if p.Date.Day() == 5 {
            name = "こどもの日"
        } else if p.Date.Day() == 6 {
            if p.Date.Year() >= 2007 && (p.Date.Weekday() == time.Tuesday || p.Date.Weekday() == time.Wednesday) {
                name = "振替休日"     // [5/3,5/4が日曜]ケースのみ、ここで判定
            }
        }

    //-- 6月 --
    } else if p.Date.Month() == time.June {
        if p.Date.Year() == 1993 && p.Date.Month() == 6 && p.Date.Day() == 9 {
            name = "皇太子徳仁親王の結婚の儀"
        }

    //-- 7月 --
    } else if p.Date.Month() == time.July {
        if p.Date.Year() >= 2021 {
            if int((p.Date.Day() - 1) / 7) == 2 && p.Date.Weekday() == time.Monday {    // 3rd Monday
                name = "海の日"
            }
        } else if p.Date.Year() == 2020 {
            // 2020年はオリンピック特措法により
            //「海の日」が 7/23 , 「スポーツの日」が 7/24 に移動
            if p.Date.Day() == 23 {
                name = "海の日"
            } else if p.Date.Day() == 24 {
                name = "スポーツの日"
            }
        } else if p.Date.Year() >= 2003 {
            if int((p.Date.Day() - 1) / 7) == 2 && p.Date.Weekday() == time.Monday {    // 3rd Monday
                name = "海の日"
            }
        } else if p.Date.Year() >= 1996 {
            if p.Date.Day() == 20 {
                name = "海の日"
            }
        }

    //-- 8月 --
    } else if p.Date.Month() == time.August {
        if p.Date.Year() >= 2021 {
            if p.Date.Day() == 11 {
                name = "山の日"
            }
        } else if p.Date.Year() == 2020 {
            // 2020年はオリンピック特措法により「山の日」が 8/10 に移動
            if p.Date.Day() == 10 {
                name = "山の日"
            }
        } else if p.Date.Year() >= 2016 {
            if p.Date.Day() == 11 {
                name = "山の日"
            }
        }

    //-- 9月 --
    } else if p.Date.Month() == time.September {
        autumn_equinox := AutumnEquinox(p.Date.Year())
        if p.Date.Day() == autumn_equinox {    // 1948〜2150以外は[99]が返るので、必ず≠になる
            name = "秋分の日"
        } else if p.Date.Year() >= 2003 {
            if (int((p.Date.Day() - 1) / 7.0) == 2) && p.Date.Weekday() == time.Monday {    // 3rd Monday
                name = "敬老の日"
            } else if p.Date.Weekday() == time.Tuesday && p.Date.Day() == (autumn_equinox - 1) {
                name = "国民の休日"     // 火曜日&[秋分日の前日]
            } else if p.Date.Year() >= 1966 && p.Date.Day() == 15 {
                name = "敬老の日"
            }
        }

    //-- 10月 --
    } else if p.Date.Month() == time.October {
        if p.Date.Year() >= 2021 {
            if (int((p.Date.Day() - 1) / 7.0) == 1) && p.Date.Weekday() == time.Monday {    // 2nd Monday
                name = "スポーツの日"    // 2020年より改名
            }
        } else if p.Date.Year() == 2020 {
            // 2020年はオリンピック特措法により「スポーツの日」が 7/24 に移動
        } else if p.Date.Year() >= 2000 {
            if (int((p.Date.Day() - 1) / 7.0) == 1) && p.Date.Weekday() == time.Monday {    // 2nd Monday
                name = "体育の日"
            }
        } else if p.Date.Year() >= 1966 {
            if p.Date.Day() == 10 {
                name = "体育の日"
            }
        }

    //-- 11月 --
    } else if p.Date.Month() == time.November {
        if p.Date.Day() == 3 {
            name = "文化の日"
        } else if p.Date.Day() == 23 {
            name = "勤労感謝の日"
        } else if p.Date.Year() == 1990 && p.Date.Month() == 11 && p.Date.Day() == 12 {
            name = "即位礼正殿の儀// 平成天皇
        }

    //-- 12月 --
    }  else if p.Date.Month() == time.December {
        if p.Date.Day() == 23 && p.Date.Year() >= 1989 && p.Date.Year() <= 2018 {
            name = "天皇誕生日// 平成天皇
        }
    }

    // ----- 振替休日の判定 (振替休日施行日:1973/4/12) -----
    // [ 対象日≠祝日/休日 & 対象日=月曜日 ]のみ、前日(=日曜日)を祝日判定する。
    // 前日(=日曜日)が祝日の場合は”振替休日”となる。
    // 尚、5月6日の扱いを
    //     「火曜 or 水曜(みどりの日(5/4) or 憲法記念日(5/3)の振替休日)」⇒5月ブロック内で判定済
    //     「月曜(こどもの日(5/5)の振替休日」⇒ここの判定処理で判定
    // とする事により、ここでの判定対象は『対象日が月曜日』のみ となります。

    if (name == "") && (p.Date.Weekday() == time.Monday)
        && (p.Date.Sub(time.Date(1973, 4, 12, 0, 0, 0, 0, now.Location())) >= 0) {
        prev := p.Date.AddDate(0, 0, -1)  // 1日前
        params := Params{Year:prev.Year(), Month:prev.Month(), Day:prev.Day(), Date:time.Time{}}
        if GetHolidayName(params) != "" {
            name = "振替休日"
        }
    }

    return name
}








角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2010 Allrights Reserved.