View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.time;
18  
19  import static org.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
20  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNotSame;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import java.lang.reflect.Constructor;
29  import java.lang.reflect.Modifier;
30  import java.text.DateFormat;
31  import java.text.ParseException;
32  import java.text.SimpleDateFormat;
33  import java.time.Instant;
34  import java.time.LocalDateTime;
35  import java.time.OffsetDateTime;
36  import java.time.ZoneId;
37  import java.time.ZoneOffset;
38  import java.time.ZonedDateTime;
39  import java.time.temporal.ChronoUnit;
40  import java.util.Calendar;
41  import java.util.Date;
42  import java.util.GregorianCalendar;
43  import java.util.Iterator;
44  import java.util.Locale;
45  import java.util.NoSuchElementException;
46  import java.util.TimeZone;
47  import java.util.stream.Stream;
48  
49  import org.apache.commons.lang3.AbstractLangTest;
50  import org.junit.jupiter.api.AfterEach;
51  import org.junit.jupiter.api.BeforeAll;
52  import org.junit.jupiter.api.BeforeEach;
53  import org.junit.jupiter.api.Test;
54  import org.junit.jupiter.params.ParameterizedTest;
55  import org.junit.jupiter.params.provider.Arguments;
56  import org.junit.jupiter.params.provider.MethodSource;
57  import org.junitpioneer.jupiter.DefaultLocale;
58  import org.junitpioneer.jupiter.DefaultTimeZone;
59  import org.junitpioneer.jupiter.ReadsDefaultLocale;
60  import org.junitpioneer.jupiter.WritesDefaultLocale;
61  
62  /**
63   * Tests {@link org.apache.commons.lang3.time.DateUtils}.
64   */
65  @ReadsDefaultLocale
66  @WritesDefaultLocale
67  class DateUtilsTest extends AbstractLangTest {
68  
69      private static final TimeZone TIME_ZONE_NY = TimeZone.getTimeZone("America/New_York");
70      private static final TimeZone TIME_ZONE_DEFAULT = TimeZone.getDefault();
71      private static final TimeZone TIME_ZONE_MET = TimeZone.getTimeZone("MET");
72      private static Date BASE_DATE;
73  
74      /**
75       * Used to check that Calendar objects are close enough
76       * delta is in milliseconds
77       */
78      private static void assertCalendarsEquals(final String message, final Calendar cal1, final Calendar cal2, final long delta) {
79          assertFalse(Math.abs(cal1.getTime().getTime() - cal2.getTime().getTime()) > delta,
80                  message + " expected " + cal1.getTime() + " but got " + cal2.getTime());
81      }
82  
83      /**
84       * This checks that this is a 7 element iterator of Calendar objects
85       * that are dates (no time), and exactly 1 day spaced after each other.
86       */
87      private static void assertWeekIterator(final Iterator<?> it, final Calendar start) {
88          final Calendar end = (Calendar) start.clone();
89          end.add(Calendar.DATE, 6);
90  
91          assertWeekIterator(it, start, end);
92      }
93  
94      /**
95       * This checks that this is a 7 divisible iterator of Calendar objects
96       * that are dates (no time), and exactly 1 day spaced after each other
97       * (in addition to the proper start and stop dates)
98       */
99      private static void assertWeekIterator(final Iterator<?> it, final Calendar start, final Calendar end) {
100         Calendar cal = (Calendar) it.next();
101         assertCalendarsEquals("", start, cal, 0);
102         Calendar last;
103         int count = 1;
104         while (it.hasNext()) {
105             //Check this is just a date (no time component)
106             assertCalendarsEquals("", cal, DateUtils.truncate(cal, Calendar.DATE), 0);
107 
108             last = cal;
109             cal = (Calendar) it.next();
110             count++;
111 
112             //Check that this is one day more than the last date
113             last.add(Calendar.DATE, 1);
114             assertCalendarsEquals("", last, cal, 0);
115         }
116 
117         assertFalse(count % 7 != 0, "There were " + count + " days in this iterator");
118         assertCalendarsEquals("", end, cal, 0);
119     }
120 
121     /**
122      * Convenience method for when working with Date objects
123      */
124     private static void assertWeekIterator(final Iterator<?> it, final Date start, final Date end) {
125         final Calendar calStart = Calendar.getInstance();
126         calStart.setTime(start);
127         final Calendar calEnd = Calendar.getInstance();
128         calEnd.setTime(end);
129 
130         assertWeekIterator(it, calStart, calEnd);
131     }
132 
133     @BeforeAll
134     public static void classSetup() {
135         final GregorianCalendar cal = new GregorianCalendar(2000, 6, 5, 4, 3, 2);
136         cal.set(Calendar.MILLISECOND, 1);
137         BASE_DATE = cal.getTime();
138     }
139 
140     private static Stream<Arguments> testToLocalDateTimeTimeZone() {
141         // @formatter:off
142         return Stream.of(
143                 // [1]
144                 Arguments.of(
145                         // -292275055-05-16T16:47:04.192
146                         LocalDateTime.of(-292275055, 5, 16, 16, 47, 04, 192_000_000),
147                         new Date(Long.MIN_VALUE),
148                         TimeZones.GMT
149                 ),
150                 // [2]
151                 Arguments.of(
152                         // +292278994-08-17T07:12:55.807
153                         LocalDateTime.of(292278994, 8, 17, 7, 12, 55, 807_000_000),
154                         new Date(Long.MAX_VALUE),
155                         TimeZones.GMT
156                 ),
157                 // [3]
158                 Arguments.of(
159                         LocalDateTime.ofInstant(Instant.EPOCH, TimeZones.GMT.toZoneId()),
160                         Date.from(LocalDateTime.of(1970, 1, 1, 0, 0).atOffset(ZoneOffset.UTC).toInstant()),
161                         TimeZones.GMT
162                 ),
163                 // [4]
164                 Arguments.of(
165                         LocalDateTime.ofInstant(Instant.EPOCH.minus(1, ChronoUnit.DAYS), TimeZones.GMT.toZoneId()),
166                         Date.from(LocalDateTime.of(1969, 12, 31, 0, 0).atOffset(ZoneOffset.UTC).toInstant()),
167                         TimeZones.GMT
168                 ),
169                 // [5]
170                 Arguments.of(
171                         LocalDateTime.ofInstant(
172                                 java.sql.Timestamp.valueOf("2000-01-01 12:30:45").toInstant(),
173                                 TIME_ZONE_NY.toZoneId()
174                         ),
175                         java.sql.Timestamp.valueOf("2000-01-01 12:30:45"),
176                         TIME_ZONE_NY
177                 ),
178                 // [6]
179                 Arguments.of(
180                         LocalDateTime.ofInstant(
181                                 java.sql.Timestamp.valueOf("2023-03-12 02:30:00").toInstant(),
182                                 TIME_ZONE_NY.toZoneId()
183                         ),
184                         java.sql.Timestamp.valueOf("2023-03-12 02:30:00"),
185                         TIME_ZONE_NY
186                 ),
187                 // [7]
188                 Arguments.of(
189                         LocalDateTime.ofInstant(
190                                 java.sql.Timestamp.valueOf("2023-03-12 02:30:00").toInstant(),
191                                 TimeZone.getDefault().toZoneId()
192                         ),
193                         java.sql.Timestamp.valueOf("2023-03-12 02:30:00"),
194                         null
195                 ),
196                 // [8]
197                 Arguments.of(
198                         LocalDateTime.of(2022, 12, 31, 19, 0),
199                         Date.from(LocalDateTime.of(2023, 1, 1, 0, 0).atOffset(ZoneOffset.UTC).toInstant()),
200                         TIME_ZONE_NY
201                 ),
202                 // [9]
203                 Arguments.of(
204                         LocalDateTime.of(2023, 3, 12, 3, 0),
205                         Date.from(LocalDateTime.of(2023, 3, 12, 7, 0).atOffset(ZoneOffset.UTC).toInstant()),
206                         TIME_ZONE_NY
207                 ),
208                 // [10]
209                 Arguments.of(
210                         LocalDateTime.of(2023, 1, 1, 14, 0),
211                         Date.from(LocalDateTime.of(2023, 1, 1, 0, 0).atOffset(ZoneOffset.UTC).toInstant()),
212                         TimeZone.getTimeZone("Pacific/Kiritimati")
213                 )
214         );
215         // @formatter:on
216     }
217 
218     private DateFormat dateParser;
219     private DateFormat dateTimeParser;
220     private Date dateAmPm1;
221     private Date dateAmPm2;
222     private Date dateAmPm3;
223     private Date dateAmPm4;
224     private Date date0;
225     private Date date1;
226     private Date date2;
227     private Date date3;
228     private Date date4;
229     private Date date5;
230     private Date date6;
231     private Date date7;
232     private Date date8;
233     private Calendar calAmPm1;
234     private Calendar calAmPm2;
235     private Calendar calAmPm3;
236     private Calendar calAmPm4;
237     private Calendar cal1;
238     private Calendar cal2;
239     private Calendar cal3;
240     private Calendar cal4;
241     private Calendar cal5;
242     private Calendar cal6;
243     private Calendar cal7;
244     private Calendar cal8;
245 
246     @AfterEach
247     public void afterEachResetTimeZones() {
248         TimeZone.setDefault(TIME_ZONE_DEFAULT);
249         dateTimeParser.setTimeZone(TIME_ZONE_DEFAULT);
250     }
251     private void assertDate(final Date date, final int year, final int month, final int day, final int hour, final int min, final int sec, final int mil) {
252         final GregorianCalendar cal = new GregorianCalendar();
253         cal.setTime(date);
254         assertEquals(year, cal.get(Calendar.YEAR));
255         assertEquals(month, cal.get(Calendar.MONTH));
256         assertEquals(day, cal.get(Calendar.DAY_OF_MONTH));
257         assertEquals(hour, cal.get(Calendar.HOUR_OF_DAY));
258         assertEquals(min, cal.get(Calendar.MINUTE));
259         assertEquals(sec, cal.get(Calendar.SECOND));
260         assertEquals(mil, cal.get(Calendar.MILLISECOND));
261     }
262     @BeforeEach
263     public void setUp() throws Exception {
264         dateParser = new SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH);
265         dateTimeParser = new SimpleDateFormat("MMM dd, yyyy H:mm:ss.SSS", Locale.ENGLISH);
266         dateAmPm1 = dateTimeParser.parse("February 3, 2002 01:10:00.000");
267         dateAmPm2 = dateTimeParser.parse("February 3, 2002 11:10:00.000");
268         dateAmPm3 = dateTimeParser.parse("February 3, 2002 13:10:00.000");
269         dateAmPm4 = dateTimeParser.parse("February 3, 2002 19:10:00.000");
270         date0 = dateTimeParser.parse("February 3, 2002 12:34:56.789");
271         date1 = dateTimeParser.parse("February 12, 2002 12:34:56.789");
272         date2 = dateTimeParser.parse("November 18, 2001 1:23:11.321");
273         try {
274             TimeZone.setDefault(TIME_ZONE_MET);
275             dateTimeParser.setTimeZone(TIME_ZONE_MET);
276             date3 = dateTimeParser.parse("March 30, 2003 05:30:45.000");
277             date4 = dateTimeParser.parse("March 30, 2003 01:10:00.000");
278             date5 = dateTimeParser.parse("March 30, 2003 01:40:00.000");
279             date6 = dateTimeParser.parse("March 30, 2003 02:10:00.000");
280             date7 = dateTimeParser.parse("March 30, 2003 02:40:00.000");
281             date8 = dateTimeParser.parse("October 26, 2003 05:30:45.000");
282         } finally {
283             dateTimeParser.setTimeZone(TIME_ZONE_DEFAULT);
284             TimeZone.setDefault(TIME_ZONE_DEFAULT);
285         }
286         calAmPm1 = Calendar.getInstance();
287         calAmPm1.setTime(dateAmPm1);
288         calAmPm2 = Calendar.getInstance();
289         calAmPm2.setTime(dateAmPm2);
290         calAmPm3 = Calendar.getInstance();
291         calAmPm3.setTime(dateAmPm3);
292         calAmPm4 = Calendar.getInstance();
293         calAmPm4.setTime(dateAmPm4);
294         cal1 = Calendar.getInstance();
295         cal1.setTime(date1);
296         cal2 = Calendar.getInstance();
297         cal2.setTime(date2);
298         try {
299             TimeZone.setDefault(TIME_ZONE_MET);
300             cal3 = Calendar.getInstance();
301             cal3.setTime(date3);
302             cal4 = Calendar.getInstance();
303             cal4.setTime(date4);
304             cal5 = Calendar.getInstance();
305             cal5.setTime(date5);
306             cal6 = Calendar.getInstance();
307             cal6.setTime(date6);
308             cal7 = Calendar.getInstance();
309             cal7.setTime(date7);
310             cal8 = Calendar.getInstance();
311             cal8.setTime(date8);
312         } finally {
313             TimeZone.setDefault(TIME_ZONE_DEFAULT);
314         }
315     }
316 
317     @Test
318     void testAddDays() throws Exception {
319         Date result = DateUtils.addDays(BASE_DATE, 0);
320         assertNotSame(BASE_DATE, result);
321         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
322         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
323 
324         result = DateUtils.addDays(BASE_DATE, 1);
325         assertNotSame(BASE_DATE, result);
326         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
327         assertDate(result, 2000, 6, 6, 4, 3, 2, 1);
328 
329         result = DateUtils.addDays(BASE_DATE, -1);
330         assertNotSame(BASE_DATE, result);
331         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
332         assertDate(result, 2000, 6, 4, 4, 3, 2, 1);
333 
334         assertNullPointerException(() -> DateUtils.addDays(null, 0));
335     }
336 
337     @Test
338     void testAddHours() throws Exception {
339         Date result = DateUtils.addHours(BASE_DATE, 0);
340         assertNotSame(BASE_DATE, result);
341         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
342         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
343 
344         result = DateUtils.addHours(BASE_DATE, 1);
345         assertNotSame(BASE_DATE, result);
346         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
347         assertDate(result, 2000, 6, 5, 5, 3, 2, 1);
348 
349         result = DateUtils.addHours(BASE_DATE, -1);
350         assertNotSame(BASE_DATE, result);
351         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
352         assertDate(result, 2000, 6, 5, 3, 3, 2, 1);
353 
354         assertNullPointerException(() -> DateUtils.addHours(null, 0));
355     }
356 
357     @Test
358     void testAddMilliseconds() throws Exception {
359         Date result = DateUtils.addMilliseconds(BASE_DATE, 0);
360         assertNotSame(BASE_DATE, result);
361         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
362         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
363 
364         result = DateUtils.addMilliseconds(BASE_DATE, 1);
365         assertNotSame(BASE_DATE, result);
366         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
367         assertDate(result, 2000, 6, 5, 4, 3, 2, 2);
368 
369         result = DateUtils.addMilliseconds(BASE_DATE, -1);
370         assertNotSame(BASE_DATE, result);
371         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
372         assertDate(result, 2000, 6, 5, 4, 3, 2, 0);
373 
374         assertNullPointerException(() -> DateUtils.addMilliseconds(null, 0));
375     }
376 
377     @Test
378     void testAddMinutes() throws Exception {
379         Date result = DateUtils.addMinutes(BASE_DATE, 0);
380         assertNotSame(BASE_DATE, result);
381         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
382         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
383 
384         result = DateUtils.addMinutes(BASE_DATE, 1);
385         assertNotSame(BASE_DATE, result);
386         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
387         assertDate(result, 2000, 6, 5, 4, 4, 2, 1);
388 
389         result = DateUtils.addMinutes(BASE_DATE, -1);
390         assertNotSame(BASE_DATE, result);
391         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
392         assertDate(result, 2000, 6, 5, 4, 2, 2, 1);
393 
394         assertNullPointerException(() -> DateUtils.addMinutes(null, 0));
395     }
396 
397     @Test
398     void testAddMonths() throws Exception {
399         Date result = DateUtils.addMonths(BASE_DATE, 0);
400         assertNotSame(BASE_DATE, result);
401         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
402         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
403 
404         result = DateUtils.addMonths(BASE_DATE, 1);
405         assertNotSame(BASE_DATE, result);
406         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
407         assertDate(result, 2000, 7, 5, 4, 3, 2, 1);
408 
409         result = DateUtils.addMonths(BASE_DATE, -1);
410         assertNotSame(BASE_DATE, result);
411         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
412         assertDate(result, 2000, 5, 5, 4, 3, 2, 1);
413 
414         assertNullPointerException(() -> DateUtils.addMonths(null, 0));
415     }
416 
417     @Test
418     void testAddSeconds() throws Exception {
419         Date result = DateUtils.addSeconds(BASE_DATE, 0);
420         assertNotSame(BASE_DATE, result);
421         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
422         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
423 
424         result = DateUtils.addSeconds(BASE_DATE, 1);
425         assertNotSame(BASE_DATE, result);
426         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
427         assertDate(result, 2000, 6, 5, 4, 3, 3, 1);
428 
429         result = DateUtils.addSeconds(BASE_DATE, -1);
430         assertNotSame(BASE_DATE, result);
431         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
432         assertDate(result, 2000, 6, 5, 4, 3, 1, 1);
433 
434         assertNullPointerException(() -> DateUtils.addSeconds(null, 0));
435     }
436 
437     @Test
438     void testAddWeeks() throws Exception {
439         Date result = DateUtils.addWeeks(BASE_DATE, 0);
440         assertNotSame(BASE_DATE, result);
441         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
442         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
443 
444         result = DateUtils.addWeeks(BASE_DATE, 1);
445         assertNotSame(BASE_DATE, result);
446         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
447         assertDate(result, 2000, 6, 12, 4, 3, 2, 1);
448 
449         result = DateUtils.addWeeks(BASE_DATE, -1);
450         assertNotSame(BASE_DATE, result);
451         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);      // july
452         assertDate(result, 2000, 5, 28, 4, 3, 2, 1);   // june
453 
454         assertNullPointerException(() -> DateUtils.addMonths(null, 0));
455     }
456 
457     @Test
458     void testAddYears() throws Exception {
459         Date result = DateUtils.addYears(BASE_DATE, 0);
460         assertNotSame(BASE_DATE, result);
461         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
462         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
463 
464         result = DateUtils.addYears(BASE_DATE, 1);
465         assertNotSame(BASE_DATE, result);
466         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
467         assertDate(result, 2001, 6, 5, 4, 3, 2, 1);
468 
469         result = DateUtils.addYears(BASE_DATE, -1);
470         assertNotSame(BASE_DATE, result);
471         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
472         assertDate(result, 1999, 6, 5, 4, 3, 2, 1);
473 
474         assertNullPointerException(() -> DateUtils.addYears(null, 0));
475     }
476 
477     /**
478      * Tests various values with the ceiling method
479      *
480      * @throws Exception so we don't have to catch it
481      */
482     @Test
483     void testCeiling() throws Exception {
484         // test javadoc
485         assertEquals(dateTimeParser.parse("March 28, 2002 14:00:00.000"),
486                 DateUtils.ceiling(
487                             dateTimeParser.parse("March 28, 2002 13:45:01.231"),
488                         Calendar.HOUR),
489                 "ceiling javadoc-1 failed");
490         assertEquals(dateTimeParser.parse("April 1, 2002 00:00:00.000"),
491                 DateUtils.ceiling(
492                             dateTimeParser.parse("March 28, 2002 13:45:01.231"),
493                         Calendar.MONTH),
494                 "ceiling javadoc-2 failed");
495 
496         // tests public static Date ceiling(Date date, int field)
497         assertEquals(dateParser.parse("January 1, 2003"),
498                 DateUtils.ceiling(date1, Calendar.YEAR),
499                 "ceiling year-1 failed");
500         assertEquals(dateParser.parse("January 1, 2002"),
501                 DateUtils.ceiling(date2, Calendar.YEAR),
502                 "ceiling year-2 failed");
503         assertEquals(dateParser.parse("March 1, 2002"),
504                 DateUtils.ceiling(date1, Calendar.MONTH),
505                 "ceiling month-1 failed");
506         assertEquals(dateParser.parse("December 1, 2001"),
507                 DateUtils.ceiling(date2, Calendar.MONTH),
508                 "ceiling month-2 failed");
509         assertEquals(dateParser.parse("February 16, 2002"),
510                 DateUtils.ceiling(date1, DateUtils.SEMI_MONTH),
511                 "ceiling semimonth-1 failed");
512         assertEquals(dateParser.parse("December 1, 2001"),
513                 DateUtils.ceiling(date2, DateUtils.SEMI_MONTH),
514                 "ceiling semimonth-2 failed");
515         assertEquals(dateParser.parse("February 13, 2002"),
516                 DateUtils.ceiling(date1, Calendar.DATE),
517                 "ceiling date-1 failed");
518         assertEquals(dateParser.parse("November 19, 2001"),
519                 DateUtils.ceiling(date2, Calendar.DATE),
520                 "ceiling date-2 failed");
521         assertEquals(dateTimeParser.parse("February 12, 2002 13:00:00.000"),
522                 DateUtils.ceiling(date1, Calendar.HOUR),
523                 "ceiling hour-1 failed");
524         assertEquals(dateTimeParser.parse("November 18, 2001 2:00:00.000"),
525                 DateUtils.ceiling(date2, Calendar.HOUR),
526                 "ceiling hour-2 failed");
527         assertEquals(dateTimeParser.parse("February 12, 2002 12:35:00.000"),
528                 DateUtils.ceiling(date1, Calendar.MINUTE),
529                 "ceiling minute-1 failed");
530         assertEquals(dateTimeParser.parse("November 18, 2001 1:24:00.000"),
531                 DateUtils.ceiling(date2, Calendar.MINUTE),
532                 "ceiling minute-2 failed");
533         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:57.000"),
534                 DateUtils.ceiling(date1, Calendar.SECOND),
535                 "ceiling second-1 failed");
536         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:12.000"),
537                 DateUtils.ceiling(date2, Calendar.SECOND),
538                 "ceiling second-2 failed");
539         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
540                 DateUtils.ceiling(dateAmPm1, Calendar.AM_PM),
541                 "ceiling ampm-1 failed");
542         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
543                 DateUtils.ceiling(dateAmPm2, Calendar.AM_PM),
544                 "ceiling ampm-2 failed");
545         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"),
546                 DateUtils.ceiling(dateAmPm3, Calendar.AM_PM),
547                 "ceiling ampm-3 failed");
548         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"),
549                 DateUtils.ceiling(dateAmPm4, Calendar.AM_PM),
550                 "ceiling ampm-4 failed");
551 
552      // tests public static Date ceiling(Object date, int field)
553         assertEquals(dateParser.parse("January 1, 2003"),
554                 DateUtils.ceiling((Object) date1, Calendar.YEAR),
555                 "ceiling year-1 failed");
556         assertEquals(dateParser.parse("January 1, 2002"),
557                 DateUtils.ceiling((Object) date2, Calendar.YEAR),
558                 "ceiling year-2 failed");
559         assertEquals(dateParser.parse("March 1, 2002"),
560                 DateUtils.ceiling((Object) date1, Calendar.MONTH),
561                 "ceiling month-1 failed");
562         assertEquals(dateParser.parse("December 1, 2001"),
563                 DateUtils.ceiling((Object) date2, Calendar.MONTH),
564                 "ceiling month-2 failed");
565         assertEquals(dateParser.parse("February 16, 2002"),
566                 DateUtils.ceiling((Object) date1, DateUtils.SEMI_MONTH),
567                 "ceiling semimonth-1 failed");
568         assertEquals(dateParser.parse("December 1, 2001"),
569                 DateUtils.ceiling((Object) date2, DateUtils.SEMI_MONTH),
570                 "ceiling semimonth-2 failed");
571         assertEquals(dateParser.parse("February 13, 2002"),
572                 DateUtils.ceiling((Object) date1, Calendar.DATE),
573                 "ceiling date-1 failed");
574         assertEquals(dateParser.parse("November 19, 2001"),
575                 DateUtils.ceiling((Object) date2, Calendar.DATE),
576                 "ceiling date-2 failed");
577         assertEquals(dateTimeParser.parse("February 12, 2002 13:00:00.000"),
578                 DateUtils.ceiling((Object) date1, Calendar.HOUR),
579                 "ceiling hour-1 failed");
580         assertEquals(dateTimeParser.parse("November 18, 2001 2:00:00.000"),
581                 DateUtils.ceiling((Object) date2, Calendar.HOUR),
582                 "ceiling hour-2 failed");
583         assertEquals(dateTimeParser.parse("February 12, 2002 12:35:00.000"),
584                 DateUtils.ceiling((Object) date1, Calendar.MINUTE),
585                 "ceiling minute-1 failed");
586         assertEquals(dateTimeParser.parse("November 18, 2001 1:24:00.000"),
587                 DateUtils.ceiling((Object) date2, Calendar.MINUTE),
588                 "ceiling minute-2 failed");
589         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:57.000"),
590                 DateUtils.ceiling((Object) date1, Calendar.SECOND),
591                 "ceiling second-1 failed");
592         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:12.000"),
593                 DateUtils.ceiling((Object) date2, Calendar.SECOND),
594                 "ceiling second-2 failed");
595         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
596                 DateUtils.ceiling((Object) dateAmPm1, Calendar.AM_PM),
597                 "ceiling ampm-1 failed");
598         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
599                 DateUtils.ceiling((Object) dateAmPm2, Calendar.AM_PM),
600                 "ceiling ampm-2 failed");
601         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"),
602                 DateUtils.ceiling((Object) dateAmPm3, Calendar.AM_PM),
603                 "ceiling ampm-3 failed");
604         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"),
605                 DateUtils.ceiling((Object) dateAmPm4, Calendar.AM_PM),
606                 "ceiling ampm-4 failed");
607 
608         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:57.000"),
609                 DateUtils.ceiling((Object) cal1, Calendar.SECOND),
610                 "ceiling calendar second-1 failed");
611         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:12.000"),
612                 DateUtils.ceiling((Object) cal2, Calendar.SECOND),
613                 "ceiling calendar second-2 failed");
614 
615         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
616                 DateUtils.ceiling((Object) calAmPm1, Calendar.AM_PM),
617                 "ceiling ampm-1 failed");
618         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
619                 DateUtils.ceiling((Object) calAmPm2, Calendar.AM_PM),
620                 "ceiling ampm-2 failed");
621         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"),
622                 DateUtils.ceiling((Object) calAmPm3, Calendar.AM_PM),
623                 "ceiling ampm-3 failed");
624         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"),
625                 DateUtils.ceiling((Object) calAmPm4, Calendar.AM_PM),
626                 "ceiling ampm-4 failed");
627 
628         assertNullPointerException(() -> DateUtils.ceiling((Date) null, Calendar.SECOND));
629         assertNullPointerException(() -> DateUtils.ceiling((Calendar) null, Calendar.SECOND));
630         assertNullPointerException(() -> DateUtils.ceiling((Object) null, Calendar.SECOND));
631         assertThrows(ClassCastException.class, () -> DateUtils.ceiling("", Calendar.SECOND));
632         assertIllegalArgumentException(() -> DateUtils.ceiling(date1, -9999));
633 
634     }
635 
636     /**
637      * Tests various values with the ceiling method
638      *
639      * @throws Exception so we don't have to catch it
640      */
641     @Test
642     void testCeiling_Bugzilla_31395() throws Exception {
643         // Bug 31395, large dates
644         final Date endOfTime = new Date(Long.MAX_VALUE); // fyi: Sun Aug 17 07:12:55 CET 292278994 -- 807 millis
645         final GregorianCalendar endCal = new GregorianCalendar();
646         endCal.setTime(endOfTime);
647         assertThrows(ArithmeticException.class, () -> DateUtils.ceiling(endCal, Calendar.DATE));
648         endCal.set(Calendar.YEAR, 280000001);
649         assertThrows(ArithmeticException.class, () -> DateUtils.ceiling(endCal, Calendar.DATE));
650         endCal.set(Calendar.YEAR, 280000000);
651         final Calendar cal = DateUtils.ceiling(endCal, Calendar.DATE);
652         assertEquals(0, cal.get(Calendar.HOUR));
653     }
654 
655     /**
656      * Tests various values with the ceiling method
657      *
658      * @throws Exception so we don't have to catch it
659      */
660     @Test
661     void testCeiling_MET() throws Exception {
662         // Fix for https://issues.apache.org/bugzilla/show_bug.cgi?id=25560
663         // Test ceiling across the beginning of daylight saving time
664         TimeZone.setDefault(TIME_ZONE_MET);
665         dateTimeParser.setTimeZone(TIME_ZONE_MET);
666 
667         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling(date4, Calendar.DATE), "ceiling MET date across DST change-over");
668         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling((Object) cal4, Calendar.DATE),
669                 "ceiling MET date across DST change-over");
670         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling(date5, Calendar.DATE), "ceiling MET date across DST change-over");
671         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling((Object) cal5, Calendar.DATE),
672                 "ceiling MET date across DST change-over");
673         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling(date6, Calendar.DATE), "ceiling MET date across DST change-over");
674         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling((Object) cal6, Calendar.DATE),
675                 "ceiling MET date across DST change-over");
676         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling(date7, Calendar.DATE), "ceiling MET date across DST change-over");
677         assertEquals(dateTimeParser.parse("March 31, 2003 00:00:00.000"), DateUtils.ceiling((Object) cal7, Calendar.DATE),
678                 "ceiling MET date across DST change-over");
679 
680         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.ceiling(date4, Calendar.HOUR_OF_DAY),
681                 "ceiling MET date across DST change-over");
682         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.ceiling((Object) cal4, Calendar.HOUR_OF_DAY),
683                 "ceiling MET date across DST change-over");
684         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.ceiling(date5, Calendar.HOUR_OF_DAY),
685                 "ceiling MET date across DST change-over");
686         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.ceiling((Object) cal5, Calendar.HOUR_OF_DAY),
687                 "ceiling MET date across DST change-over");
688         assertEquals(dateTimeParser.parse("March 30, 2003 04:00:00.000"), DateUtils.ceiling(date6, Calendar.HOUR_OF_DAY),
689                 "ceiling MET date across DST change-over");
690         assertEquals(dateTimeParser.parse("March 30, 2003 04:00:00.000"), DateUtils.ceiling((Object) cal6, Calendar.HOUR_OF_DAY),
691                 "ceiling MET date across DST change-over");
692         assertEquals(dateTimeParser.parse("March 30, 2003 04:00:00.000"), DateUtils.ceiling(date7, Calendar.HOUR_OF_DAY),
693                 "ceiling MET date across DST change-over");
694         assertEquals(dateTimeParser.parse("March 30, 2003 04:00:00.000"), DateUtils.ceiling((Object) cal7, Calendar.HOUR_OF_DAY),
695                 "ceiling MET date across DST change-over");
696     }
697 
698     @Test
699     void testConstructor() {
700         assertNotNull(new DateUtils());
701         final Constructor<?>[] cons = DateUtils.class.getDeclaredConstructors();
702         assertEquals(1, cons.length);
703         assertTrue(Modifier.isPublic(cons[0].getModifiers()));
704         assertTrue(Modifier.isPublic(DateUtils.class.getModifiers()));
705         assertFalse(Modifier.isFinal(DateUtils.class.getModifiers()));
706     }
707 
708     @Test
709     void testIsSameDay_Cal() {
710         final GregorianCalendar cala = new GregorianCalendar(2004, 6, 9, 13, 45);
711         final GregorianCalendar calb = new GregorianCalendar(2004, 6, 9, 13, 45);
712         assertTrue(DateUtils.isSameDay(cala, calb));
713         calb.add(Calendar.DAY_OF_YEAR, 1);
714         assertFalse(DateUtils.isSameDay(cala, calb));
715         cala.add(Calendar.DAY_OF_YEAR, 1);
716         assertTrue(DateUtils.isSameDay(cala, calb));
717         calb.add(Calendar.YEAR, 1);
718         assertFalse(DateUtils.isSameDay(cala, calb));
719     }
720 
721     @Test
722     void testIsSameDay_CalNotNullNull() {
723         assertNullPointerException(() -> DateUtils.isSameDay(Calendar.getInstance(), null));
724     }
725 
726     @Test
727     void testIsSameDay_CalNullNotNull() {
728         assertNullPointerException(() -> DateUtils.isSameDay(null, Calendar.getInstance()));
729     }
730 
731     @Test
732     void testIsSameDay_CalNullNull() {
733         assertNullPointerException(() -> DateUtils.isSameDay((Calendar) null, null));
734     }
735 
736     @Test
737     void testIsSameDay_Date() {
738         Date datea = new GregorianCalendar(2004, 6, 9, 13, 45).getTime();
739         Date dateb = new GregorianCalendar(2004, 6, 9, 13, 45).getTime();
740         assertTrue(DateUtils.isSameDay(datea, dateb));
741         dateb = new GregorianCalendar(2004, 6, 10, 13, 45).getTime();
742         assertFalse(DateUtils.isSameDay(datea, dateb));
743         datea = new GregorianCalendar(2004, 6, 10, 13, 45).getTime();
744         assertTrue(DateUtils.isSameDay(datea, dateb));
745         dateb = new GregorianCalendar(2005, 6, 10, 13, 45).getTime();
746         assertFalse(DateUtils.isSameDay(datea, dateb));
747     }
748 
749     @Test
750     void testIsSameDay_DateNotNullNull() {
751         assertNullPointerException(() -> DateUtils.isSameDay(new Date(), null));
752     }
753 
754     @Test
755     void testIsSameDay_DateNullNotNull() {
756         assertNullPointerException(() -> DateUtils.isSameDay(null, new Date()));
757     }
758 
759     @Test
760     void testIsSameDay_DateNullNull() {
761         assertNullPointerException(() -> DateUtils.isSameDay((Date) null, null));
762     }
763 
764     @Test
765     void testIsSameInstant_Cal() {
766         final GregorianCalendar cala = new GregorianCalendar(TimeZone.getTimeZone("GMT+1"));
767         final GregorianCalendar calb = new GregorianCalendar(TimeZone.getTimeZone("GMT-1"));
768         cala.set(2004, Calendar.JULY, 9, 13, 45, 0);
769         cala.set(Calendar.MILLISECOND, 0);
770         calb.set(2004, Calendar.JULY, 9, 13, 45, 0);
771         calb.set(Calendar.MILLISECOND, 0);
772         assertFalse(DateUtils.isSameInstant(cala, calb));
773 
774         calb.set(2004, Calendar.JULY, 9, 11, 45, 0);
775         assertTrue(DateUtils.isSameInstant(cala, calb));
776     }
777 
778     @Test
779     void testIsSameInstant_CalNotNullNull() {
780         assertNullPointerException(() -> DateUtils.isSameInstant(Calendar.getInstance(), null));
781     }
782 
783     @Test
784     void testIsSameInstant_CalNullNotNull() {
785         assertNullPointerException(() -> DateUtils.isSameInstant(null, Calendar.getInstance()));
786     }
787 
788     @Test
789     void testIsSameInstant_CalNullNull() {
790         assertNullPointerException(() -> DateUtils.isSameInstant((Calendar) null, null));
791     }
792 
793     @Test
794     void testIsSameInstant_Date() {
795         Date datea = new GregorianCalendar(2004, 6, 9, 13, 45).getTime();
796         Date dateb = new GregorianCalendar(2004, 6, 9, 13, 45).getTime();
797         assertTrue(DateUtils.isSameInstant(datea, dateb));
798         dateb = new GregorianCalendar(2004, 6, 10, 13, 45).getTime();
799         assertFalse(DateUtils.isSameInstant(datea, dateb));
800         datea = new GregorianCalendar(2004, 6, 10, 13, 45).getTime();
801         assertTrue(DateUtils.isSameInstant(datea, dateb));
802         dateb = new GregorianCalendar(2005, 6, 10, 13, 45).getTime();
803         assertFalse(DateUtils.isSameInstant(datea, dateb));
804     }
805 
806     @Test
807     void testIsSameInstant_DateNotNullNull() {
808         assertNullPointerException(() -> DateUtils.isSameInstant(new Date(), null));
809     }
810 
811     @Test
812     void testIsSameInstant_DateNullNotNull() {
813         assertNullPointerException(() -> DateUtils.isSameInstant(null, new Date()));
814     }
815 
816     @Test
817     void testIsSameInstant_DateNullNull() {
818         assertNullPointerException(() -> DateUtils.isSameInstant((Date) null, null));
819     }
820 
821     @Test
822     void testIsSameLocalTime_Cal() {
823         final GregorianCalendar cala = new GregorianCalendar(TimeZone.getTimeZone("GMT+1"));
824         final GregorianCalendar calb = new GregorianCalendar(TimeZone.getTimeZone("GMT-1"));
825         cala.set(2004, Calendar.JULY, 9, 13, 45, 0);
826         cala.set(Calendar.MILLISECOND, 0);
827         calb.set(2004, Calendar.JULY, 9, 13, 45, 0);
828         calb.set(Calendar.MILLISECOND, 0);
829         assertTrue(DateUtils.isSameLocalTime(cala, calb));
830 
831         final Calendar calc = Calendar.getInstance();
832         final Calendar cald = Calendar.getInstance();
833         calc.set(2004, Calendar.JULY, 9, 4,  0, 0);
834         cald.set(2004, Calendar.JULY, 9, 16, 0, 0);
835         calc.set(Calendar.MILLISECOND, 0);
836         cald.set(Calendar.MILLISECOND, 0);
837         assertFalse(DateUtils.isSameLocalTime(calc, cald), "LANG-677");
838 
839         calb.set(2004, Calendar.JULY, 9, 11, 45, 0);
840         assertFalse(DateUtils.isSameLocalTime(cala, calb));
841     }
842 
843     @Test
844     void testIsSameLocalTime_CalNotNullNull() {
845         assertNullPointerException(() -> DateUtils.isSameLocalTime(Calendar.getInstance(), null));
846     }
847 
848     @Test
849     void testIsSameLocalTime_CalNullNotNull() {
850         assertNullPointerException(() -> DateUtils.isSameLocalTime(null, Calendar.getInstance()));
851     }
852 
853     @Test
854     void testIsSameLocalTime_CalNullNull() {
855         assertNullPointerException(() -> DateUtils.isSameLocalTime(null, null));
856     }
857 
858     /**
859      * Tests the iterator exceptions
860      */
861     @Test
862     void testIteratorEx() {
863         assertIllegalArgumentException(() -> DateUtils.iterator(Calendar.getInstance(), -9999));
864         assertNullPointerException(() -> DateUtils.iterator((Date) null, DateUtils.RANGE_WEEK_CENTER));
865         assertNullPointerException(() -> DateUtils.iterator((Calendar) null, DateUtils.RANGE_WEEK_CENTER));
866         assertNullPointerException(() -> DateUtils.iterator((Object) null, DateUtils.RANGE_WEEK_CENTER));
867         assertThrows(ClassCastException.class, () -> DateUtils.iterator("", DateUtils.RANGE_WEEK_CENTER));
868     }
869 
870     /** See https://issues.apache.org/jira/browse/LANG-530 */
871     @SuppressWarnings("deprecation")
872     @Test
873     void testLang530() throws ParseException {
874         final Date d = new Date();
875         final String isoDateStr = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(d);
876         final Date d2 = DateUtils.parseDate(isoDateStr, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern());
877         // the format loses milliseconds so have to reintroduce them
878         assertEquals(d.getTime(), d2.getTime() + d.getTime() % 1000, "Date not equal to itself ISO formatted and parsed");
879     }
880 
881     @Test
882     void testLANG799() throws ParseException {
883         DateUtils.parseDateStrictly("09 abril 2008 23:55:38 GMT", new Locale("es"), "dd MMM yyyy HH:mm:ss zzz");
884     }
885 
886     /** Parse English date with German Locale. */
887     @DefaultLocale(language = "de")
888     @Test
889     void testLANG799_DE_FAIL() {
890         assertThrows(ParseException.class, () -> DateUtils.parseDate("Wed, 09 Apr 2008 23:55:38 GMT", "EEE, dd MMM yyyy HH:mm:ss zzz"));
891     }
892 
893     @DefaultLocale(language = "de")
894     @Test
895     void testLANG799_DE_OK() throws ParseException {
896         DateUtils.parseDate("Mi, 09 Apr 2008 23:55:38 GMT", "EEE, dd MMM yyyy HH:mm:ss zzz");
897         DateUtils.parseDateStrictly("Mi, 09 Apr 2008 23:55:38 GMT", "EEE, dd MMM yyyy HH:mm:ss zzz");
898     }
899 
900     // Parse German date with English Locale
901     @DefaultLocale(language = "en")
902     @Test
903     void testLANG799_EN_FAIL() {
904         assertThrows(ParseException.class, () -> DateUtils.parseDate("Mi, 09 Apr 2008 23:55:38 GMT", "EEE, dd MMM yyyy HH:mm:ss zzz"));
905     }
906 
907     @DefaultLocale(language = "en")
908     @Test
909     void testLANG799_EN_OK() throws ParseException {
910         DateUtils.parseDate("Wed, 09 Apr 2008 23:55:38 GMT", "EEE, dd MMM yyyy HH:mm:ss zzz");
911         DateUtils.parseDateStrictly("Wed, 09 Apr 2008 23:55:38 GMT", "EEE, dd MMM yyyy HH:mm:ss zzz");
912     }
913 
914     /** Parse German date with English Locale, specifying German Locale override. */
915     @DefaultLocale(language = "en")
916     @Test
917     void testLANG799_EN_WITH_DE_LOCALE() throws ParseException {
918         DateUtils.parseDate("Mi, 09 Apr 2008 23:55:38 GMT", Locale.GERMAN, "EEE, dd MMM yyyy HH:mm:ss zzz");
919     }
920 
921     /**
922      * Tests the calendar iterator for month-based ranges
923      *
924      * @throws Exception so we don't have to catch it
925      */
926     @Test
927     void testMonthIterator() throws Exception {
928         Iterator<?> it = DateUtils.iterator(date1, DateUtils.RANGE_MONTH_SUNDAY);
929         assertWeekIterator(it,
930                 dateParser.parse("January 27, 2002"),
931                 dateParser.parse("March 2, 2002"));
932 
933         it = DateUtils.iterator(date1, DateUtils.RANGE_MONTH_MONDAY);
934         assertWeekIterator(it,
935                 dateParser.parse("January 28, 2002"),
936                 dateParser.parse("March 3, 2002"));
937 
938         it = DateUtils.iterator(date2, DateUtils.RANGE_MONTH_SUNDAY);
939         assertWeekIterator(it,
940                 dateParser.parse("October 28, 2001"),
941                 dateParser.parse("December 1, 2001"));
942 
943         it = DateUtils.iterator(date2, DateUtils.RANGE_MONTH_MONDAY);
944         assertWeekIterator(it,
945                 dateParser.parse("October 29, 2001"),
946                 dateParser.parse("December 2, 2001"));
947     }
948 
949     @Test
950     void testParse_EmptyParsers() {
951         assertThrows(ParseException.class, () -> DateUtils.parseDate("19721203"));
952     }
953 
954     @Test
955     void testParse_NullParsers() {
956         assertNullPointerException(() -> DateUtils.parseDate("19721203", (String[]) null));
957     }
958 
959     @Test
960     void testParseDate() throws Exception {
961         final GregorianCalendar cal = new GregorianCalendar(1972, 11, 3);
962         String dateStr = "1972-12-03";
963         final String[] parsers = {"yyyy'-'DDD", "yyyy'-'MM'-'dd", "yyyyMMdd"};
964         Date date = DateUtils.parseDate(dateStr, parsers);
965         assertEquals(cal.getTime(), date);
966 
967         dateStr = "1972-338";
968         date = DateUtils.parseDate(dateStr, parsers);
969         assertEquals(cal.getTime(), date);
970 
971         dateStr = "19721203";
972         date = DateUtils.parseDate(dateStr, parsers);
973         assertEquals(cal.getTime(), date);
974     }
975 
976     @Test
977     void testParseDate_InvalidDateString() {
978         final String[] parsers = {"yyyy'-'DDD", "yyyy'-'MM'-'dd", "yyyyMMdd"};
979         assertThrows(ParseException.class, () -> DateUtils.parseDate("197212AB", parsers));
980     }
981 
982     @Test
983     void testParseDate_NoDateString() {
984         final String[] parsers = {"yyyy'-'DDD", "yyyy'-'MM'-'dd", "yyyyMMdd"};
985         assertThrows(ParseException.class, () -> DateUtils.parseDate("PURPLE", parsers));
986     }
987 
988     @Test
989     void testParseDate_Null() {
990         final String[] parsers = {"yyyy'-'DDD", "yyyy'-'MM'-'dd", "yyyyMMdd"};
991         assertNullPointerException(() -> DateUtils.parseDate(null, parsers));
992     }
993 
994     /** LANG-486 */
995     @Test
996     void testParseDateWithLeniency() throws ParseException {
997         final GregorianCalendar cal = new GregorianCalendar(1998, 6, 30);
998         final String dateStr = "02 942, 1996";
999         final String[] parsers = {"MM DDD, yyyy"};
1000 
1001         final Date date = DateUtils.parseDate(dateStr, parsers);
1002         assertEquals(cal.getTime(), date);
1003 
1004         assertThrows(ParseException.class, () -> DateUtils.parseDateStrictly(dateStr, parsers));
1005     }
1006 
1007     /**
1008      * Tests various values with the round method
1009      *
1010      * @throws Exception so we don't have to catch it
1011      */
1012     @Test
1013     void testRound() throws Exception {
1014         // tests for public static Date round(Date date, int field)
1015         assertEquals(dateParser.parse("January 1, 2002"), DateUtils.round(date1, Calendar.YEAR), "round year-1 failed");
1016         assertEquals(dateParser.parse("January 1, 2002"), DateUtils.round(date2, Calendar.YEAR), "round year-2 failed");
1017         assertEquals(dateParser.parse("February 1, 2002"), DateUtils.round(date1, Calendar.MONTH), "round month-1 failed");
1018         assertEquals(dateParser.parse("December 1, 2001"), DateUtils.round(date2, Calendar.MONTH), "round month-2 failed");
1019         assertEquals(dateParser.parse("February 1, 2002"), DateUtils.round(date0, DateUtils.SEMI_MONTH), "round semimonth-0 failed");
1020         assertEquals(dateParser.parse("February 16, 2002"), DateUtils.round(date1, DateUtils.SEMI_MONTH), "round semimonth-1 failed");
1021         assertEquals(dateParser.parse("November 16, 2001"), DateUtils.round(date2, DateUtils.SEMI_MONTH), "round semimonth-2 failed");
1022 
1023         assertEquals(dateParser.parse("February 13, 2002"), DateUtils.round(date1, Calendar.DATE), "round date-1 failed");
1024         assertEquals(dateParser.parse("November 18, 2001"), DateUtils.round(date2, Calendar.DATE), "round date-2 failed");
1025         assertEquals(dateTimeParser.parse("February 12, 2002 13:00:00.000"), DateUtils.round(date1, Calendar.HOUR), "round hour-1 failed");
1026         assertEquals(dateTimeParser.parse("November 18, 2001 1:00:00.000"), DateUtils.round(date2, Calendar.HOUR), "round hour-2 failed");
1027         assertEquals(dateTimeParser.parse("February 12, 2002 12:35:00.000"), DateUtils.round(date1, Calendar.MINUTE), "round minute-1 failed");
1028         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:00.000"), DateUtils.round(date2, Calendar.MINUTE), "round minute-2 failed");
1029         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:57.000"), DateUtils.round(date1, Calendar.SECOND), "round second-1 failed");
1030         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:11.000"), DateUtils.round(date2, Calendar.SECOND), "round second-2 failed");
1031         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"), DateUtils.round(dateAmPm1, Calendar.AM_PM), "round ampm-1 failed");
1032         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"), DateUtils.round(dateAmPm2, Calendar.AM_PM), "round ampm-2 failed");
1033         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"), DateUtils.round(dateAmPm3, Calendar.AM_PM), "round ampm-3 failed");
1034         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"), DateUtils.round(dateAmPm4, Calendar.AM_PM), "round ampm-4 failed");
1035 
1036         // tests for public static Date round(Object date, int field)
1037         assertEquals(dateParser.parse("January 1, 2002"), DateUtils.round((Object) date1, Calendar.YEAR), "round year-1 failed");
1038         assertEquals(dateParser.parse("January 1, 2002"), DateUtils.round((Object) date2, Calendar.YEAR), "round year-2 failed");
1039         assertEquals(dateParser.parse("February 1, 2002"), DateUtils.round((Object) date1, Calendar.MONTH), "round month-1 failed");
1040         assertEquals(dateParser.parse("December 1, 2001"), DateUtils.round((Object) date2, Calendar.MONTH), "round month-2 failed");
1041         assertEquals(dateParser.parse("February 16, 2002"), DateUtils.round((Object) date1, DateUtils.SEMI_MONTH), "round semimonth-1 failed");
1042         assertEquals(dateParser.parse("November 16, 2001"), DateUtils.round((Object) date2, DateUtils.SEMI_MONTH), "round semimonth-2 failed");
1043         assertEquals(dateParser.parse("February 13, 2002"), DateUtils.round((Object) date1, Calendar.DATE), "round date-1 failed");
1044         assertEquals(dateParser.parse("November 18, 2001"), DateUtils.round((Object) date2, Calendar.DATE), "round date-2 failed");
1045         assertEquals(dateTimeParser.parse("February 12, 2002 13:00:00.000"), DateUtils.round((Object) date1, Calendar.HOUR), "round hour-1 failed");
1046         assertEquals(dateTimeParser.parse("November 18, 2001 1:00:00.000"), DateUtils.round((Object) date2, Calendar.HOUR), "round hour-2 failed");
1047         assertEquals(dateTimeParser.parse("February 12, 2002 12:35:00.000"), DateUtils.round((Object) date1, Calendar.MINUTE), "round minute-1 failed");
1048         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:00.000"), DateUtils.round((Object) date2, Calendar.MINUTE), "round minute-2 failed");
1049         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:57.000"), DateUtils.round((Object) date1, Calendar.SECOND), "round second-1 failed");
1050         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:11.000"), DateUtils.round((Object) date2, Calendar.SECOND), "round second-2 failed");
1051         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:57.000"), DateUtils.round((Object) cal1, Calendar.SECOND), "round calendar second-1 failed");
1052         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:11.000"), DateUtils.round((Object) cal2, Calendar.SECOND), "round calendar second-2 failed");
1053         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"), DateUtils.round((Object) dateAmPm1, Calendar.AM_PM), "round ampm-1 failed");
1054         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"), DateUtils.round((Object) dateAmPm2, Calendar.AM_PM), "round ampm-2 failed");
1055         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"), DateUtils.round((Object) dateAmPm3, Calendar.AM_PM), "round ampm-3 failed");
1056         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"), DateUtils.round((Object) dateAmPm4, Calendar.AM_PM), "round ampm-4 failed");
1057 
1058         assertNullPointerException(() -> DateUtils.round((Date) null, Calendar.SECOND));
1059         assertNullPointerException(() -> DateUtils.round((Calendar) null, Calendar.SECOND));
1060         assertNullPointerException(() -> DateUtils.round((Object) null, Calendar.SECOND));
1061         assertThrows(ClassCastException.class, () -> DateUtils.round("", Calendar.SECOND));
1062         assertIllegalArgumentException(() -> DateUtils.round(date1, -9999));
1063 
1064         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"), DateUtils.round((Object) calAmPm1, Calendar.AM_PM), "round ampm-1 failed");
1065         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"), DateUtils.round((Object) calAmPm2, Calendar.AM_PM), "round ampm-2 failed");
1066         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"), DateUtils.round((Object) calAmPm3, Calendar.AM_PM), "round ampm-3 failed");
1067         assertEquals(dateTimeParser.parse("February 4, 2002 00:00:00.000"), DateUtils.round((Object) calAmPm4, Calendar.AM_PM), "round ampm-4 failed");
1068     }
1069 
1070     /**
1071      * Tests various values with the round method
1072      *
1073      * @throws Exception so we don't have to catch it
1074      */
1075     @Test
1076     void testRound_MET() throws Exception {
1077         // Fix for https://issues.apache.org/bugzilla/show_bug.cgi?id=25560 / LANG-13
1078         // Test rounding across the beginning of daylight saving time
1079         TimeZone.setDefault(TIME_ZONE_MET);
1080         dateTimeParser.setTimeZone(TIME_ZONE_MET);
1081         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round(date4, Calendar.DATE), "round MET date across DST change-over");
1082         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round((Object) cal4, Calendar.DATE),
1083                 "round MET date across DST change-over");
1084         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round(date5, Calendar.DATE), "round MET date across DST change-over");
1085         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round((Object) cal5, Calendar.DATE),
1086                 "round MET date across DST change-over");
1087         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round(date6, Calendar.DATE), "round MET date across DST change-over");
1088         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round((Object) cal6, Calendar.DATE),
1089                 "round MET date across DST change-over");
1090         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round(date7, Calendar.DATE), "round MET date across DST change-over");
1091         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.round((Object) cal7, Calendar.DATE),
1092                 "round MET date across DST change-over");
1093 
1094         assertEquals(dateTimeParser.parse("March 30, 2003 01:00:00.000"), DateUtils.round(date4, Calendar.HOUR_OF_DAY),
1095                 "round MET date across DST change-over");
1096         assertEquals(dateTimeParser.parse("March 30, 2003 01:00:00.000"), DateUtils.round((Object) cal4, Calendar.HOUR_OF_DAY),
1097                 "round MET date across DST change-over");
1098         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.round(date5, Calendar.HOUR_OF_DAY),
1099                 "round MET date across DST change-over");
1100         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.round((Object) cal5, Calendar.HOUR_OF_DAY),
1101                 "round MET date across DST change-over");
1102         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.round(date6, Calendar.HOUR_OF_DAY),
1103                 "round MET date across DST change-over");
1104         assertEquals(dateTimeParser.parse("March 30, 2003 03:00:00.000"), DateUtils.round((Object) cal6, Calendar.HOUR_OF_DAY),
1105                 "round MET date across DST change-over");
1106         assertEquals(dateTimeParser.parse("March 30, 2003 04:00:00.000"), DateUtils.round(date7, Calendar.HOUR_OF_DAY),
1107                 "round MET date across DST change-over");
1108         assertEquals(dateTimeParser.parse("March 30, 2003 04:00:00.000"), DateUtils.round((Object) cal7, Calendar.HOUR_OF_DAY),
1109                 "round MET date across DST change-over");
1110     }
1111 
1112     /**
1113      * Tests the Changes Made by LANG-346 to the DateUtils.modify() private method invoked
1114      * by DateUtils.round().
1115      *
1116      * @throws Exception so we don't have to catch it
1117      */
1118     @Test
1119     void testRoundLang346() throws Exception {
1120         final Calendar testCalendar = Calendar.getInstance();
1121         testCalendar.set(2007, Calendar.JULY, 2, 8, 8, 50);
1122         Date date = testCalendar.getTime();
1123         assertEquals(dateTimeParser.parse("July 2, 2007 08:09:00.000"),
1124                 DateUtils.round(date, Calendar.MINUTE),
1125                 "Minute Round Up Failed");
1126 
1127         testCalendar.set(2007, Calendar.JULY, 2, 8, 8, 20);
1128         date = testCalendar.getTime();
1129         assertEquals(dateTimeParser.parse("July 2, 2007 08:08:00.000"),
1130                 DateUtils.round(date, Calendar.MINUTE),
1131                 "Minute No Round Failed");
1132 
1133         testCalendar.set(2007, Calendar.JULY, 2, 8, 8, 50);
1134         testCalendar.set(Calendar.MILLISECOND, 600);
1135         date = testCalendar.getTime();
1136 
1137         assertEquals(dateTimeParser.parse("July 2, 2007 08:08:51.000"),
1138                 DateUtils.round(date, Calendar.SECOND),
1139                 "Second Round Up with 600 Milli Seconds Failed");
1140 
1141         testCalendar.set(2007, Calendar.JULY, 2, 8, 8, 50);
1142         testCalendar.set(Calendar.MILLISECOND, 200);
1143         date = testCalendar.getTime();
1144         assertEquals(dateTimeParser.parse("July 2, 2007 08:08:50.000"),
1145                 DateUtils.round(date, Calendar.SECOND),
1146                 "Second Round Down with 200 Milli Seconds Failed");
1147 
1148         testCalendar.set(2007, Calendar.JULY, 2, 8, 8, 20);
1149         testCalendar.set(Calendar.MILLISECOND, 600);
1150         date = testCalendar.getTime();
1151         assertEquals(dateTimeParser.parse("July 2, 2007 08:08:21.000"),
1152                 DateUtils.round(date, Calendar.SECOND),
1153                 "Second Round Up with 200 Milli Seconds Failed");
1154 
1155         testCalendar.set(2007, Calendar.JULY, 2, 8, 8, 20);
1156         testCalendar.set(Calendar.MILLISECOND, 200);
1157         date = testCalendar.getTime();
1158         assertEquals(dateTimeParser.parse("July 2, 2007 08:08:20.000"),
1159                 DateUtils.round(date, Calendar.SECOND),
1160                 "Second Round Down with 200 Milli Seconds Failed");
1161 
1162         testCalendar.set(2007, Calendar.JULY, 2, 8, 8, 50);
1163         date = testCalendar.getTime();
1164         assertEquals(dateTimeParser.parse("July 2, 2007 08:00:00.000"),
1165                 DateUtils.round(date, Calendar.HOUR),
1166                 "Hour Round Down Failed");
1167 
1168         testCalendar.set(2007, Calendar.JULY, 2, 8, 31, 50);
1169         date = testCalendar.getTime();
1170         assertEquals(dateTimeParser.parse("July 2, 2007 09:00:00.000"),
1171                 DateUtils.round(date, Calendar.HOUR),
1172                 "Hour Round Up Failed");
1173     }
1174 
1175     @Test
1176     void testSetDays() throws Exception {
1177         Date result = DateUtils.setDays(BASE_DATE, 1);
1178         assertNotSame(BASE_DATE, result);
1179         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1180         assertDate(result, 2000, 6, 1, 4, 3, 2, 1);
1181         result = DateUtils.setDays(BASE_DATE, 29);
1182         assertNotSame(BASE_DATE, result);
1183         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1184         assertDate(result, 2000, 6, 29, 4, 3, 2, 1);
1185         final String outsideOfRangeAssertionMessage = "DateUtils.setDays did not throw an expected IllegalArgumentException for amount outside of range 1 to 31.";
1186         assertIllegalArgumentException(() -> DateUtils.setDays(BASE_DATE, 32), outsideOfRangeAssertionMessage);
1187         assertIllegalArgumentException(() -> DateUtils.setDays(BASE_DATE, 0), outsideOfRangeAssertionMessage);
1188         assertNullPointerException(() -> DateUtils.setDays(null, 1));
1189     }
1190 
1191     @Test
1192     void testSetHours() throws Exception {
1193         Date result = DateUtils.setHours(BASE_DATE, 0);
1194         assertNotSame(BASE_DATE, result);
1195         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1196         assertDate(result, 2000, 6, 5, 0, 3, 2, 1);
1197         result = DateUtils.setHours(BASE_DATE, 23);
1198         assertNotSame(BASE_DATE, result);
1199         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1200         assertDate(result, 2000, 6, 5, 23, 3, 2, 1);
1201         final String outsideOfRangeAssertionMessage = "DateUtils.setHours did not throw an expected IllegalArgumentException for amount outside of range 0 to 23.";
1202         assertIllegalArgumentException(() -> DateUtils.setHours(BASE_DATE, 24), outsideOfRangeAssertionMessage);
1203         assertIllegalArgumentException(() -> DateUtils.setHours(BASE_DATE, -1), outsideOfRangeAssertionMessage);
1204         assertNullPointerException(() -> DateUtils.setHours(null, 0));
1205     }
1206 
1207     @Test
1208     void testSetMilliseconds() throws Exception {
1209         Date result = DateUtils.setMilliseconds(BASE_DATE, 0);
1210         assertNotSame(BASE_DATE, result);
1211         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1212         assertDate(result, 2000, 6, 5, 4, 3, 2, 0);
1213         result = DateUtils.setMilliseconds(BASE_DATE, 999);
1214         assertNotSame(BASE_DATE, result);
1215         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1216         assertDate(result, 2000, 6, 5, 4, 3, 2, 999);
1217         final String outsideOfRangeAssertionMessage = "DateUtils.setMilliseconds did not throw an expected IllegalArgumentException for range outside of 0 to 999.";
1218         assertIllegalArgumentException(() -> DateUtils.setMilliseconds(BASE_DATE, 1000), outsideOfRangeAssertionMessage);
1219         assertIllegalArgumentException(() -> DateUtils.setMilliseconds(BASE_DATE, -1), outsideOfRangeAssertionMessage);
1220         assertNullPointerException(() -> DateUtils.setMilliseconds(null, 0));
1221     }
1222 
1223     @Test
1224     void testSetMinutes() throws Exception {
1225         Date result = DateUtils.setMinutes(BASE_DATE, 0);
1226         assertNotSame(BASE_DATE, result);
1227         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1228         assertDate(result, 2000, 6, 5, 4, 0, 2, 1);
1229         result = DateUtils.setMinutes(BASE_DATE, 59);
1230         assertNotSame(BASE_DATE, result);
1231         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1232         assertDate(result, 2000, 6, 5, 4, 59, 2, 1);
1233         final String outsideOfRangeAssertionMessage = "DateUtils.setMinutes did not throw an expected IllegalArgumentException for amount outside of range 0 to 59.";
1234         assertIllegalArgumentException(() -> DateUtils.setMinutes(BASE_DATE, 60), outsideOfRangeAssertionMessage);
1235         assertIllegalArgumentException(() -> DateUtils.setMinutes(BASE_DATE, -1), outsideOfRangeAssertionMessage);
1236         assertNullPointerException(() -> DateUtils.setMinutes(null, 0));
1237     }
1238 
1239     @Test
1240     void testSetMonths() throws Exception {
1241         Date result = DateUtils.setMonths(BASE_DATE, 5);
1242         assertNotSame(BASE_DATE, result);
1243         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1244         assertDate(result, 2000, 5, 5, 4, 3, 2, 1);
1245         result = DateUtils.setMonths(BASE_DATE, 1);
1246         assertNotSame(BASE_DATE, result);
1247         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1248         assertDate(result, 2000, 1, 5, 4, 3, 2, 1);
1249         result = DateUtils.setMonths(BASE_DATE, 0);
1250         assertNotSame(BASE_DATE, result);
1251         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1252         assertDate(result, 2000, 0, 5, 4, 3, 2, 1);
1253         final String outsideOfRangeAssertionMessage = "DateUtils.setMonths did not throw an expected IllegalArgumentException for amount outside of range 0 to 11.";
1254         assertIllegalArgumentException(() -> DateUtils.setMonths(BASE_DATE, 12), outsideOfRangeAssertionMessage);
1255         assertIllegalArgumentException(() -> DateUtils.setMonths(BASE_DATE, -1), outsideOfRangeAssertionMessage);
1256         assertNullPointerException(() -> DateUtils.setMonths(null, 0));
1257     }
1258 
1259     @Test
1260     void testSetSeconds() throws Exception {
1261         Date result = DateUtils.setSeconds(BASE_DATE, 0);
1262         assertNotSame(BASE_DATE, result);
1263         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1264         assertDate(result, 2000, 6, 5, 4, 3, 0, 1);
1265         result = DateUtils.setSeconds(BASE_DATE, 59);
1266         assertNotSame(BASE_DATE, result);
1267         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1268         assertDate(result, 2000, 6, 5, 4, 3, 59, 1);
1269         final String outsideOfRangeAssertionMessage = "DateUtils.setSeconds did not throw an expected IllegalArgumentException for amount outside of range 0 to 59.";
1270         assertIllegalArgumentException(() -> DateUtils.setSeconds(BASE_DATE, 60), outsideOfRangeAssertionMessage);
1271         assertIllegalArgumentException(() -> DateUtils.setSeconds(BASE_DATE, -1), outsideOfRangeAssertionMessage);
1272         assertNullPointerException(() -> DateUtils.setSeconds(null, 0));
1273     }
1274 
1275     @Test
1276     void testSetYears() throws Exception {
1277         Date result = DateUtils.setYears(BASE_DATE, 2000);
1278         assertNotSame(BASE_DATE, result);
1279         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1280         assertDate(result, 2000, 6, 5, 4, 3, 2, 1);
1281 
1282         result = DateUtils.setYears(BASE_DATE, 2008);
1283         assertNotSame(BASE_DATE, result);
1284         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1285         assertDate(result, 2008, 6, 5, 4, 3, 2, 1);
1286 
1287         result = DateUtils.setYears(BASE_DATE, 2005);
1288         assertNotSame(BASE_DATE, result);
1289         assertDate(BASE_DATE, 2000, 6, 5, 4, 3, 2, 1);
1290         assertDate(result, 2005, 6, 5, 4, 3, 2, 1);
1291 
1292         assertNullPointerException(() -> DateUtils.setYears(null, 0));
1293     }
1294 
1295     @Test
1296     void testToCalendar() {
1297         assertEquals(date1, DateUtils.toCalendar(date1).getTime(), "Failed to convert to a Calendar and back");
1298         assertNullPointerException(() -> DateUtils.toCalendar(null));
1299     }
1300 
1301     @Test
1302     void testToCalendarWithDateAndTimeZoneNotNull() {
1303         final Calendar c = DateUtils.toCalendar(date2, TIME_ZONE_DEFAULT);
1304         assertEquals(date2, c.getTime(), "Convert Date and TimeZone to a Calendar, but failed to get the Date back");
1305         assertEquals(TIME_ZONE_DEFAULT, c.getTimeZone(), "Convert Date and TimeZone to a Calendar, but failed to get the TimeZone back");
1306     }
1307 
1308     @Test
1309     void testToCalendarWithDateAndTimeZoneNull() {
1310         assertNullPointerException(() -> DateUtils.toCalendar(null, null));
1311     }
1312 
1313     @Test
1314     void testToCalendarWithDateNull() {
1315         assertNullPointerException(() -> DateUtils.toCalendar(null, TIME_ZONE_MET));
1316     }
1317 
1318     @Test
1319     void testToCalendarWithTimeZoneNull() {
1320         assertNullPointerException(() -> DateUtils.toCalendar(date1, null));
1321     }
1322 
1323     @ParameterizedTest
1324     @MethodSource("testToLocalDateTimeTimeZone")
1325     @DefaultLocale(language = "en", country = "US")
1326     @DefaultTimeZone(TimeZones.GMT_ID)
1327     void testToLocalDateTime(final LocalDateTime expected, final Date date, final TimeZone timeZone) {
1328         assertEquals(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()), DateUtils.toLocalDateTime(date),
1329                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1330     }
1331 
1332     @ParameterizedTest
1333     @MethodSource("testToLocalDateTimeTimeZone")
1334     @DefaultLocale(language = "en", country = "US")
1335     @DefaultTimeZone(TimeZones.GMT_ID)
1336     void testToLocalDateTimeTimeZone(final LocalDateTime expected, final Date date, final TimeZone timeZone) {
1337         assertEquals(expected, DateUtils.toLocalDateTime(date, timeZone),
1338                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1339     }
1340 
1341     @ParameterizedTest
1342     @MethodSource("testToLocalDateTimeTimeZone")
1343     @DefaultLocale(language = "en", country = "US")
1344     @DefaultTimeZone(TimeZones.GMT_ID)
1345     void testToOffsetDateTime(final LocalDateTime expected, final Date date, final TimeZone timeZone) {
1346         final OffsetDateTime offsetDateTime = DateUtils.toOffsetDateTime(date);
1347         assertEquals(OffsetDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()), offsetDateTime,
1348                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1349     }
1350 
1351     @ParameterizedTest
1352     @MethodSource("testToLocalDateTimeTimeZone")
1353     @DefaultLocale(language = "en", country = "US")
1354     @DefaultTimeZone(TimeZones.GMT_ID)
1355     void testToOffsetDateTimeTimeZone(final LocalDateTime expected, final Date date, final TimeZone timeZone) {
1356         assertEquals(expected, DateUtils.toOffsetDateTime(date, timeZone).toLocalDateTime(),
1357                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1358     }
1359 
1360     @ParameterizedTest
1361     @MethodSource("testToLocalDateTimeTimeZone")
1362     @DefaultLocale(language = "en", country = "US")
1363     @DefaultTimeZone(TimeZones.GMT_ID)
1364     void testToZonedDateTime(final LocalDateTime expected, final Date date, final TimeZone timeZone) {
1365         final ZonedDateTime zonedDateTime = DateUtils.toZonedDateTime(date);
1366         assertEquals(ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()), zonedDateTime,
1367                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1368         // Using atZone()
1369         assertEquals(date.toInstant().atZone(ZoneId.systemDefault()), zonedDateTime,
1370                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1371     }
1372 
1373     @ParameterizedTest
1374     @MethodSource("testToLocalDateTimeTimeZone")
1375     @DefaultLocale(language = "en", country = "US")
1376     @DefaultTimeZone(TimeZones.GMT_ID)
1377     void testToZonedDateTimeTimeZone(final LocalDateTime expected, final Date date, final TimeZone timeZone) {
1378         final ZonedDateTime zonedDateTime = DateUtils.toZonedDateTime(date, timeZone);
1379         assertEquals(expected, zonedDateTime.toOffsetDateTime().toLocalDateTime(),
1380                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1381         // Using atZone()
1382         assertEquals(date.toInstant().atZone(TimeZones.toTimeZone(timeZone).toZoneId()), zonedDateTime,
1383                 () -> String.format("expected = %s, date = %s, timeZone = %s, TimeZone.getDefault() = %s", expected, date, timeZone, TimeZone.getDefault()));
1384     }
1385 
1386     /**
1387      * Tests various values with the trunc method.
1388      *
1389      * @throws Exception so we don't have to catch it.
1390      */
1391     @Test
1392     void testTruncate() throws Exception {
1393         // tests public static Date truncate(Date date, int field)
1394         assertEquals(dateParser.parse("January 1, 2002"),
1395                 DateUtils.truncate(date1, Calendar.YEAR),
1396                 "truncate year-1 failed");
1397         assertEquals(dateParser.parse("January 1, 2001"),
1398                 DateUtils.truncate(date2, Calendar.YEAR),
1399                 "truncate year-2 failed");
1400         assertEquals(dateParser.parse("February 1, 2002"),
1401                 DateUtils.truncate(date1, Calendar.MONTH),
1402                 "truncate month-1 failed");
1403         assertEquals(dateParser.parse("November 1, 2001"),
1404                 DateUtils.truncate(date2, Calendar.MONTH),
1405                 "truncate month-2 failed");
1406         assertEquals(dateParser.parse("February 1, 2002"),
1407                 DateUtils.truncate(date1, DateUtils.SEMI_MONTH),
1408                 "truncate semimonth-1 failed");
1409         assertEquals(dateParser.parse("November 16, 2001"),
1410                 DateUtils.truncate(date2, DateUtils.SEMI_MONTH),
1411                 "truncate semimonth-2 failed");
1412         assertEquals(dateParser.parse("February 12, 2002"),
1413                 DateUtils.truncate(date1, Calendar.DATE),
1414                 "truncate date-1 failed");
1415         assertEquals(dateParser.parse("November 18, 2001"),
1416                 DateUtils.truncate(date2, Calendar.DATE),
1417                 "truncate date-2 failed");
1418         assertEquals(dateTimeParser.parse("February 12, 2002 12:00:00.000"),
1419                 DateUtils.truncate(date1, Calendar.HOUR),
1420                 "truncate hour-1 failed");
1421         assertEquals(dateTimeParser.parse("November 18, 2001 1:00:00.000"),
1422                 DateUtils.truncate(date2, Calendar.HOUR),
1423                 "truncate hour-2 failed");
1424         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:00.000"),
1425                 DateUtils.truncate(date1, Calendar.MINUTE),
1426                 "truncate minute-1 failed");
1427         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:00.000"),
1428                 DateUtils.truncate(date2, Calendar.MINUTE),
1429                 "truncate minute-2 failed");
1430         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:56.000"),
1431                 DateUtils.truncate(date1, Calendar.SECOND),
1432                 "truncate second-1 failed");
1433         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:11.000"),
1434                 DateUtils.truncate(date2, Calendar.SECOND),
1435                 "truncate second-2 failed");
1436         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"),
1437                 DateUtils.truncate(dateAmPm1, Calendar.AM_PM),
1438                 "truncate ampm-1 failed");
1439         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"),
1440                 DateUtils.truncate(dateAmPm2, Calendar.AM_PM),
1441                 "truncate ampm-2 failed");
1442         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
1443                 DateUtils.truncate(dateAmPm3, Calendar.AM_PM),
1444                 "truncate ampm-3 failed");
1445         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
1446                 DateUtils.truncate(dateAmPm4, Calendar.AM_PM),
1447                 "truncate ampm-4 failed");
1448 
1449         // tests public static Date truncate(Object date, int field)
1450         assertEquals(dateParser.parse("January 1, 2002"),
1451                 DateUtils.truncate((Object) date1, Calendar.YEAR),
1452                 "truncate year-1 failed");
1453         assertEquals(dateParser.parse("January 1, 2001"),
1454                 DateUtils.truncate((Object) date2, Calendar.YEAR),
1455                 "truncate year-2 failed");
1456         assertEquals(dateParser.parse("February 1, 2002"),
1457                 DateUtils.truncate((Object) date1, Calendar.MONTH),
1458                 "truncate month-1 failed");
1459         assertEquals(dateParser.parse("November 1, 2001"),
1460                 DateUtils.truncate((Object) date2, Calendar.MONTH),
1461                 "truncate month-2 failed");
1462         assertEquals(dateParser.parse("February 1, 2002"),
1463                 DateUtils.truncate((Object) date1, DateUtils.SEMI_MONTH),
1464                 "truncate semimonth-1 failed");
1465         assertEquals(dateParser.parse("November 16, 2001"),
1466                 DateUtils.truncate((Object) date2, DateUtils.SEMI_MONTH),
1467                 "truncate semimonth-2 failed");
1468         assertEquals(dateParser.parse("February 12, 2002"),
1469                 DateUtils.truncate((Object) date1, Calendar.DATE),
1470                 "truncate date-1 failed");
1471         assertEquals(dateParser.parse("November 18, 2001"),
1472                 DateUtils.truncate((Object) date2, Calendar.DATE),
1473                 "truncate date-2 failed");
1474         assertEquals(dateTimeParser.parse("February 12, 2002 12:00:00.000"),
1475                 DateUtils.truncate((Object) date1, Calendar.HOUR),
1476                 "truncate hour-1 failed");
1477         assertEquals(dateTimeParser.parse("November 18, 2001 1:00:00.000"),
1478                 DateUtils.truncate((Object) date2, Calendar.HOUR),
1479                 "truncate hour-2 failed");
1480         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:00.000"),
1481                 DateUtils.truncate((Object) date1, Calendar.MINUTE),
1482                 "truncate minute-1 failed");
1483         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:00.000"),
1484                 DateUtils.truncate((Object) date2, Calendar.MINUTE),
1485                 "truncate minute-2 failed");
1486         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:56.000"),
1487                 DateUtils.truncate((Object) date1, Calendar.SECOND),
1488                 "truncate second-1 failed");
1489         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:11.000"),
1490                 DateUtils.truncate((Object) date2, Calendar.SECOND),
1491                 "truncate second-2 failed");
1492         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"),
1493                 DateUtils.truncate((Object) dateAmPm1, Calendar.AM_PM),
1494                 "truncate ampm-1 failed");
1495         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"),
1496                 DateUtils.truncate((Object) dateAmPm2, Calendar.AM_PM),
1497                 "truncate ampm-2 failed");
1498         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
1499                 DateUtils.truncate((Object) dateAmPm3, Calendar.AM_PM),
1500                 "truncate ampm-3 failed");
1501         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
1502                 DateUtils.truncate((Object) dateAmPm4, Calendar.AM_PM),
1503                 "truncate ampm-4 failed");
1504 
1505         assertEquals(dateTimeParser.parse("February 12, 2002 12:34:56.000"),
1506                 DateUtils.truncate((Object) cal1, Calendar.SECOND),
1507                 "truncate calendar second-1 failed");
1508         assertEquals(dateTimeParser.parse("November 18, 2001 1:23:11.000"),
1509                 DateUtils.truncate((Object) cal2, Calendar.SECOND),
1510                 "truncate calendar second-2 failed");
1511 
1512         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"),
1513                 DateUtils.truncate((Object) calAmPm1, Calendar.AM_PM),
1514                 "truncate ampm-1 failed");
1515         assertEquals(dateTimeParser.parse("February 3, 2002 00:00:00.000"),
1516                 DateUtils.truncate((Object) calAmPm2, Calendar.AM_PM),
1517                 "truncate ampm-2 failed");
1518         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
1519                 DateUtils.truncate((Object) calAmPm3, Calendar.AM_PM),
1520                 "truncate ampm-3 failed");
1521         assertEquals(dateTimeParser.parse("February 3, 2002 12:00:00.000"),
1522                 DateUtils.truncate((Object) calAmPm4, Calendar.AM_PM),
1523                 "truncate ampm-4 failed");
1524 
1525         assertNullPointerException(() -> DateUtils.truncate((Date) null, Calendar.SECOND));
1526         assertNullPointerException(() -> DateUtils.truncate((Calendar) null, Calendar.SECOND));
1527         assertNullPointerException(() -> DateUtils.truncate((Object) null, Calendar.SECOND));
1528         assertThrows(ClassCastException.class, () -> DateUtils.truncate("", Calendar.SECOND));
1529 
1530     }
1531 
1532     /**
1533      * Tests various values with the trunc method
1534      *
1535      * @throws Exception so we don't have to catch it
1536      */
1537     @Test
1538     void testTruncate_Bugzilla_25560() throws Exception {
1539         // Fix for https://issues.apache.org/bugzilla/show_bug.cgi?id=25560
1540         // Test truncate across beginning of daylight saving time
1541         TimeZone.setDefault(TIME_ZONE_MET);
1542         dateTimeParser.setTimeZone(TIME_ZONE_MET);
1543         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.truncate(date3, Calendar.DATE), "truncate MET date across DST change-over");
1544         assertEquals(dateTimeParser.parse("March 30, 2003 00:00:00.000"), DateUtils.truncate((Object) cal3, Calendar.DATE),
1545                 "truncate MET date across DST change-over");
1546         // Test truncate across end of daylight saving time
1547         assertEquals(dateTimeParser.parse("October 26, 2003 00:00:00.000"), DateUtils.truncate(date8, Calendar.DATE),
1548                 "truncate MET date across DST change-over");
1549         assertEquals(dateTimeParser.parse("October 26, 2003 00:00:00.000"), DateUtils.truncate((Object) cal8, Calendar.DATE),
1550                 "truncate MET date across DST change-over");
1551     }
1552 
1553     /**
1554      * Tests various values with the trunc method
1555      *
1556      * @throws Exception so we don't have to catch it
1557      */
1558     @Test
1559     void testTruncate_Bugzilla_31395() throws Exception {
1560         // Bug 31395, large dates
1561         final Date endOfTime = new Date(Long.MAX_VALUE); // fyi: Sun Aug 17 07:12:55 CET 292278994 -- 807 millis
1562         final GregorianCalendar endCal = new GregorianCalendar();
1563         endCal.setTime(endOfTime);
1564         assertThrows(ArithmeticException.class, () -> DateUtils.truncate(endCal, Calendar.DATE));
1565         endCal.set(Calendar.YEAR, 280000001);
1566         assertThrows(ArithmeticException.class, () -> DateUtils.truncate(endCal, Calendar.DATE));
1567         endCal.set(Calendar.YEAR, 280000000);
1568         final Calendar cal = DateUtils.truncate(endCal, Calendar.DATE);
1569         assertEquals(0, cal.get(Calendar.HOUR));
1570     }
1571 
1572     /**
1573      * Tests for LANG-59
1574      *
1575      * see https://issues.apache.org/jira/browse/LANG-59
1576      */
1577     @Test
1578     void testTruncateLang59() {
1579         // Set TimeZone to Mountain Time
1580         final TimeZone denverZone = TimeZone.getTimeZone("America/Denver");
1581         TimeZone.setDefault(denverZone);
1582         final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS XXX");
1583         format.setTimeZone(denverZone);
1584         final Date oct31_01MDT = new Date(1099206000000L);
1585         final Date oct31MDT = new Date(oct31_01MDT.getTime() - 3600000L); // - 1 hour
1586         final Date oct31_01_02MDT = new Date(oct31_01MDT.getTime() + 120000L); // + 2 minutes
1587         final Date oct31_01_02_03MDT = new Date(oct31_01_02MDT.getTime() + 3000L); // + 3 seconds
1588         final Date oct31_01_02_03_04MDT = new Date(oct31_01_02_03MDT.getTime() + 4L); // + 4 milliseconds
1589         assertEquals("2004-10-31 00:00:00.000 -06:00", format.format(oct31MDT), "Check 00:00:00.000");
1590         assertEquals("2004-10-31 01:00:00.000 -06:00", format.format(oct31_01MDT), "Check 01:00:00.000");
1591         assertEquals("2004-10-31 01:02:00.000 -06:00", format.format(oct31_01_02MDT), "Check 01:02:00.000");
1592         assertEquals("2004-10-31 01:02:03.000 -06:00", format.format(oct31_01_02_03MDT), "Check 01:02:03.000");
1593         assertEquals("2004-10-31 01:02:03.004 -06:00", format.format(oct31_01_02_03_04MDT), "Check 01:02:03.004");
1594         // Demonstrate Problem
1595         final Calendar gval = Calendar.getInstance();
1596         gval.setTime(new Date(oct31_01MDT.getTime()));
1597         gval.set(Calendar.MINUTE, gval.get(Calendar.MINUTE)); // set minutes to the same value
1598         assertEquals(gval.getTime().getTime(), oct31_01MDT.getTime() + 3600000L, "Demonstrate Problem");
1599         // Test Truncate
1600         assertEquals(oct31_01_02_03_04MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.MILLISECOND), "Truncate Calendar.MILLISECOND");
1601         assertEquals(oct31_01_02_03MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.SECOND), "Truncate Calendar.SECOND");
1602         assertEquals(oct31_01_02MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.MINUTE), "Truncate Calendar.MINUTE");
1603         assertEquals(oct31_01MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.HOUR_OF_DAY), "Truncate Calendar.HOUR_OF_DAY");
1604         assertEquals(oct31_01MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.HOUR), "Truncate Calendar.HOUR");
1605         assertEquals(oct31MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.DATE), "Truncate Calendar.DATE");
1606         // Test Round (down)
1607         assertEquals(oct31_01_02_03_04MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.MILLISECOND), "Round Calendar.MILLISECOND");
1608         assertEquals(oct31_01_02_03MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.SECOND), "Round Calendar.SECOND");
1609         assertEquals(oct31_01_02MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.MINUTE), "Round Calendar.MINUTE");
1610         assertEquals(oct31_01MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.HOUR_OF_DAY), "Round Calendar.HOUR_OF_DAY");
1611         assertEquals(oct31_01MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.HOUR), "Round Calendar.HOUR");
1612         assertEquals(oct31MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.DATE), "Round Calendar.DATE");
1613     }
1614 
1615     /**
1616      * Tests the calendar iterator for week ranges
1617      */
1618     @Test
1619     void testWeekIterator() {
1620         final Calendar now = Calendar.getInstance();
1621         for (int i = 0; i < 7; i++) {
1622             final Calendar today = DateUtils.truncate(now, Calendar.DATE);
1623             final Calendar sunday = DateUtils.truncate(now, Calendar.DATE);
1624             sunday.add(Calendar.DATE, 1 - sunday.get(Calendar.DAY_OF_WEEK));
1625             final Calendar monday = DateUtils.truncate(now, Calendar.DATE);
1626             if (monday.get(Calendar.DAY_OF_WEEK) == 1) {
1627                 // This is sunday... roll back 6 days
1628                 monday.add(Calendar.DATE, -6);
1629             } else {
1630                 monday.add(Calendar.DATE, 2 - monday.get(Calendar.DAY_OF_WEEK));
1631             }
1632             final Calendar centered = DateUtils.truncate(now, Calendar.DATE);
1633             centered.add(Calendar.DATE, -3);
1634 
1635             Iterator<?> it = DateUtils.iterator(now, DateUtils.RANGE_WEEK_SUNDAY);
1636             assertWeekIterator(it, sunday);
1637             it = DateUtils.iterator(now, DateUtils.RANGE_WEEK_MONDAY);
1638             assertWeekIterator(it, monday);
1639             it = DateUtils.iterator(now, DateUtils.RANGE_WEEK_RELATIVE);
1640             assertWeekIterator(it, today);
1641             it = DateUtils.iterator(now, DateUtils.RANGE_WEEK_CENTER);
1642             assertWeekIterator(it, centered);
1643 
1644             it = DateUtils.iterator((Object) now, DateUtils.RANGE_WEEK_CENTER);
1645             assertWeekIterator(it, centered);
1646             final Iterator<?> it2 = DateUtils.iterator((Object) now.getTime(), DateUtils.RANGE_WEEK_CENTER);
1647             assertWeekIterator(it2, centered);
1648             assertThrows(NoSuchElementException.class, it2::next);
1649             final Iterator<?> it3 = DateUtils.iterator(now, DateUtils.RANGE_WEEK_CENTER);
1650             it3.next();
1651             assertThrows(UnsupportedOperationException.class, it3::remove);
1652 
1653             now.add(Calendar.DATE, 1);
1654         }
1655     }
1656 
1657 }
1658