2019年12月15日日曜日

[MT4]日本の祝日判定(令和版)

以前のブログで祝日判定のコードを挙げていましたが来年から天皇誕生日が変わるので修正します。
つい自分でも祝日(特に海外の)を忘れがちなので、MT4向けに祝日表示インジケータ作ってアップしますのでしばらくお待ちください。

さしあたりコードだけ。


   MqlDateTime dt;
   TimeToStruct(japanTime, dt);
   
   //土日
   if(dt.day_of_week == SUNDAY || dt.day_of_week == SATURDAY ) return "休日";
   

   //春分の日、秋分の日計算用
   int yearMod = dt.year % 4;

   switch(dt.mon)
   {
      //1月
      case 1:
         //正月三が日
         if(dt.day == 1 || dt.day == 2 || dt.day == 3) return "正月三が日";
         
         //成人の日 1/15
         if(dt.year < 2000 && dt.day == 15 ) return "成人の日"; 
         if(dt.year < 2000 && dt.day == 16 && dt.day_of_week == MONDAY ) return "成人の日(振替)"; 

         //成人の日 第2月曜日
         if(2000 <= dt.year && dt.day_of_week == MONDAY && ( 8 <= dt.day && dt.day <= 14 )) return "成人の日"; 
         break;
         
      //2月
      case 2:
         //建国記念日 2/11
         if(dt.day == 11 ) return "建国記念日";
         if(dt.day == 12 && dt.day_of_week == MONDAY ) return "建国記念日(振替)";
         // 天皇誕生日 
         if( 2020 <= dt.year && dt.day == 23 ) return "天皇誕生日";
         if( 2020 <= dt.year && dt.day == 24 && dt.day_of_week == MONDAY ) return "天皇誕生日(振替)";

         break;

      //3月
      case 3:
         //春分の日 3/19~3/21までのどこか。 1980~2088年まで
         if( yearMod == 0 )
         {
            if( dt.day == 20 ) return "春分の日";
            if( dt.day == 21 && dt.day_of_week == MONDAY ) return "春分の日(振替)";
         }
         if( yearMod == 1 )
         {
            if( dt.year <= 1989 && dt.day == 21 ) return "春分の日";
            if( dt.year <= 1989 && dt.day == 22 && dt.day_of_week == MONDAY ) return "春分の日(振替)";
            if( 1993 <= dt.year && dt.day == 20 ) return "春分の日";
            if( 1993 <= dt.year && dt.day == 21 && dt.day_of_week == MONDAY ) return "春分の日(振替)";
         }
         if( yearMod == 2 )
         {
            if( dt.year <= 2022 && dt.day == 21 ) return "春分の日";
            if( dt.year <= 2022 && dt.day == 22 && dt.day_of_week == MONDAY ) return "春分の日(振替)";
            if( 2026 <= dt.year && dt.day == 20 ) return "春分の日";
            if( 2026 <= dt.year && dt.day == 21 && dt.day_of_week == MONDAY ) return "春分の日(振替)";
         }
         if( yearMod == 3 )
         {
            if( dt.year <= 2055 && dt.day == 21 ) return "春分の日";
            if( dt.year <= 2055 && dt.day == 22 && dt.day_of_week == MONDAY ) return "春分の日(振替)";
            if( 2059 <= dt.year && dt.day == 20 ) return "春分の日";
            if( 2059 <= dt.year && dt.day == 21 && dt.day_of_week == MONDAY ) return "春分の日(振替)";
         }
         break;
    
      //4月
      case 4:
         // 天皇誕生日・みどりの日・昭和の日 4/29
         if( dt.year && dt.day == 29 ) return "昭和の日";
         if( dt.year && dt.day == 30 && dt.day_of_week == MONDAY ) return "昭和の日(振替)";
         break;

      //5月         
      case 5:
         // 憲法記念日 5/3
         if( dt.day == 3 ) return "憲法記念日";
         // みどりの日・国民の休日 5/4
         if( dt.day == 4 ) return "みどりの日";
         // こどもの日 5/5
         if( dt.day == 5 ) return "こどもの日";

         // 6日が月曜日の場合のみ、振り替え休日が発生する。
         if( dt.year < 2007 && dt.day == 6 && dt.day_of_week == MONDAY) return "こどもの日(振替)";
         // 6日が月曜日~水曜日の場合、5/3~5/5いずれかの振替になる。
         if( 2007 <= dt.year && dt.day == 6 &&  dt.day_of_week == MONDAY ) return "こどもの日(振替)";
         // 6日が月曜日~水曜日の場合、5/3~5/5いずれかの振替になる。
         if( 2007 <= dt.year && dt.day == 6 &&  dt.day_of_week == TUESDAY ) return "みどりの日(振替)";
         // 6日が月曜日~水曜日の場合、5/3~5/5いずれかの振替になる。
         if( 2007 <= dt.year && dt.day == 6 &&  dt.day_of_week == WEDNESDAY ) return "憲法記念日(振替)";

         break;

      //6月         
      case 6:
         break;
         
      case 7:
         // 海の日 7/20 1996年より
         if( 1996 <= dt.year && dt.year < 2003 && dt.day == 20 ) return "海の日";
         if( 1996 <= dt.year && dt.year < 2003 && dt.day == 21 && dt.day_of_week == MONDAY) return "海の日(振替)";
         // 海の日 第3月曜日
         if( 2003 <= dt.year && dt.day_of_week == MONDAY && ( 15 <= dt.day && dt.day <= 21 )) return "海の日"; 
         break;
      case 8:
         // 山の日 2016年より 8/11
         if( 2016 <= dt.year && dt.day == 11 ) return "山の日";
         if( 2016 <= dt.year && dt.day == 12 && dt.day_of_week == MONDAY ) return "山の日(振替)";
         break;
         
      case 9:
         // 敬老の日 9/15
         if( dt.year < 2003 && dt.day == 15 ) return "敬老の日";
         if( dt.year < 2003 && dt.day == 16  && dt.day_of_week == MONDAY) return "敬老の日(振替)";
         // 敬老の日 第3月曜日
         if( 2003 <= dt.year && dt.day_of_week == MONDAY && ( 15 <= dt.day && dt.day <= 21 )) return "敬老の日"; 
         
         //秋分の日 3/19~3/21までのどこか。 1980~2088
         if( yearMod == 0 )
         {
            if( dt.year <= 2008 && dt.day == 23 ) return "秋分の日";
            if( dt.year <= 2008 && dt.day == 24 && dt.day_of_week == MONDAY ) return "秋分の日(振替)";
            if( 2012 <= dt.year && dt.day == 22 ) return "秋分の日";
            if( 2012 <= dt.year && dt.day == 23 && dt.day_of_week == MONDAY ) return "秋分の日(振替)";
         }
         if( yearMod == 1 )
         {
            if( dt.year <= 2041 && dt.day == 23 ) return "秋分の日";
            if( dt.year <= 2041 && dt.day == 24 && dt.day_of_week == MONDAY ) return "秋分の日(振替)";
            if( 2045 <= dt.year && dt.day == 22 ) return "秋分の日";
            if( 2045 <= dt.year && dt.day == 23 && dt.day_of_week == MONDAY ) return "秋分の日(振替)";
         }
         if( yearMod == 2 )
         {
            if( dt.year <= 2074 && dt.day == 23 ) return "秋分の日";
            if( dt.year <= 2074 && dt.day == 24 && dt.day_of_week == MONDAY ) return "秋分の日(振替)";
            if( 2078 <= dt.year && dt.day == 22 ) return "秋分の日";
            if( 2078 <= dt.year && dt.day == 23 && dt.day_of_week == MONDAY ) return "秋分の日(振替)";
         }
         if( yearMod == 3 )
         {
            if( dt.day == 23 ) return "秋分の日";
            if( dt.day == 24 && dt.day_of_week == MONDAY ) return "秋分の日(振替)";
         }         
         
         // 国民の休日 ※祝日と祝日の間に挟まれた平日 あと一個できたらロジック化
         if( dt.day == 21 && (dt.year == 2032 || dt.year == 2049 || dt.year == 2060 || dt.year == 2088)) return "国民の休日";
         if( dt.day == 22 && (dt.year == 2009 || dt.year == 2015 || dt.year == 2026 || dt.year == 2037 || dt.year == 2043 || dt.year == 2054 || dt.year == 2071)) return "国民の休日";
         break;
     // 10月
     case 10:
         // 体育の日 10/10
         if( dt.year < 2000 && dt.day == 10 ) return "体育の日";
         if( dt.year < 2000 && dt.day == 11 && dt.day_of_week == MONDAY ) return "体育の日(振替)";
     
         // 体育の日 第2月曜日
         if( 2000 <= dt.year  && dt.day_of_week == MONDAY && ( 8 <= dt.day && dt.day <= 14 )) return "体育の日"; 

         break;
     // 11月
     case 11:
         // 文化の日 11/3
         if( dt.day == 3 ) return "文化の日";
         if( dt.day == 4 && dt.day_of_week == MONDAY ) return "文化の日(振替)" ;

         // 勤労感謝の日 11/23
         if( dt.day == 23 ) return "勤労感謝の日";
         if( dt.day == 24 && dt.day_of_week == MONDAY ) return "勤労感謝の日(振替)";

         break;
         
     // 12月
     case 12:
         // 平成天皇誕生日の日 12/23
         if( 1989 <= dt.year && dt.year <= 2018 && dt.day == 23 ) return "平成天皇誕生日";
         if( 1989 <= dt.year && dt.year <= 2018 && dt.day == 24 && dt.day_of_week == MONDAY ) return "平成天皇誕生日(振替)";

         // 大晦日
         if( dt.day == 31 ) return "大晦日";
         break;
   }
   return "";