• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *  * Redistributions of source code must retain the above copyright notice,
10  *    this list of conditions and the following disclaimer.
11  *
12  *  * Redistributions in binary form must reproduce the above copyright notice,
13  *    this list of conditions and the following disclaimer in the documentation
14  *    and/or other materials provided with the distribution.
15  *
16  *  * Neither the name of JSR-310 nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package org.threeten.bp.chrono;
33 
34 import static org.testng.Assert.assertEquals;
35 import static org.testng.Assert.assertTrue;
36 
37 import java.io.ByteArrayInputStream;
38 import java.io.ByteArrayOutputStream;
39 import java.io.ObjectInputStream;
40 import java.io.ObjectOutputStream;
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.Locale;
44 import java.util.Map;
45 
46 import org.testng.Assert;
47 import org.testng.annotations.DataProvider;
48 import org.testng.annotations.Test;
49 import org.threeten.bp.Duration;
50 import org.threeten.bp.LocalDate;
51 import org.threeten.bp.LocalDateTime;
52 import org.threeten.bp.LocalTime;
53 import org.threeten.bp.format.ResolverStyle;
54 import org.threeten.bp.temporal.ChronoUnit;
55 import org.threeten.bp.temporal.Temporal;
56 import org.threeten.bp.temporal.TemporalAccessor;
57 import org.threeten.bp.temporal.TemporalAdjuster;
58 import org.threeten.bp.temporal.TemporalAmount;
59 import org.threeten.bp.temporal.TemporalField;
60 import org.threeten.bp.temporal.TemporalUnit;
61 import org.threeten.bp.temporal.ValueRange;
62 
63 /**
64  * Test assertions that must be true for all built-in chronologies.
65  */
66 @SuppressWarnings("rawtypes")
67 @Test
68 public class TestChronoLocalDateTime {
69     //-----------------------------------------------------------------------
70     // regular data factory for names and descriptions of available calendars
71     //-----------------------------------------------------------------------
72     @DataProvider(name = "calendars")
data_of_calendars()73     Chronology[][] data_of_calendars() {
74         return new Chronology[][]{
75                     {HijrahChronology.INSTANCE},
76                     {IsoChronology.INSTANCE},
77                     {JapaneseChronology.INSTANCE},
78                     {MinguoChronology.INSTANCE},
79                     {ThaiBuddhistChronology.INSTANCE}};
80     }
81 
82     @Test(dataProvider="calendars")
test_badWithAdjusterChrono(Chronology chrono)83     public void test_badWithAdjusterChrono(Chronology chrono) {
84         LocalDate refDate = LocalDate.of(1900, 1, 1);
85         ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON);
86         for (Chronology[] clist : data_of_calendars()) {
87             Chronology chrono2 = clist[0];
88             ChronoLocalDateTime<?> cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON);
89             TemporalAdjuster adjuster = new FixedAdjuster(cdt2);
90             if (chrono != chrono2) {
91                 try {
92                     cdt.with(adjuster);
93                     Assert.fail("WithAdjuster should have thrown a ClassCastException, "
94                             + "required: " + cdt + ", supplied: " + cdt2);
95                 } catch (ClassCastException cce) {
96                     // Expected exception; not an error
97                 }
98             } else {
99                 // Same chronology,
100                 ChronoLocalDateTime<?> result = cdt.with(adjuster);
101                 assertEquals(result, cdt2, "WithAdjuster failed to replace date");
102             }
103         }
104     }
105 
106     @Test(dataProvider="calendars")
test_badPlusAdjusterChrono(Chronology chrono)107     public void test_badPlusAdjusterChrono(Chronology chrono) {
108         LocalDate refDate = LocalDate.of(1900, 1, 1);
109         ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON);
110         for (Chronology[] clist : data_of_calendars()) {
111             Chronology chrono2 = clist[0];
112             ChronoLocalDateTime<?> cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON);
113             TemporalAmount adjuster = new FixedAdjuster(cdt2);
114             if (chrono != chrono2) {
115                 try {
116                     cdt.plus(adjuster);
117                     Assert.fail("WithAdjuster should have thrown a ClassCastException, "
118                             + "required: " + cdt + ", supplied: " + cdt2);
119                 } catch (ClassCastException cce) {
120                     // Expected exception; not an error
121                 }
122             } else {
123                 // Same chronology,
124                 ChronoLocalDateTime<?> result = cdt.plus(adjuster);
125                 assertEquals(result, cdt2, "WithAdjuster failed to replace date time");
126             }
127         }
128     }
129 
130     @Test(dataProvider="calendars")
test_badMinusAdjusterChrono(Chronology chrono)131     public void test_badMinusAdjusterChrono(Chronology chrono) {
132         LocalDate refDate = LocalDate.of(1900, 1, 1);
133         ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON);
134         for (Chronology[] clist : data_of_calendars()) {
135             Chronology chrono2 = clist[0];
136             ChronoLocalDateTime<?> cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON);
137             TemporalAmount adjuster = new FixedAdjuster(cdt2);
138             if (chrono != chrono2) {
139                 try {
140                     cdt.minus(adjuster);
141                     Assert.fail("WithAdjuster should have thrown a ClassCastException, "
142                             + "required: " + cdt + ", supplied: " + cdt2);
143                 } catch (ClassCastException cce) {
144                     // Expected exception; not an error
145                 }
146             } else {
147                 // Same chronology,
148                 ChronoLocalDateTime<?> result = cdt.minus(adjuster);
149                 assertEquals(result, cdt2, "WithAdjuster failed to replace date");
150             }
151         }
152     }
153 
154     @Test(dataProvider="calendars")
test_badPlusPeriodUnitChrono(Chronology chrono)155     public void test_badPlusPeriodUnitChrono(Chronology chrono) {
156         LocalDate refDate = LocalDate.of(1900, 1, 1);
157         ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON);
158         for (Chronology[] clist : data_of_calendars()) {
159             Chronology chrono2 = clist[0];
160             ChronoLocalDateTime<?> cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON);
161             TemporalUnit adjuster = new FixedPeriodUnit(cdt2);
162             if (chrono != chrono2) {
163                 try {
164                     cdt.plus(1, adjuster);
165                     Assert.fail("PeriodUnit.doAdd plus should have thrown a ClassCastException" + cdt
166                             + ", can not be cast to " + cdt2);
167                 } catch (ClassCastException cce) {
168                     // Expected exception; not an error
169                 }
170             } else {
171                 // Same chronology,
172                 ChronoLocalDateTime<?> result = cdt.plus(1, adjuster);
173                 assertEquals(result, cdt2, "WithAdjuster failed to replace date");
174             }
175         }
176     }
177 
178     @Test(dataProvider="calendars")
test_badMinusPeriodUnitChrono(Chronology chrono)179     public void test_badMinusPeriodUnitChrono(Chronology chrono) {
180         LocalDate refDate = LocalDate.of(1900, 1, 1);
181         ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON);
182         for (Chronology[] clist : data_of_calendars()) {
183             Chronology chrono2 = clist[0];
184             ChronoLocalDateTime<?> cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON);
185             TemporalUnit adjuster = new FixedPeriodUnit(cdt2);
186             if (chrono != chrono2) {
187                 try {
188                     cdt.minus(1, adjuster);
189                     Assert.fail("PeriodUnit.doAdd minus should have thrown a ClassCastException" + cdt.getClass()
190                             + ", can not be cast to " + cdt2.getClass());
191                 } catch (ClassCastException cce) {
192                     // Expected exception; not an error
193                 }
194             } else {
195                 // Same chronology,
196                 ChronoLocalDateTime<?> result = cdt.minus(1, adjuster);
197                 assertEquals(result, cdt2, "WithAdjuster failed to replace date");
198             }
199         }
200     }
201 
202     @Test(dataProvider="calendars")
test_badDateTimeFieldChrono(Chronology chrono)203     public void test_badDateTimeFieldChrono(Chronology chrono) {
204         LocalDate refDate = LocalDate.of(1900, 1, 1);
205         ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON);
206         for (Chronology[] clist : data_of_calendars()) {
207             Chronology chrono2 = clist[0];
208             ChronoLocalDateTime<?> cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON);
209             TemporalField adjuster = new FixedDateTimeField(cdt2);
210             if (chrono != chrono2) {
211                 try {
212                     cdt.with(adjuster, 1);
213                     Assert.fail("DateTimeField doSet should have thrown a ClassCastException" + cdt.getClass()
214                             + ", can not be cast to " + cdt2.getClass());
215                 } catch (ClassCastException cce) {
216                     // Expected exception; not an error
217                 }
218             } else {
219                 // Same chronology,
220                 ChronoLocalDateTime<?> result = cdt.with(adjuster, 1);
221                 assertEquals(result, cdt2, "DateTimeField doSet failed to replace date");
222             }
223         }
224     }
225 
226     //-----------------------------------------------------------------------
227     // isBefore, isAfter, isEqual
228     //-----------------------------------------------------------------------
229     @Test(dataProvider="calendars")
test_datetime_comparisons(Chronology chrono)230     public void test_datetime_comparisons(Chronology chrono) {
231         List<ChronoLocalDateTime<?>> dates = new ArrayList<ChronoLocalDateTime<?>>();
232 
233         ChronoLocalDateTime<?> date = chrono.date(LocalDate.of(1900, 1, 1)).atTime(LocalTime.MIN);
234 
235         // Insert dates in order, no duplicates
236         if (chrono != JapaneseChronology.INSTANCE) {
237             dates.add(date.minus(100, ChronoUnit.YEARS));
238         }
239         dates.add(date.minus(1, ChronoUnit.YEARS));
240         dates.add(date.minus(1, ChronoUnit.MONTHS));
241         dates.add(date.minus(1, ChronoUnit.WEEKS));
242         dates.add(date.minus(1, ChronoUnit.DAYS));
243         dates.add(date.minus(1, ChronoUnit.HOURS));
244         dates.add(date.minus(1, ChronoUnit.MINUTES));
245         dates.add(date.minus(1, ChronoUnit.SECONDS));
246         dates.add(date.minus(1, ChronoUnit.NANOS));
247         dates.add(date);
248         dates.add(date.plus(1, ChronoUnit.NANOS));
249         dates.add(date.plus(1, ChronoUnit.SECONDS));
250         dates.add(date.plus(1, ChronoUnit.MINUTES));
251         dates.add(date.plus(1, ChronoUnit.HOURS));
252         dates.add(date.plus(1, ChronoUnit.DAYS));
253         dates.add(date.plus(1, ChronoUnit.WEEKS));
254         dates.add(date.plus(1, ChronoUnit.MONTHS));
255         dates.add(date.plus(1, ChronoUnit.YEARS));
256         dates.add(date.plus(100, ChronoUnit.YEARS));
257 
258         // Check these dates against the corresponding dates for every calendar
259         for (Chronology[] clist : data_of_calendars()) {
260             List<ChronoLocalDateTime<?>> otherDates = new ArrayList<ChronoLocalDateTime<?>>();
261             Chronology chrono2 = clist[0];
262             if (chrono2 == JapaneseChronology.INSTANCE) {
263                 continue;
264             }
265             for (ChronoLocalDateTime<?> d : dates) {
266                 otherDates.add(chrono2.date(d).atTime(d.toLocalTime()));
267             }
268 
269             // Now compare  the sequence of original dates with the sequence of converted dates
270             for (int i = 0; i < dates.size(); i++) {
271                 ChronoLocalDateTime<?> a = dates.get(i);
272                 for (int j = 0; j < otherDates.size(); j++) {
273                     ChronoLocalDateTime<?> b = otherDates.get(j);
274                     int cmp = ChronoLocalDateTime.timeLineOrder().compare(a, b);
275                     if (i < j) {
276                         assertTrue(cmp < 0, a + " compare " + b);
277                         assertEquals(a.isBefore(b), true, a + " isBefore " + b);
278                         assertEquals(a.isAfter(b), false, a + " isAfter " + b);
279                         assertEquals(a.isEqual(b), false, a + " isEqual " + b);
280                     } else if (i > j) {
281                         assertTrue(cmp > 0, a + " compare " + b);
282                         assertEquals(a.isBefore(b), false, a + " isBefore " + b);
283                         assertEquals(a.isAfter(b), true, a + " isAfter " + b);
284                         assertEquals(a.isEqual(b), false, a + " isEqual " + b);
285                     } else {
286                         assertTrue(cmp == 0, a + " compare " + b);
287                         assertEquals(a.isBefore(b), false, a + " isBefore " + b);
288                         assertEquals(a.isAfter(b), false, a + " isAfter " + b);
289                         assertEquals(a.isEqual(b), true, a + " isEqual " + b);
290                     }
291                 }
292             }
293         }
294     }
295 
296     //-----------------------------------------------------------------------
297     // Test Serialization of ISO via chrono API
298     //-----------------------------------------------------------------------
299     @Test( dataProvider="calendars")
test_ChronoLocalDateTimeSerialization(Chronology chrono)300     public void test_ChronoLocalDateTimeSerialization(Chronology chrono) throws Exception {
301         LocalDateTime ref = LocalDate.of(2000, 1, 5).atTime(12, 1, 2, 3);
302         ChronoLocalDateTime<?> orginal = chrono.date(ref).atTime(ref.toLocalTime());
303         ByteArrayOutputStream baos = new ByteArrayOutputStream();
304         ObjectOutputStream out = new ObjectOutputStream(baos);
305         out.writeObject(orginal);
306         out.close();
307         ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
308         ObjectInputStream in = new ObjectInputStream(bais);
309         ChronoLocalDateTime<?> ser = (ChronoLocalDateTime<?>) in.readObject();
310         assertEquals(ser, orginal, "deserialized date is wrong");
311     }
312 
313 
314     /**
315      * FixedAdjusted returns a fixed DateTime in all adjustments.
316      * Construct an adjuster with the DateTime that should be returned.
317      */
318     static class FixedAdjuster implements TemporalAdjuster, TemporalAmount {
319         private Temporal datetime;
320 
FixedAdjuster(Temporal datetime)321         FixedAdjuster(Temporal datetime) {
322             this.datetime = datetime;
323         }
324 
325         @Override
adjustInto(Temporal ignore)326         public Temporal adjustInto(Temporal ignore) {
327             return datetime;
328         }
329 
330         @Override
addTo(Temporal ignore)331         public Temporal addTo(Temporal ignore) {
332             return datetime;
333         }
334 
335         @Override
subtractFrom(Temporal ignore)336         public Temporal subtractFrom(Temporal ignore) {
337             return datetime;
338         }
339 
340         @Override
getUnits()341         public List<TemporalUnit> getUnits() {
342             throw new UnsupportedOperationException("Not supported yet.");
343         }
344 
345         @Override
get(TemporalUnit unit)346         public long get(TemporalUnit unit) {
347             throw new UnsupportedOperationException("Not supported yet.");
348         }
349     }
350 
351     /**
352      * FixedPeriodUnit returns a fixed DateTime in all adjustments.
353      * Construct an FixedPeriodUnit with the DateTime that should be returned.
354      */
355     static class FixedPeriodUnit implements TemporalUnit {
356         private Temporal dateTime;
357 
FixedPeriodUnit(Temporal dateTime)358         FixedPeriodUnit(Temporal dateTime) {
359             this.dateTime = dateTime;
360         }
361 
362         @Override
toString()363         public String toString() {
364             return "FixedPeriodUnit";
365         }
366 
367         @Override
getDuration()368         public Duration getDuration() {
369             throw new UnsupportedOperationException("Not supported yet.");
370         }
371 
372         @Override
isDurationEstimated()373         public boolean isDurationEstimated() {
374             throw new UnsupportedOperationException("Not supported yet.");
375         }
376 
377         @Override
isDateBased()378         public boolean isDateBased() {
379             throw new UnsupportedOperationException("Not supported yet.");
380         }
381 
382         @Override
isTimeBased()383         public boolean isTimeBased() {
384             throw new UnsupportedOperationException("Not supported yet.");
385         }
386 
387         @Override
isSupportedBy(Temporal dateTime)388         public boolean isSupportedBy(Temporal dateTime) {
389             throw new UnsupportedOperationException("Not supported yet.");
390         }
391 
392         @SuppressWarnings("unchecked")
393         @Override
addTo(R dateTime, long periodToAdd)394         public <R extends Temporal> R addTo(R dateTime, long periodToAdd) {
395             return (R) this.dateTime;
396         }
397 
398         @Override
between(Temporal temporal1, Temporal temporal2)399         public long between(Temporal temporal1, Temporal temporal2) {
400             throw new UnsupportedOperationException("Not supported yet.");
401         }
402     }
403 
404     /**
405      * FixedDateTimeField returns a fixed DateTime in all adjustments.
406      * Construct an FixedDateTimeField with the DateTime that should be returned from doSet.
407      */
408     static class FixedDateTimeField implements TemporalField {
409         private Temporal dateTime;
FixedDateTimeField(Temporal dateTime)410         FixedDateTimeField(Temporal dateTime) {
411             this.dateTime = dateTime;
412         }
413 
414         @Override
toString()415         public String toString() {
416             return "FixedDateTimeField";
417         }
418 
419         @Override
getBaseUnit()420         public TemporalUnit getBaseUnit() {
421             throw new UnsupportedOperationException("Not supported yet.");
422         }
423 
424         @Override
getRangeUnit()425         public TemporalUnit getRangeUnit() {
426             throw new UnsupportedOperationException("Not supported yet.");
427         }
428 
429         @Override
range()430         public ValueRange range() {
431             throw new UnsupportedOperationException("Not supported yet.");
432         }
433 
434         @Override
isDateBased()435         public boolean isDateBased() {
436             throw new UnsupportedOperationException("Not supported yet.");
437         }
438 
439         @Override
isTimeBased()440         public boolean isTimeBased() {
441             throw new UnsupportedOperationException("Not supported yet.");
442         }
443 
444         @Override
isSupportedBy(TemporalAccessor dateTime)445         public boolean isSupportedBy(TemporalAccessor dateTime) {
446             throw new UnsupportedOperationException("Not supported yet.");
447         }
448 
449         @Override
rangeRefinedBy(TemporalAccessor dateTime)450         public ValueRange rangeRefinedBy(TemporalAccessor dateTime) {
451             throw new UnsupportedOperationException("Not supported yet.");
452         }
453 
454         @Override
getFrom(TemporalAccessor dateTime)455         public long getFrom(TemporalAccessor dateTime) {
456             throw new UnsupportedOperationException("Not supported yet.");
457         }
458 
459         @SuppressWarnings("unchecked")
460         @Override
adjustInto(R dateTime, long newValue)461         public <R extends Temporal> R adjustInto(R dateTime, long newValue) {
462             return (R) this.dateTime;
463         }
464 
465         @Override
getDisplayName(Locale locale)466         public String getDisplayName(Locale locale) {
467             throw new UnsupportedOperationException("Not supported yet.");
468         }
469 
470         @Override
resolve(Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle)471         public TemporalAccessor resolve(Map<TemporalField, Long> fieldValues,
472                         TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
473             return null;
474         }
475     }
476 }
477