前提・実現したいこと
課題で2020年から2025年までの間の営業日カレンダーを作成したいのですがうまくいきません。
【条件】 ・指定範囲内の正しい日付なら経過日および営業日を計算する。 ただし結果が 2020 年から 2025 年までの範囲から外れるときは、値が正しくなくても良い。例外が発生してもよい。 ・指定範囲外または存在しない日付なら「x 年 x 月 x 日は指定条件を満たしていません。」と表示して処理を終了する。 ・間隔を表す引数に負の数を指定すると過去の日付と営業日を出力するようにする。 ・間隔を表す引数に 0 を指定すると、指定日が営業日でなくても指定日をそのまま出力する。 ・休みは通常のカレンダーに 12 月 29 日から翌年の 1 月 3 日までの年末年始の休みを加えたものとすること。 ・2020 年はオリンピックに関連しての休日の特例が適用されたが、この特例は無いものとして計算すること。 また 2021 年以降に法律が改正され特例または恒久的に休日が設定されても、 それは無視してそのような休日は無いものと考えて計算すること。
コンパイルはできるのですが、実行すると以下のようなエラーがでてしまいます。
色々と調べてみたり修正してみたりはしたのですが、当方の知識不足のため解決に至りませんでした。
どのようにエラーを解消すればよいかアドバイスをいただきたいです。
エラーメッセージ
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 12 at BusinessDayMulti.daysOfMonth(BusinessDayMulti.java:32) at BusinessDayMulti.getYYYYMMDD(BusinessDayMulti.java:84) at BusinessDayMulti.main(BusinessDayMulti.java:14)
該当のソースコード
java
1 2class BusinessDayMulti{ 3static final int BASIS_YEAR = 2020; // 起算年 4static final int LIMIT_YEAR = 2025; // 限界年 5static final int YOUBI_OF_BASIS = 3; // 起算年の初日の曜日(水曜日) 6public static void main(String[] args) { 7 int year = Integer.parseInt(args[0]); // 年の入力 8 int month = Integer.parseInt(args[1]); // 月の入力 9 int date = Integer.parseInt(args[2]); // 日の入力 10 int span = Integer.parseInt(args[3]); // 間隔の入力 11 if (checkDate(year, month, date)) { 12 // 年月日で与えた日付の起算日からの日数を得る 13 int days = elapsedDays(year, month, date); 14 // 起算日からの日数を与えその日付を YYYYMMDD 形式で得る 15 int eymd = getYYYYMMDD(days + span); 16 // days から span 日後の営業日付を YYYYMMDD 形式で得る 17 int bymd = getBusinessDay(days, span); 18 19 System.out.println(year + "年" + month + "月" + date + "日は起算日から" + days + "日目です。"); 20 String zengo = span < 0 ? "前" : "後"; 21 System.out.println(Math.abs(span) + "日" + zengo + "は" 22 + (eymd / 10000) + "年" + (eymd % 10000) / 100 + "月" 23 + (eymd % 100) + "日です。"); 24 System.out.println(Math.abs(span) + "営業日" + zengo + "は" 25 + (bymd / 10000) + "年" + (bymd % 10000) / 100 + "月" + (bymd % 100) + "日です。"); 26 } else { 27 System.out.println(year + "年" + month + "月" 28 + date + "日は指定条件を満たしていません。"); 29 } 30 } 31static int daysOfMonth(int year, int month) { 32 int[] DAYS_OF_MONTH = {31,28,31,30,31,30,31,31,30,31,30,31}; 33 int day = DAYS_OF_MONTH[month-1]; 34 if (year % 4==0 && month==2){ 35 if(year % 100!=0 && month==2){ 36 day++; 37 if (year % 400==0 && month==2){ 38 day++; //閏年なので1加算 39 }else{ 40 } 41} 42 43} 44 return day; 45} 46 47 48 // 指定月日が存在すれば true を返す 49 static boolean checkDate(int year,int month, int date) { 50 if (year<2020 || 2025<year)return false; 51 if (month < 1 || 12 < month) return false; 52 if (date < 1) return false; 53 if (month == 1 && date <=31) return true; 54 if (month == 2 && date <=28) return true; 55 if (month == 2 && date <=29 && year % 4==0 && year % 100!=0 || year % 400==0)return true; 56 if (month == 3 && date <=31) return true; 57 if (month == 4 && date <=30) return true; 58 if (month == 5 && date <=31) return true; 59 if (month == 6 && date <=30) return true; 60 if (month == 7 && date <=31) return true; 61 if (month == 8 && date <=31) return true; 62 if (month == 9 && date <=30) return true; 63 if (month == 10 && date <=31) return true; 64 if (month == 11 && date <=30) return true; 65 if (month == 12 && date <=31) return true; 66 return false; 67 } 68 69 70 // 1 月 1 日からの経過日数 71 static int elapsedDays(int year,int month,int date){ 72 int dYear = year-BASIS_YEAR; //起算年との差 73 int days = dYear * 365+((dYear+3)/4)-((dYear+3)/100)+((dYear+3)/400); //閏年補正 74 for (int m = 1 ; m<month;m++){ 75 days += daysOfMonth(year,m); 76 } 77 return days+date-1; 78 } 79 80 // 1 月 1 日から指定日数後の日付 81 static int getYYYYMMDD(int days) { 82 days++; // 0 日目は 1 日なので+1 する 83 int year=0; 84 int month = 0; 85 while(daysOfMonth(year,month)<days){ 86 days -= daysOfMonth(year++,month++); 87 } 88 if (month>12){ 89 year = 2020+(month-12); 90 }else{ 91 return year; 92 } 93 return year + (month + 1) * 100 + days; 94 } 95 96 // 1 月 1 日からの経過日数 days から間隔日数 span 日後の営業日 97 static int getBusinessDay(int days, int span) { 98 for (int i = 0; i < span; ) { 99 days++; 100 if (isWeekend(days)) continue; 101 if (isTotalHoliday(getYYYYMMDD(days))) continue; 102 i++; 103 } 104 return getYYYYMMDD(days+span); 105 106 } 107 108 // 週末判定 109 static boolean isWeekend(int days) { 110 if ((days + YOUBI_OF_BASIS) % 7 == 0) return true; 111 if ((days + YOUBI_OF_BASIS) % 7 == 6) return true; 112 return false; 113 } 114 115//休日判定呼び出し 116 static boolean isTotalHoliday(int yyyymmdd) { 117 int year=0; 118 int month=0; 119 int date=0; 120 if (isNationalHoliday(year, month, date)) return true; 121 if (isFurikaeHoliday(year, month, date)) return true; 122 if (isOtherHoliday(month, date)) return true; 123 return false; 124 } 125 // 普通の休日判定 126 static boolean isNationalHoliday(int year, int month, int date) { 127 int[] FIX_HOLIDAYS = {101, 211, 223, 429, 503, 504, 505, 811, 1103, 1123,}; 128 int mmdd = month * 100 + date; 129 for (int holiday: FIX_HOLIDAYS) { 130 if (holiday == mmdd) return true; 131 } 132 if (isHappyMonday(year, month, date)) return true; 133 if (isEquinox(year, month, date)) return true; return false; 134 } 135 //ハッピーマンデー 136 static boolean isHappyMonday(int year, int month, int date) { 137 int[] HAPPY_MONDAYS = {102, 703, 903, 1002,}; 138 int youbiOfFirstDay = (elapsedDays(year, month, 1) + YOUBI_OF_BASIS) % 7; 139 for (int mmnn: HAPPY_MONDAYS) { 140 if (mmnn / 100 != month) continue; 141 int n = mmnn % 100; 142 int happyMonday = (8 - youbiOfFirstDay) % 7 + n * 7 - 6; 143 if (date == happyMonday) return true; 144 } 145 return false; 146 } 147 //春分の日、秋分の日 148 static boolean isEquinox(int year,int month, int date) { 149 int[][] EQUINOX = {{320, 922},{320, 923},{321, 923},{321, 923}}; 150 int mmdd = month * 100 + date; 151 for (int equinox: EQUINOX[year % 4]) { 152 if (equinox == mmdd) return true; 153 } 154 return false; 155 } 156 157 158 //振替休日 159 static boolean isFurikaeHoliday(int year, int month, int date) { 160 int[] MULTI_SHIFT = {2020, 2025, 2026}; 161 for (int shift_year: MULTI_SHIFT) { 162 if (year == shift_year && month == 5 && date == 6) return true; 163 } 164 int youbi = (elapsedDays(year, month, date) + YOUBI_OF_BASIS) % 7; 165 if (youbi != 1) return false; // 月曜でなけれは非該当 166 return isNationalHoliday(year, month, date - 1); // 前日が祝日なら休日 167 } 168 169 //そのほかの休日 170 static boolean isOtherHoliday(int month, int date) { 171 int[] OTHER_HOLIDAYS = {101,102,103,1229,1230,1231,}; 172 int mmdd = month * 100 + date; 173 for (int holiday: OTHER_HOLIDAYS) { 174 if (holiday == mmdd) return true; 175 } 176 return false; 177 } 178 179 180 } 181
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。