1
2
3
4 package de.powerstat.validation.values;
5
6
7 import java.util.Objects;
8
9 import de.powerstat.validation.interfaces.IValueObject;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 public final class GregorianDate implements Comparable<GregorianDate>, IValueObject
34 {
35
36
37
38
39
40
41
42
43 private static final String FORMAT_TWODIGIT = "%02d";
44
45
46
47
48 private static final String FORMAT_FOURDIGIT = "%04d";
49
50
51
52
53 private static final String DATE_SEP = "-";
54
55
56
57
58 private static final String IT = "IT";
59
60
61
62
63 private final GregorianCalendar calendar;
64
65
66
67
68 private final Year year;
69
70
71
72
73 private final Month month;
74
75
76
77
78 private final Day day;
79
80
81
82
83
84
85
86
87
88
89 private GregorianDate(final GregorianCalendar calendar, final Year year, final Month month, final Day day)
90 {
91 super();
92 Objects.requireNonNull(calendar, "calendar");
93 Objects.requireNonNull(year, "year");
94 Objects.requireNonNull(month, "month");
95 Objects.requireNonNull(day, "day");
96 if (day.intValue() > calendar.daysInMonth(year, month))
97 {
98 throw new IllegalArgumentException("Day does not exists in month");
99 }
100 this.calendar = calendar;
101 this.year = year;
102 this.month = month;
103 this.day = day;
104 }
105
106
107
108
109
110
111
112
113
114
115
116 public static GregorianDate of(final GregorianCalendar calendar, final Year year, final Month month, final Day day)
117 {
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 return new GregorianDate(calendar, year, month, day);
133 }
134
135
136
137
138
139
140
141
142
143
144 public static GregorianDate of(final Year year, final Month month, final Day day)
145 {
146 return GregorianDate.of(GregorianCalendar.of(Country.of(IT)), year, month, day);
147 }
148
149
150
151
152
153
154
155
156 public static GregorianDate of(final String value)
157 {
158 final String[] values = value.split(DATE_SEP);
159 if (values.length != 3)
160 {
161 throw new IllegalArgumentException("Format not as expected: yyyy-mm-dd");
162 }
163 return GregorianDate.of(GregorianCalendar.of(Country.of(IT)), Year.of(values[0]), Month.of(values[1]), Day.of(values[2]));
164 }
165
166
167
168
169
170
171
172 @Override
173 public String stringValue()
174 {
175 return String.format(GregorianDate.FORMAT_FOURDIGIT, this.year.longValue()) + GregorianDate.DATE_SEP + String.format(GregorianDate.FORMAT_TWODIGIT, this.month.intValue()) + GregorianDate.DATE_SEP + String.format(GregorianDate.FORMAT_TWODIGIT, this.day.intValue());
176 }
177
178
179
180
181
182
183
184
185 @Override
186 public int hashCode()
187 {
188
189 return Objects.hash(this.year, this.month, this.day);
190 }
191
192
193
194
195
196
197
198
199
200 @Override
201 public boolean equals(final Object obj)
202 {
203 if (this == obj)
204 {
205 return true;
206 }
207 if (!(obj instanceof GregorianDate))
208 {
209 return false;
210 }
211 final GregorianDate other = (GregorianDate)obj;
212
213 boolean result = this.year.equals(other.year);
214 if (result)
215 {
216 result = this.month.equals(other.month);
217 if (result)
218 {
219 result = this.day.equals(other.day);
220 }
221 }
222 return result;
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236 @Override
237 public String toString()
238 {
239 final var builder = new StringBuilder(30);
240 builder.append("GregorianDate[country=").append(this.calendar.getCountry().stringValue()).append(", date=").append(stringValue()).append(']');
241 return builder.toString();
242 }
243
244
245
246
247
248
249
250
251
252 @Override
253 public int compareTo(final GregorianDate obj)
254 {
255 Objects.requireNonNull(obj, "obj");
256
257 int result = this.year.compareTo(obj.year);
258 if (result == 0)
259 {
260 result = this.month.compareTo(obj.month);
261 if (result == 0)
262 {
263 result = this.day.compareTo(obj.day);
264 }
265 }
266 return result;
267 }
268
269
270
271
272
273
274
275
276
277 @SuppressWarnings("PMD.ShortVariable")
278 public static GregorianDate easter(final GregorianCalendar calendar, final Year year)
279 {
280 final long a = year.longValue() % 19;
281 final long b = year.longValue() / 100;
282 final long c = year.longValue() % 100;
283 final long d = ((((19 * a) + b) - (b / 4) - (((b - ((b + 8) / 25)) + 1) / 3)) + 15) % 30;
284 final long e = ((32 + (2 * (b % 4)) + (2 * (c / 4))) - d - (c % 4)) % 7;
285 final long f = ((d + e) - (7 * ((a + (11 * d) + (22 * e)) / 451))) + 114;
286 final var day = Day.of(((int)f % 31) + 1);
287 final var month = Month.of((int)(f / 31));
288 return GregorianDate.of(calendar, year, month, day);
289 }
290
291 }