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