1
2
3
4 package de.powerstat.validation.values;
5
6
7 import java.util.Map;
8 import java.util.Objects;
9 import java.util.concurrent.ConcurrentHashMap;
10
11 import de.powerstat.validation.interfaces.IValueObject;
12
13
14
15
16
17
18
19
20
21 public final class GregorianCalendar implements Comparable<GregorianCalendar>, IValueObject
22 {
23
24
25
26
27
28
29
30
31 private static final int[] DAYS_IN_MONTH = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
32
33
34
35
36 private static final Map<Country, Map<String, Map<String, Long>>> REFORM_DATES = new ConcurrentHashMap<>();
37
38
39
40
41 private static final String AFTER = "after";
42
43
44
45
46 private static final String BEFORE = "before";
47
48
49
50
51 private static final String DAYS = "days";
52
53
54
55
56 private static final String DAY = "day";
57
58
59
60
61 private static final String MONTH = "month";
62
63
64
65
66 private static final String YEAR = "year";
67
68
69
70
71 private final Country country;
72
73
74
75
76
77 static
78 {
79 final Map<String, Long> itBefore = new ConcurrentHashMap<>();
80 itBefore.put(GregorianCalendar.YEAR, Long.valueOf(1582));
81 itBefore.put(GregorianCalendar.MONTH, Long.valueOf(10));
82 itBefore.put(GregorianCalendar.DAY, Long.valueOf(4));
83 itBefore.put(GregorianCalendar.DAYS, Long.valueOf(21));
84 final Map<String, Long> itAfter = new ConcurrentHashMap<>();
85 itAfter.put(GregorianCalendar.YEAR, Long.valueOf(1582));
86 itAfter.put(GregorianCalendar.MONTH, Long.valueOf(10));
87 itAfter.put(GregorianCalendar.DAY, Long.valueOf(15));
88 final Map<String, Map<String, Long>> it = new ConcurrentHashMap<>();
89 it.put(GregorianCalendar.BEFORE, itBefore);
90 it.put(GregorianCalendar.AFTER, itAfter);
91 GregorianCalendar.REFORM_DATES.put(Country.of("IT"), it);
92
93 final Map<String, Long> beBefore = new ConcurrentHashMap<>();
94 beBefore.put(GregorianCalendar.YEAR, Long.valueOf(1582));
95 beBefore.put(GregorianCalendar.MONTH, Long.valueOf(12));
96 beBefore.put(GregorianCalendar.DAY, Long.valueOf(21));
97 beBefore.put(GregorianCalendar.DAYS, Long.valueOf(21));
98 final Map<String, Long> beAfter = new ConcurrentHashMap<>();
99 beAfter.put(GregorianCalendar.YEAR, Long.valueOf(1583));
100 beAfter.put(GregorianCalendar.MONTH, Long.valueOf(1));
101 beAfter.put(GregorianCalendar.DAY, Long.valueOf(1));
102 final Map<String, Map<String, Long>> be = new ConcurrentHashMap<>();
103 be.put(GregorianCalendar.BEFORE, beBefore);
104 be.put(GregorianCalendar.AFTER, beAfter);
105 GregorianCalendar.REFORM_DATES.put(Country.of("BE"), be);
106
107 final Map<String, Long> deBefore = new ConcurrentHashMap<>();
108 deBefore.put(GregorianCalendar.YEAR, Long.valueOf(1700));
109 deBefore.put(GregorianCalendar.MONTH, Long.valueOf(2));
110 deBefore.put(GregorianCalendar.DAY, Long.valueOf(18));
111 deBefore.put(GregorianCalendar.DAYS, Long.valueOf(18));
112 final Map<String, Long> deAfter = new ConcurrentHashMap<>();
113 deAfter.put(GregorianCalendar.YEAR, Long.valueOf(1700));
114 deAfter.put(GregorianCalendar.MONTH, Long.valueOf(3));
115 deAfter.put(GregorianCalendar.DAY, Long.valueOf(1));
116 final Map<String, Map<String, Long>> de = new ConcurrentHashMap<>();
117 de.put(GregorianCalendar.BEFORE, deBefore);
118 de.put(GregorianCalendar.AFTER, deAfter);
119 GregorianCalendar.REFORM_DATES.put(Country.of("DE"), de);
120 GregorianCalendar.REFORM_DATES.put(Country.of("CH"), de);
121 GregorianCalendar.REFORM_DATES.put(Country.of("DK"), de);
122
123 final Map<String, Long> usBefore = new ConcurrentHashMap<>();
124 usBefore.put(GregorianCalendar.YEAR, Long.valueOf(1752));
125 usBefore.put(GregorianCalendar.MONTH, Long.valueOf(9));
126 usBefore.put(GregorianCalendar.DAY, Long.valueOf(2));
127 usBefore.put(GregorianCalendar.DAYS, Long.valueOf(19));
128 final Map<String, Long> usAfter = new ConcurrentHashMap<>();
129 usAfter.put(GregorianCalendar.YEAR, Long.valueOf(1752));
130 usAfter.put(GregorianCalendar.MONTH, Long.valueOf(9));
131 usAfter.put(GregorianCalendar.DAY, Long.valueOf(14));
132 final Map<String, Map<String, Long>> us = new ConcurrentHashMap<>();
133 us.put(GregorianCalendar.BEFORE, usBefore);
134 us.put(GregorianCalendar.AFTER, usAfter);
135 GregorianCalendar.REFORM_DATES.put(Country.of("US"), us);
136 GregorianCalendar.REFORM_DATES.put(Country.of("GB"), us);
137
138 final Map<String, Long> seBefore = new ConcurrentHashMap<>();
139 seBefore.put(GregorianCalendar.YEAR, Long.valueOf(1753));
140 seBefore.put(GregorianCalendar.MONTH, Long.valueOf(2));
141 seBefore.put(GregorianCalendar.DAY, Long.valueOf(17));
142 seBefore.put(GregorianCalendar.DAYS, Long.valueOf(17));
143 final Map<String, Long> seAfter = new ConcurrentHashMap<>();
144 seAfter.put(GregorianCalendar.YEAR, Long.valueOf(1753));
145 seAfter.put(GregorianCalendar.MONTH, Long.valueOf(3));
146 seAfter.put(GregorianCalendar.DAY, Long.valueOf(1));
147 final Map<String, Map<String, Long>> se = new ConcurrentHashMap<>();
148 se.put(GregorianCalendar.BEFORE, seBefore);
149 se.put(GregorianCalendar.AFTER, seAfter);
150 GregorianCalendar.REFORM_DATES.put(Country.of("SE"), se);
151
152 final Map<String, Long> ruBefore = new ConcurrentHashMap<>();
153 ruBefore.put(GregorianCalendar.YEAR, Long.valueOf(1918));
154 ruBefore.put(GregorianCalendar.MONTH, Long.valueOf(1));
155 ruBefore.put(GregorianCalendar.DAY, Long.valueOf(31));
156 final Map<String, Long> ruAfter = new ConcurrentHashMap<>();
157 ruAfter.put(GregorianCalendar.YEAR, Long.valueOf(1918));
158 ruAfter.put(GregorianCalendar.MONTH, Long.valueOf(2));
159 ruAfter.put(GregorianCalendar.DAY, Long.valueOf(14));
160 ruAfter.put(GregorianCalendar.DAYS, Long.valueOf(15));
161 final Map<String, Map<String, Long>> ru = new ConcurrentHashMap<>();
162 ru.put(GregorianCalendar.BEFORE, ruBefore);
163 ru.put(GregorianCalendar.AFTER, ruAfter);
164 GregorianCalendar.REFORM_DATES.put(Country.of("RU"), ru);
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 private GregorianCalendar(final Country country)
183 {
184 super();
185 Objects.requireNonNull(country, "country");
186 this.country = country;
187 }
188
189
190
191
192
193
194
195
196 public static GregorianCalendar of(final Country country)
197 {
198
199
200
201
202
203
204
205
206
207
208
209
210
211 return new GregorianCalendar(country);
212 }
213
214
215
216
217
218
219
220
221 public static GregorianCalendar of(final String value)
222 {
223 return of(Country.of(value));
224 }
225
226
227
228
229
230
231
232 public Country getCountry()
233 {
234 return this.country;
235 }
236
237
238
239
240
241
242
243 @Override
244 public String stringValue()
245 {
246 return this.country.stringValue();
247 }
248
249
250
251
252
253
254
255
256 @Override
257 public int hashCode()
258 {
259 return Objects.hash(this.country);
260 }
261
262
263
264
265
266
267
268
269
270 @Override
271 public boolean equals(final Object obj)
272 {
273 if (this == obj)
274 {
275 return true;
276 }
277 if (!(obj instanceof GregorianCalendar))
278 {
279 return false;
280 }
281 final GregorianCalendar other = (GregorianCalendar)obj;
282 return this.country.equals(other.country);
283 }
284
285
286
287
288
289
290
291
292
293
294
295
296 @Override
297 public String toString()
298 {
299 final var builder = new StringBuilder(27);
300 builder.append("GregorianCalendar[country=").append(this.country.stringValue()).append(']');
301 return builder.toString();
302 }
303
304
305
306
307
308
309
310
311
312 @Override
313 public int compareTo(final GregorianCalendar obj)
314 {
315 Objects.requireNonNull(obj, "obj");
316 int result = GregorianCalendar.REFORM_DATES.get(this.country).get(GregorianCalendar.BEFORE).get(GregorianCalendar.YEAR).compareTo(GregorianCalendar.REFORM_DATES.get(obj.country).get(GregorianCalendar.BEFORE).get(GregorianCalendar.YEAR));
317 if (result == 0)
318 {
319 result = GregorianCalendar.REFORM_DATES.get(this.country).get(GregorianCalendar.BEFORE).get(GregorianCalendar.MONTH).compareTo(GregorianCalendar.REFORM_DATES.get(obj.country).get(GregorianCalendar.BEFORE).get(GregorianCalendar.MONTH));
320 }
321 return result;
322 }
323
324
325
326
327
328
329
330
331 public boolean isLeapYear(final Year year)
332 {
333 Objects.requireNonNull(year, GregorianCalendar.YEAR);
334
335 final String beforeAfter = GregorianCalendar.REFORM_DATES.get(this.country).get(GregorianCalendar.BEFORE).get(GregorianCalendar.DAYS) == null ? GregorianCalendar.AFTER : GregorianCalendar.BEFORE;
336 final long reformYear = GregorianCalendar.REFORM_DATES.get(this.country).get(beforeAfter).get(GregorianCalendar.YEAR).longValue();
337 if (year.longValue() > reformYear)
338 {
339 return ((year.longValue() % 4) == 0) && (((year.longValue() % 100) != 0) || ((year.longValue() % 400) == 0));
340 }
341 return ((year.longValue() % 4) == 0);
342 }
343
344
345
346
347
348
349
350
351
352 public int daysInMonth(final Year year, final Month month)
353 {
354 Objects.requireNonNull(year, GregorianCalendar.YEAR);
355 Objects.requireNonNull(month, GregorianCalendar.MONTH);
356
357 final String beforeAfter = GregorianCalendar.REFORM_DATES.get(this.country).get(GregorianCalendar.BEFORE).get(GregorianCalendar.DAYS) == null ? GregorianCalendar.AFTER : GregorianCalendar.BEFORE;
358 final long reformYear = GregorianCalendar.REFORM_DATES.get(this.country).get(beforeAfter).get(GregorianCalendar.YEAR).longValue();
359 final int reformMonth = GregorianCalendar.REFORM_DATES.get(this.country).get(beforeAfter).get(GregorianCalendar.MONTH).intValue();
360 final int restDaysInMonth = GregorianCalendar.REFORM_DATES.get(this.country).get(beforeAfter).get(GregorianCalendar.DAYS).intValue();
361 if ((year.longValue() == reformYear) && (month.intValue() == reformMonth))
362 {
363 return restDaysInMonth;
364 }
365 return GregorianCalendar.DAYS_IN_MONTH[month.intValue()] + (((month.intValue() == 2) && isLeapYear(year)) ? 1 : 0);
366 }
367
368 }