26
26
* #L%
27
27
*/
28
28
29
- import java .util .Arrays ;
30
- import java .util .Calendar ;
31
- import java .util .Date ;
29
+ import java .time .DayOfWeek ;
30
+ import java .time .LocalDate ;
31
+ import java .time .Month ;
32
+ import java .time .ZonedDateTime ;
33
+ import java .util .Comparator ;
32
34
import java .util .HashMap ;
33
- import java .util .HashSet ;
34
35
import java .util .Map ;
36
+ import java .util .NavigableSet ;
35
37
import java .util .Set ;
38
+ import java .util .TreeSet ;
39
+ import java .util .stream .Stream ;
36
40
37
41
/**
38
42
* Utility class for Norwegian dates.
39
43
*/
40
44
public class NorwegianDateUtil {
41
- private static Map <Integer , Set <Date >> holidays ;
45
+
46
+ private final static Map <Integer , NavigableSet <LocalDate >> holidays = new HashMap <>();
42
47
43
48
/**
44
49
* Adds the given number of working days to the given date. A working day is
@@ -60,19 +65,14 @@ public class NorwegianDateUtil {
60
65
* The number of working days to add.
61
66
* @return The new date.
62
67
*/
63
- public static Date addWorkingDaysToDate (Date date , int days ) {
64
- Calendar cal = dateToCalendar (date );
65
-
66
- for (int i = 0 ; i < days ; i ++) {
67
- cal .add (Calendar .DATE , 1 );
68
- while (!isWorkingDay (cal )) {
69
- cal .add (Calendar .DATE , 1 );
70
- }
71
- }
72
-
73
- return cal .getTime ();
68
+ public static ZonedDateTime addWorkingDaysToDate (ZonedDateTime date , int days ) {
69
+ return Stream .iterate (date , (d ) -> d .plusDays (1 ))
70
+ .filter (NorwegianDateUtil ::isWorkingDay )
71
+ .limit (days + 1 )
72
+ .max (Comparator .naturalOrder ())
73
+ .orElse (date );
74
74
}
75
-
75
+
76
76
/**
77
77
* Will check if the given date is a working day. That is check if the given
78
78
* date is a weekend day or a national holiday.
@@ -81,8 +81,8 @@ public static Date addWorkingDaysToDate(Date date, int days) {
81
81
* The date to check.
82
82
* @return true if the given date is a working day, false otherwise.
83
83
*/
84
- public static boolean isWorkingDay (Date date ) {
85
- return isWorkingDay ( dateToCalendar ( date ) );
84
+ public static boolean isWorkingDay (ZonedDateTime date ) {
85
+ return date . getDayOfWeek () != DayOfWeek . SATURDAY && date . getDayOfWeek () != DayOfWeek . SUNDAY && ! isHoliday ( date );
86
86
}
87
87
88
88
/**
@@ -92,214 +92,97 @@ public static boolean isWorkingDay(Date date) {
92
92
* The Date to check.
93
93
* @return true if holiday, false otherwise.
94
94
*/
95
- public static boolean isHoliday (Date date ) {
96
- return isHoliday (dateToCalendar (date ));
95
+ public static boolean isHoliday (ZonedDateTime date ) {
96
+ final Set <LocalDate > holidaySet = getHolidaySet (date .getYear ());
97
+ return holidaySet .contains (date .toLocalDate ());
97
98
}
98
-
99
+
99
100
/**
100
- * Return a sorted array of holidays for a given year.
101
+ * Return a sorted set of holidays for a given year.
101
102
*
102
103
* @param year
103
104
* The year to get holidays for.
104
- * @return The array of holidays, sorted by date.
105
+ * @return The set of holidays, naturally sorted by date.
105
106
*/
106
- public static Date [] getHolidays (int year ) {
107
- Set <Date > days = getHolidaySet (year );
108
- Date [] dates = days .toArray (new Date [days .size ()]);
109
- Arrays .sort (dates );
110
- return dates ;
107
+ public static NavigableSet <LocalDate > getHolidays (int year ) {
108
+ return getHolidaySet (year );
111
109
}
112
110
111
+ /**
112
+ * Calculates easter day (sunday) by using Spencer Jones formula found here:
113
+ * <a href="http://no.wikipedia.org/wiki/P%C3%A5skeformelen">Wikipedia -
114
+ * Påskeformelen</a>
115
+ *
116
+ * @param year
117
+ * The year to calculate from.
118
+ * @return The LocalDate representing easter day for the given year.
119
+ */
120
+ private static LocalDate getEasterDay (int year ) {
121
+ int a = year % 19 ;
122
+ int b = year / 100 ;
123
+ int c = year % 100 ;
124
+ int d = b / 4 ;
125
+ int e = b % 4 ;
126
+ int f = (b + 8 ) / 25 ;
127
+ int g = (b - f + 1 ) / 3 ;
128
+ int h = ((19 * a ) + b - d - g + 15 ) % 30 ;
129
+ int i = c / 4 ;
130
+ int k = c % 4 ;
131
+ int l = (32 + (2 * e ) + (2 * i ) - h - k ) % 7 ;
132
+ int m = (a + (11 * h ) + (22 * l )) / 451 ;
133
+ int n = (h + l - (7 * m ) + 114 ) / 31 ; // This is the month number.
134
+ int p = (h + l - (7 * m ) + 114 ) % 31 ; // This is the date minus one.
135
+
136
+ return LocalDate .of (year , n , p + 1 );
137
+ }
138
+
113
139
/**
114
140
* Get a set of holidays for a given year.
115
141
*
116
142
* @param year
117
143
* The year to get holidays for.
118
144
* @return The set of dates.
119
145
*/
120
- private static Set <Date > getHolidaySet (int year ) {
121
- if (holidays == null ) {
122
- holidays = new HashMap <>();
123
- }
146
+ private static NavigableSet <LocalDate > getHolidaySet (int year ) {
124
147
if (!holidays .containsKey (year )) {
125
- Set < Date > yearSet = new HashSet <>();
148
+ NavigableSet < LocalDate > yearSet = new TreeSet <>();
126
149
127
150
// Add set holidays.
128
- yearSet .add (getDate ( 1 , Calendar .JANUARY , year ));
129
- yearSet .add (getDate ( 1 , Calendar .MAY , year ));
130
- yearSet .add (getDate ( 17 , Calendar .MAY , year ));
131
- yearSet .add (getDate ( 25 , Calendar .DECEMBER , year ));
132
- yearSet .add (getDate ( 26 , Calendar .DECEMBER , year ));
151
+ yearSet .add (LocalDate . of ( year , Month .JANUARY , 1 ));
152
+ yearSet .add (LocalDate . of ( year , Month .MAY , 1 ));
153
+ yearSet .add (LocalDate . of ( year , Month .MAY , 17 ));
154
+ yearSet .add (LocalDate . of ( year , Month .DECEMBER , 25 ));
155
+ yearSet .add (LocalDate . of ( year , Month .DECEMBER , 26 ));
133
156
134
157
// Add movable holidays - based on easter day.
135
- Calendar easterDay = dateToCalendar ( getEasterDay (year ) );
158
+ final LocalDate easterDay = getEasterDay (year );
136
159
137
160
// Sunday before easter.
138
- yearSet .add (rollGetDate ( easterDay , - 7 ));
161
+ yearSet .add (easterDay . minusDays ( 7 ));
139
162
140
163
// Thursday before easter.
141
- yearSet .add (rollGetDate ( easterDay , - 3 ));
164
+ yearSet .add (easterDay . minusDays ( 3 ));
142
165
143
166
// Friday before easter.
144
- yearSet .add (rollGetDate ( easterDay , - 2 ));
167
+ yearSet .add (easterDay . minusDays ( 2 ));
145
168
146
169
// Easter day.
147
- yearSet .add (easterDay . getTime () );
170
+ yearSet .add (easterDay );
148
171
149
172
// Second easter day.
150
- yearSet .add (rollGetDate ( easterDay , 1 ));
173
+ yearSet .add (easterDay . plusDays ( 1 ));
151
174
152
175
// "Kristi himmelfart" day.
153
- yearSet .add (rollGetDate ( easterDay , 39 ));
176
+ yearSet .add (easterDay . plusDays ( 39 ));
154
177
155
178
// "Pinse" day.
156
- yearSet .add (rollGetDate ( easterDay , 49 ));
179
+ yearSet .add (easterDay . plusDays ( 49 ));
157
180
158
181
// Second "Pinse" day.
159
- yearSet .add (rollGetDate ( easterDay , 50 ));
182
+ yearSet .add (easterDay . plusDays ( 50 ));
160
183
161
184
holidays .put (year , yearSet );
162
185
}
163
186
return holidays .get (year );
164
187
}
165
-
166
- /**
167
- * Will check if the given date is a working day. That is check if the given
168
- * date is a weekend day or a national holiday.
169
- *
170
- * @param cal
171
- * The Calendar object representing the date.
172
- * @return true if the given date is a working day, false otherwise.
173
- */
174
- private static boolean isWorkingDay (Calendar cal ) {
175
- return cal .get (Calendar .DAY_OF_WEEK ) != Calendar .SATURDAY && cal .get (Calendar .DAY_OF_WEEK ) != Calendar .SUNDAY
176
- && !isHoliday (cal );
177
- }
178
-
179
- /**
180
- * Check if given Calendar object represents a holiday.
181
- *
182
- * @param cal
183
- * The Calendar to check.
184
- * @return true if holiday, false otherwise.
185
- */
186
- private static boolean isHoliday (Calendar cal ) {
187
- int year = cal .get (Calendar .YEAR );
188
- Set <?> yearSet = getHolidaySet (year );
189
- for (Object aYearSet : yearSet ) {
190
- Date date = (Date ) aYearSet ;
191
- if (checkDate (cal , dateToCalendar (date ))) {
192
- return true ;
193
- }
194
- }
195
- return false ;
196
- }
197
-
198
- /**
199
- * Calculates easter day (sunday) by using Spencer Jones formula found here:
200
- * <a href="http://no.wikipedia.org/wiki/P%C3%A5skeformelen">Wikipedia -
201
- * Påskeformelen</a>
202
- *
203
- * @param year
204
- * The year to calculate from.
205
- * @return The Calendar object representing easter day for the given year.
206
- */
207
- private static Date getEasterDay (int year ) {
208
- int a = year % 19 ;
209
- int b = year / 100 ;
210
- int c = year % 100 ;
211
- int d = b / 4 ;
212
- int e = b % 4 ;
213
- int f = (b + 8 ) / 25 ;
214
- int g = (b - f + 1 ) / 3 ;
215
- int h = ((19 * a ) + b - d - g + 15 ) % 30 ;
216
- int i = c / 4 ;
217
- int k = c % 4 ;
218
- int l = (32 + (2 * e ) + (2 * i ) - h - k ) % 7 ;
219
- int m = (a + (11 * h ) + (22 * l )) / 451 ;
220
- int n = (h + l - (7 * m ) + 114 ) / 31 ; // This is the month number.
221
- int p = (h + l - (7 * m ) + 114 ) % 31 ; // This is the date minus one.
222
-
223
- Calendar cal = Calendar .getInstance ();
224
- cal .set (Calendar .YEAR , year );
225
- cal .set (Calendar .MONTH , n - 1 );
226
- cal .set (Calendar .DATE , p + 1 );
227
-
228
- return cal .getTime ();
229
- }
230
-
231
- /**
232
- * Check if the given dates match on day and month.
233
- *
234
- * @param cal
235
- * The Calendar representing the first date.
236
- * @param other
237
- * The Calendar representing the second date.
238
- * @return true if they match, false otherwise.
239
- */
240
- private static boolean checkDate (Calendar cal , Calendar other ) {
241
- return checkDate (cal , other .get (Calendar .DATE ), other .get (Calendar .MONTH ));
242
- }
243
-
244
- /**
245
- * Check if the given date represents the given date and month.
246
- *
247
- * @param cal
248
- * The Calendar object representing date to check.
249
- * @param date
250
- * The date.
251
- * @param month
252
- * The month.
253
- * @return true if they match, false otherwise.
254
- */
255
- private static boolean checkDate (Calendar cal , int date , int month ) {
256
- return cal .get (Calendar .DATE ) == date && cal .get (Calendar .MONTH ) == month ;
257
- }
258
-
259
- /**
260
- * Convert the given Date object to a Calendar instance.
261
- *
262
- * @param date
263
- * The Date object.
264
- * @return The Calendar instance.
265
- */
266
- private static Calendar dateToCalendar (Date date ) {
267
- Calendar cal = Calendar .getInstance ();
268
- cal .setTime (date );
269
- return cal ;
270
- }
271
-
272
- /**
273
- * Add the given number of days to the calendar and convert to Date.
274
- *
275
- * @param calendar
276
- * The calendar to add to.
277
- * @param days
278
- * The number of days to add.
279
- * @return The date object given by the modified calendar.
280
- */
281
- private static Date rollGetDate (Calendar calendar , int days ) {
282
- Calendar easterSunday = (Calendar ) calendar .clone ();
283
- easterSunday .add (Calendar .DATE , days );
284
- return easterSunday .getTime ();
285
- }
286
-
287
- /**
288
- * Get the date for the given values.
289
- *
290
- * @param day
291
- * The day.
292
- * @param month
293
- * The month.
294
- * @param year
295
- * The year.
296
- * @return The date represented by the given values.
297
- */
298
- private static Date getDate (int day , int month , int year ) {
299
- Calendar cal = Calendar .getInstance ();
300
- cal .set (Calendar .YEAR , year );
301
- cal .set (Calendar .MONTH , month );
302
- cal .set (Calendar .DATE , day );
303
- return cal .getTime ();
304
- }
305
188
}
0 commit comments