1
2
3
4
5
6
7
8
9
10
11 package de.jaret.util.date.holidayenumerator;
12
13 import java.util.ArrayList;
14 import java.util.Calendar;
15 import java.util.Date;
16 import java.util.GregorianCalendar;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Locale;
20 import java.util.Map;
21
22
23
24
25
26
27
28
29
30
31 public abstract class HolidayEnumeratorBase implements HolidayEnumerator {
32
33 protected Map<Integer, Map<Integer, Map<Integer, NamedDate>>> _yearMap = new HashMap<Integer, Map<Integer, Map<Integer, NamedDate>>>();
34
35 protected static final Calendar CALENDAR = new GregorianCalendar();
36
37 protected Locale _locale;
38
39 protected String _regionId;
40
41
42
43
44
45
46
47
48
49
50 protected abstract void fillMap(int year);
51
52
53
54
55 public String[] getAvailableRegionIds() {
56 return new String[0];
57 }
58
59
60
61
62 public String toString() {
63 return _regionId != null ? _regionId : "NONE";
64 }
65
66
67
68
69 public boolean equals(Object obj) {
70 if (obj == null) {
71 return false;
72 }
73 if (!(obj instanceof HolidayEnumerator)) {
74 return false;
75 }
76 HolidayEnumerator he = (HolidayEnumerator) obj;
77
78 if (!_locale.equals(he.getLocale())) {
79 return false;
80 }
81 if (_regionId == null && he.getRegionId() == null) {
82 return true;
83 }
84 if (_regionId != null) {
85 return _regionId.equals(he.getRegionId());
86 }
87 if (he.getRegionId() != null) {
88 return he.getRegionId().equals(_regionId);
89 }
90 return false;
91 }
92
93 @Override
94 public int hashCode() {
95 return _locale.hashCode() + 13 * (_regionId != null ? _regionId.hashCode() : 0);
96 }
97
98
99
100
101 protected void init() {
102 _yearMap = new HashMap<Integer, Map<Integer, Map<Integer, NamedDate>>>();
103 }
104
105 private NamedDate getNamedDate(int year, int month, int day) {
106 if (_yearMap == null) {
107 init();
108 }
109 Map<Integer, Map<Integer, NamedDate>> yMap = _yearMap.get(year);
110 if (yMap == null) {
111 fillMap(year);
112 yMap = _yearMap.get(year);
113 }
114 Map<Integer, NamedDate> mMap = yMap.get(month);
115 if (mMap != null) {
116 return mMap.get(day);
117 }
118 return null;
119 }
120
121
122
123
124
125
126
127
128
129
130 protected void addNamedDate(int year, int month, int day, boolean isHoliday, String name) {
131 Map<Integer, Map<Integer, NamedDate>> yMap = _yearMap.get(year);
132 if (yMap == null) {
133 yMap = new HashMap<Integer, Map<Integer, NamedDate>>();
134 _yearMap.put(year, yMap);
135 }
136 Map<Integer, NamedDate> mMap = yMap.get(month);
137 if (mMap == null) {
138 mMap = new HashMap<Integer, NamedDate>();
139 yMap.put(month, mMap);
140 }
141 Date date = getDate(year, month, day, 0);
142 NamedDate namedDate = new NamedDateImpl(date, name, isHoliday);
143 mMap.put(day, namedDate);
144 }
145
146 protected void addNamedDate(int year, int month, int day, int dayOffset, boolean isHoliday, String name) {
147 Date date = getDate(year, month, day, dayOffset);
148 EasyDate ed = new EasyDate(date);
149 year = ed.year;
150 month = ed.month;
151 day = ed.day;
152 addNamedDate(year, month, day, isHoliday, name);
153 }
154
155 protected void addNamedDate(EasyDate ed, boolean isHoliday, String name) {
156 int year = ed.year;
157 int month = ed.month;
158 int day = ed.day;
159 addNamedDate(year, month, day, isHoliday, name);
160 }
161
162 protected Date getDate(int year, int month, int day, int dayOffset) {
163 CALENDAR.set(Calendar.YEAR, year);
164 CALENDAR.set(Calendar.MONTH, month);
165 CALENDAR.set(Calendar.DAY_OF_MONTH, day);
166 CALENDAR.set(Calendar.HOUR_OF_DAY, 0);
167 CALENDAR.set(Calendar.MINUTE, 0);
168 CALENDAR.set(Calendar.SECOND, 0);
169 CALENDAR.set(Calendar.MILLISECOND, 0);
170
171 CALENDAR.add(Calendar.DAY_OF_YEAR, dayOffset);
172 return CALENDAR.getTime();
173 }
174
175 protected int getWeekday(Date date) {
176 CALENDAR.setTime(date);
177 return CALENDAR.get(Calendar.DAY_OF_WEEK);
178 }
179
180
181
182
183 public boolean isHoliday(Date date) {
184 EasyDate ed = new EasyDate(date);
185 NamedDate d = getNamedDate(ed.year, ed.month, ed.day);
186
187 if (d == null) {
188 return false;
189 }
190 return d.isHoliday();
191 }
192
193
194
195
196 public boolean isSpecialDay(Date date) {
197 EasyDate ed = new EasyDate(date);
198 NamedDate d = getNamedDate(ed.year, ed.month, ed.day);
199 if (d == null) {
200 return false;
201 }
202 return !d.isHoliday();
203 }
204
205
206
207
208 public String getDayName(Date date) {
209 EasyDate ed = new EasyDate(date);
210 NamedDate d = getNamedDate(ed.year, ed.month, ed.day);
211 if (d == null) {
212 return null;
213 }
214 return d.getName();
215 }
216
217
218
219
220 public Locale getLocale() {
221 return _locale;
222 }
223
224
225
226
227 public void setLocale(Locale locale) {
228 _locale = locale;
229 init();
230 }
231
232
233
234
235 public String getRegionId() {
236 return _regionId;
237 }
238
239
240
241
242 public void setRegionId(String regionId) {
243 _regionId = regionId;
244 init();
245 }
246
247
248
249
250 public List<NamedDate> getNamedDays(int year, boolean includeSpecialDays) {
251 List<NamedDate> result = new ArrayList<NamedDate>();
252 for (int month = 0; month < 12; month++) {
253 result.addAll(getNamedDays(year, month, includeSpecialDays));
254 }
255 return result;
256 }
257
258
259
260
261 public List<NamedDate> getNamedDays(int year, int month, boolean includeSpecialDays) {
262 List<NamedDate> result = new ArrayList<NamedDate>();
263 if (_yearMap == null) {
264 init();
265 }
266 Map<Integer, Map<Integer, NamedDate>> yMap = _yearMap.get(year);
267 if (yMap == null) {
268 fillMap(year);
269 yMap = _yearMap.get(year);
270 }
271 Map<Integer, NamedDate> mMap = yMap.get(month);
272 if (mMap != null) {
273 for (Integer day : mMap.keySet()) {
274 NamedDate d = mMap.get(day);
275 if (d.isHoliday() || includeSpecialDays) {
276 result.add(d);
277 }
278 }
279
280 }
281 return result;
282 }
283
284
285
286
287
288
289
290
291
292 public EasyDate calcEaster(int year) {
293 if (year < 1583 || year > 2499) {
294 throw new IllegalArgumentException("Valid input from 1583 to 2499");
295 }
296 int jahr = year;
297 int monat = -1;
298 int tag = -1;
299 int M = 0;
300 int N = 0;
301 if (1583 <= jahr && jahr <= 1699) {
302 M = 22;
303 N = 2;
304 } else if (1700 <= jahr && jahr <= 1799) {
305 M = 23;
306 N = 3;
307 } else if (1800 <= jahr && jahr <= 1899) {
308 M = 23;
309 N = 4;
310 } else if (1900 <= jahr && jahr <= 2099) {
311 M = 24;
312 N = 5;
313 } else if (2100 <= jahr && jahr <= 2199) {
314 M = 24;
315 N = 6;
316 } else if (2200 <= jahr && jahr <= 2299) {
317 M = 25;
318 N = 0;
319 } else if (2300 <= jahr && jahr <= 2499) {
320 M = 26;
321 N = 1;
322 } else if (2400 <= jahr && jahr <= 2499) {
323 M = 25;
324 N = 1;
325 }
326 int a = jahr % 19;
327 int b = jahr % 4;
328 int c = jahr % 7;
329 int d = (19 * a + M) % 30;
330 int e = (2 * b + 4 * c + 6 * d + N) % 7;
331
332 if ((d + e) <= 9) {
333 int easter = 22 + d + e;
334 monat = 2;
335 tag = easter;
336 } else if ((d + e) > 9) {
337 if (d + e - 9 == 26) {
338 int easter = 19;
339 monat = 3;
340 tag = easter;
341 } else if ((d + e - 9) == 25 && d == 28 && a > 10) {
342 int easter = 18;
343 monat = 3;
344 tag = easter;
345 } else {
346 int easter = d + e - 9;
347 monat = 3;
348 tag = easter;
349 }
350 }
351 if (monat == -1) {
352 throw new RuntimeException("??? Error in easter calculation");
353 }
354 return new EasyDate(jahr, monat, tag);
355 }
356
357
358
359
360
361
362
363
364
365
366 public EasyDate nThWeekdayInMonth(int year, int month, int weekday, int nTh) {
367 if (nTh > 4 || nTh < 0) {
368 throw new IllegalArgumentException("nTh must be within 1..4");
369 }
370 EasyDate result = null;
371 int i = 0;
372 int n = 0;
373 int daysInMonth = daysInMonth(year, month);
374 while (i < daysInMonth && result == null) {
375 Date d = getDate(year, month, 1, i);
376 if (getWeekday(d) == weekday) {
377 n++;
378 if (n == nTh) {
379 result = new EasyDate(d);
380 }
381 }
382 i++;
383 }
384 return result;
385 }
386
387
388
389
390
391
392
393
394
395 public EasyDate lastWeekdayInMonth(int year, int month, int weekday) {
396 EasyDate result = null;
397 int i = 0;
398 int daysInMonth = daysInMonth(year, month);
399 while (i < daysInMonth) {
400 Date d = getDate(year, month, 1, i);
401 if (getWeekday(d) == weekday) {
402 result = new EasyDate(d);
403 }
404 i++;
405 }
406 return result;
407 }
408
409
410
411
412
413
414
415
416 public EasyDate fridayOrMonday(EasyDate ed) {
417 if (getWeekday(ed.date) == Calendar.SATURDAY) {
418 return new EasyDate(getDate(ed.year, ed.month, ed.day, -1));
419 } else if (getWeekday(ed.date) == Calendar.SUNDAY) {
420 return new EasyDate(getDate(ed.year, ed.month, ed.day, 1));
421 } else {
422 return null;
423 }
424 }
425
426 protected int daysInMonth(int year, int month) {
427 Date d = getDate(year, month, 1, 0);
428 CALENDAR.setTime(d);
429 return CALENDAR.getMaximum(Calendar.DAY_OF_MONTH);
430 }
431
432 public EasyDate getEasyDate(int year, int month, int day) {
433 return new EasyDate(year, month, day);
434 }
435
436
437
438
439
440
441
442 public class EasyDate {
443 public int year;
444 public int month;
445 public int day;
446 public Date date;
447
448 public EasyDate(int year, int month, int day) {
449 this.year = year;
450 this.month = month;
451 this.day = day;
452 this.date = getDate(year, month, day, 0);
453 }
454
455 public EasyDate(Date date) {
456 CALENDAR.setTime(date);
457 this.date = date;
458 year = CALENDAR.get(Calendar.YEAR);
459 month = CALENDAR.get(Calendar.MONTH);
460 day = CALENDAR.get(Calendar.DAY_OF_MONTH);
461 }
462
463 public boolean equals(int year, int month, int day) {
464 return year == this.year && month == this.month && day == this.day;
465 }
466
467 }
468
469
470
471
472
473
474
475 public class NamedDateImpl implements NamedDate, Comparable<NamedDate> {
476 private String _name;
477 private Date _date;
478 private boolean _holiday;
479
480 public NamedDateImpl(Date date, String name, boolean holiday) {
481 if (date == null) {
482 throw new RuntimeException("date may not be null");
483 }
484 _date = date;
485 _name = name;
486 _holiday = holiday;
487 }
488
489
490
491
492 public String getName() {
493 return _name;
494 }
495
496
497
498
499 public Date getDate() {
500 return _date;
501 }
502
503
504
505
506 public boolean isHoliday() {
507 return _holiday;
508 }
509
510
511
512
513 public boolean equals(Object obj) {
514 return _date.equals(obj);
515 }
516
517
518
519
520 public int hashCode() {
521 return _date.hashCode();
522 }
523
524
525
526
527 public String toString() {
528 return "NamedDateImpl[date=" + _date + ";name=" + _name + ";isHoliday=" + _holiday + "]";
529 }
530
531
532
533
534 public int compareTo(NamedDate date) {
535 return _date.compareTo((date.getDate()));
536 }
537 }
538 }