1 /*
2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * This file is available under and governed by the GNU General Public
26  * License version 2 only, as published by the Free Software Foundation.
27  * However, the following notice accompanied the original version of this
28  * file:
29  *
30  * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
31  *
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions are met:
36  *
37  *  * Redistributions of source code must retain the above copyright notice,
38  *    this list of conditions and the following disclaimer.
39  *
40  *  * Redistributions in binary form must reproduce the above copyright notice,
41  *    this list of conditions and the following disclaimer in the documentation
42  *    and/or other materials provided with the distribution.
43  *
44  *  * Neither the name of JSR-310 nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
51  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
52  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
53  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
56  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59  */
60 package tck.java.time;
61 
62 import static java.time.temporal.ChronoUnit.DAYS;
63 import static java.time.temporal.ChronoUnit.HOURS;
64 import static java.time.temporal.ChronoUnit.YEARS;
65 import static org.testng.Assert.assertEquals;
66 
67 import java.time.DateTimeException;
68 import java.time.Duration;
69 import java.time.LocalDate;
70 import java.time.Period;
71 import java.time.chrono.ThaiBuddhistChronology;
72 import java.time.format.DateTimeParseException;
73 import java.time.temporal.ChronoUnit;
74 import java.time.temporal.Temporal;
75 import java.time.temporal.TemporalAmount;
76 import java.time.temporal.TemporalUnit;
77 import java.util.ArrayList;
78 import java.util.Collections;
79 import java.util.List;
80 import java.util.Locale;
81 
82 import org.testng.annotations.DataProvider;
83 import org.testng.annotations.Test;
84 
85 /**
86  * Test Period.
87  */
88 @Test
89 public class TCKPeriod extends AbstractTCKTest {
90 
91     //-----------------------------------------------------------------------
92     // ofYears(int)
93     //-----------------------------------------------------------------------
94     @Test
factory_ofYears_int()95     public void factory_ofYears_int() {
96         assertPeriod(Period.ofYears(0), 0, 0, 0);
97         assertPeriod(Period.ofYears(1), 1, 0, 0);
98         assertPeriod(Period.ofYears(234), 234, 0, 0);
99         assertPeriod(Period.ofYears(-100), -100, 0, 0);
100         assertPeriod(Period.ofYears(Integer.MAX_VALUE), Integer.MAX_VALUE, 0, 0);
101         assertPeriod(Period.ofYears(Integer.MIN_VALUE), Integer.MIN_VALUE, 0, 0);
102     }
103 
104     //-----------------------------------------------------------------------
105     // ofMonths(int)
106     //-----------------------------------------------------------------------
107     @Test
factory_ofMonths_int()108     public void factory_ofMonths_int() {
109         assertPeriod(Period.ofMonths(0), 0, 0, 0);
110         assertPeriod(Period.ofMonths(1), 0, 1, 0);
111         assertPeriod(Period.ofMonths(234), 0, 234, 0);
112         assertPeriod(Period.ofMonths(-100), 0, -100, 0);
113         assertPeriod(Period.ofMonths(Integer.MAX_VALUE), 0, Integer.MAX_VALUE, 0);
114         assertPeriod(Period.ofMonths(Integer.MIN_VALUE), 0, Integer.MIN_VALUE, 0);
115     }
116 
117     //-----------------------------------------------------------------------
118     // ofWeeks(int)
119     //-----------------------------------------------------------------------
120     @Test
factory_ofWeeks_int()121     public void factory_ofWeeks_int() {
122         assertPeriod(Period.ofWeeks(0), 0, 0, 0);
123         assertPeriod(Period.ofWeeks(1), 0, 0, 7);
124         assertPeriod(Period.ofWeeks(234), 0, 0, 234 * 7);
125         assertPeriod(Period.ofWeeks(-100), 0, 0, -100 * 7);
126         assertPeriod(Period.ofWeeks(Integer.MAX_VALUE / 7), 0, 0, (Integer.MAX_VALUE / 7) * 7);
127         assertPeriod(Period.ofWeeks(Integer.MIN_VALUE / 7), 0, 0, (Integer.MIN_VALUE / 7) * 7);
128     }
129 
130     //-----------------------------------------------------------------------
131     // ofDays(int)
132     //-----------------------------------------------------------------------
133     @Test
factory_ofDays_int()134     public void factory_ofDays_int() {
135         assertPeriod(Period.ofDays(0), 0, 0, 0);
136         assertPeriod(Period.ofDays(1), 0, 0, 1);
137         assertPeriod(Period.ofDays(234), 0, 0, 234);
138         assertPeriod(Period.ofDays(-100), 0, 0, -100);
139         assertPeriod(Period.ofDays(Integer.MAX_VALUE), 0, 0, Integer.MAX_VALUE);
140         assertPeriod(Period.ofDays(Integer.MIN_VALUE), 0, 0, Integer.MIN_VALUE);
141     }
142 
143     //-----------------------------------------------------------------------
144     // of(int3)
145     //-----------------------------------------------------------------------
146     @Test
factory_of_ints()147     public void factory_of_ints() {
148         assertPeriod(Period.of(1, 2, 3), 1, 2, 3);
149         assertPeriod(Period.of(0, 2, 3), 0, 2, 3);
150         assertPeriod(Period.of(1, 0, 0), 1, 0, 0);
151         assertPeriod(Period.of(0, 0, 0), 0, 0, 0);
152         assertPeriod(Period.of(-1, -2, -3), -1, -2, -3);
153     }
154 
155     //-----------------------------------------------------------------------
156     // from(TemporalAmount)
157     //-----------------------------------------------------------------------
158     @Test
factory_from_TemporalAmount_Period()159     public void factory_from_TemporalAmount_Period() {
160         TemporalAmount amount = Period.of(1, 2, 3);
161         assertPeriod(Period.from(amount), 1, 2, 3);
162     }
163 
164     @Test
factory_from_TemporalAmount_YearsDays()165     public void factory_from_TemporalAmount_YearsDays() {
166         TemporalAmount amount = new TemporalAmount() {
167             @Override
168             public long get(TemporalUnit unit) {
169                 if (unit == YEARS) {
170                     return 23;
171                 } else {
172                     return 45;
173                 }
174             }
175             @Override
176             public List<TemporalUnit> getUnits() {
177                 List<TemporalUnit> list = new ArrayList<>();
178                 list.add(YEARS);
179                 list.add(DAYS);
180                 return list;
181             }
182             @Override
183             public Temporal addTo(Temporal temporal) {
184                 throw new UnsupportedOperationException();
185             }
186             @Override
187             public Temporal subtractFrom(Temporal temporal) {
188                 throw new UnsupportedOperationException();
189             }
190         };
191         assertPeriod(Period.from(amount), 23, 0, 45);
192     }
193 
194     @Test(expectedExceptions = ArithmeticException.class)
factory_from_TemporalAmount_Years_tooBig()195     public void factory_from_TemporalAmount_Years_tooBig() {
196         TemporalAmount amount = new TemporalAmount() {
197             @Override
198             public long get(TemporalUnit unit) {
199                 return ((long) (Integer.MAX_VALUE)) + 1;
200             }
201             @Override
202             public List<TemporalUnit> getUnits() {
203                 return Collections.<TemporalUnit>singletonList(YEARS);
204             }
205             @Override
206             public Temporal addTo(Temporal temporal) {
207                 throw new UnsupportedOperationException();
208             }
209             @Override
210             public Temporal subtractFrom(Temporal temporal) {
211                 throw new UnsupportedOperationException();
212             }
213         };
214         Period.from(amount);
215     }
216 
217     @Test(expectedExceptions = DateTimeException.class)
factory_from_TemporalAmount_DaysHours()218     public void factory_from_TemporalAmount_DaysHours() {
219         TemporalAmount amount = new TemporalAmount() {
220             @Override
221             public long get(TemporalUnit unit) {
222                 if (unit == DAYS) {
223                     return 1;
224                 } else {
225                     return 2;
226                 }
227             }
228             @Override
229             public List<TemporalUnit> getUnits() {
230                 List<TemporalUnit> list = new ArrayList<>();
231                 list.add(DAYS);
232                 list.add(HOURS);
233                 return list;
234             }
235             @Override
236             public Temporal addTo(Temporal temporal) {
237                 throw new UnsupportedOperationException();
238             }
239             @Override
240             public Temporal subtractFrom(Temporal temporal) {
241                 throw new UnsupportedOperationException();
242             }
243         };
244         Period.from(amount);
245     }
246 
247     @Test(expectedExceptions = DateTimeException.class)
factory_from_TemporalAmount_NonISO()248     public void factory_from_TemporalAmount_NonISO() {
249         Period.from(ThaiBuddhistChronology.INSTANCE.period(1, 1, 1));
250     }
251 
252     @Test(expectedExceptions = DateTimeException.class)
factory_from_TemporalAmount_Duration()253     public void factory_from_TemporalAmount_Duration() {
254         Period.from(Duration.ZERO);
255     }
256 
257     @Test(expectedExceptions = NullPointerException.class)
factory_from_TemporalAmount_null()258     public void factory_from_TemporalAmount_null() {
259         Period.from(null);
260     }
261 
262     //-----------------------------------------------------------------------
263     // parse(String)
264     //-----------------------------------------------------------------------
265     @DataProvider(name="parseSuccess")
data_factory_parseSuccess()266     Object[][] data_factory_parseSuccess() {
267         return new Object[][] {
268                 {"P1Y", Period.ofYears(1)},
269                 {"P12Y", Period.ofYears(12)},
270                 {"P987654321Y", Period.ofYears(987654321)},
271                 {"P+1Y", Period.ofYears(1)},
272                 {"P+12Y", Period.ofYears(12)},
273                 {"P+987654321Y", Period.ofYears(987654321)},
274                 {"P+0Y", Period.ofYears(0)},
275                 {"P0Y", Period.ofYears(0)},
276                 {"P-0Y", Period.ofYears(0)},
277                 {"P-25Y", Period.ofYears(-25)},
278                 {"P-987654321Y", Period.ofYears(-987654321)},
279                 {"P" + Integer.MAX_VALUE + "Y", Period.ofYears(Integer.MAX_VALUE)},
280                 {"P" + Integer.MIN_VALUE + "Y", Period.ofYears(Integer.MIN_VALUE)},
281 
282                 {"P1M", Period.ofMonths(1)},
283                 {"P12M", Period.ofMonths(12)},
284                 {"P987654321M", Period.ofMonths(987654321)},
285                 {"P+1M", Period.ofMonths(1)},
286                 {"P+12M", Period.ofMonths(12)},
287                 {"P+987654321M", Period.ofMonths(987654321)},
288                 {"P+0M", Period.ofMonths(0)},
289                 {"P0M", Period.ofMonths(0)},
290                 {"P-0M", Period.ofMonths(0)},
291                 {"P-25M", Period.ofMonths(-25)},
292                 {"P-987654321M", Period.ofMonths(-987654321)},
293                 {"P" + Integer.MAX_VALUE + "M", Period.ofMonths(Integer.MAX_VALUE)},
294                 {"P" + Integer.MIN_VALUE + "M", Period.ofMonths(Integer.MIN_VALUE)},
295 
296                 {"P1W", Period.ofDays(1 * 7)},
297                 {"P12W", Period.ofDays(12 * 7)},
298                 {"P7654321W", Period.ofDays(7654321 * 7)},
299                 {"P+1W", Period.ofDays(1 * 7)},
300                 {"P+12W", Period.ofDays(12 * 7)},
301                 {"P+7654321W", Period.ofDays(7654321 * 7)},
302                 {"P+0W", Period.ofDays(0)},
303                 {"P0W", Period.ofDays(0)},
304                 {"P-0W", Period.ofDays(0)},
305                 {"P-25W", Period.ofDays(-25 * 7)},
306                 {"P-7654321W", Period.ofDays(-7654321 * 7)},
307 
308                 {"P1D", Period.ofDays(1)},
309                 {"P12D", Period.ofDays(12)},
310                 {"P987654321D", Period.ofDays(987654321)},
311                 {"P+1D", Period.ofDays(1)},
312                 {"P+12D", Period.ofDays(12)},
313                 {"P+987654321D", Period.ofDays(987654321)},
314                 {"P+0D", Period.ofDays(0)},
315                 {"P0D", Period.ofDays(0)},
316                 {"P-0D", Period.ofDays(0)},
317                 {"P-25D", Period.ofDays(-25)},
318                 {"P-987654321D", Period.ofDays(-987654321)},
319                 {"P" + Integer.MAX_VALUE + "D", Period.ofDays(Integer.MAX_VALUE)},
320                 {"P" + Integer.MIN_VALUE + "D", Period.ofDays(Integer.MIN_VALUE)},
321 
322                 {"P0Y0M0D", Period.of(0, 0, 0)},
323                 {"P2Y0M0D", Period.of(2, 0, 0)},
324                 {"P0Y3M0D", Period.of(0, 3, 0)},
325                 {"P0Y0M4D", Period.of(0, 0, 4)},
326                 {"P2Y3M25D", Period.of(2, 3, 25)},
327                 {"P-2Y3M25D", Period.of(-2, 3, 25)},
328                 {"P2Y-3M25D", Period.of(2, -3, 25)},
329                 {"P2Y3M-25D", Period.of(2, 3, -25)},
330                 {"P-2Y-3M-25D", Period.of(-2, -3, -25)},
331 
332                 {"P0Y0M0W0D", Period.of(0, 0, 0)},
333                 {"P2Y3M4W25D", Period.of(2, 3, 4 * 7 + 25)},
334                 {"P-2Y-3M-4W-25D", Period.of(-2, -3, -4 * 7 - 25)},
335         };
336     }
337 
338     @Test(dataProvider="parseSuccess")
factory_parse(String text, Period expected)339     public void factory_parse(String text, Period expected) {
340         Period p = Period.parse(text);
341         assertEquals(p, expected);
342     }
343 
344     @Test(dataProvider="parseSuccess")
factory_parse_plus(String text, Period expected)345     public void factory_parse_plus(String text, Period expected) {
346         Period p = Period.parse("+" + text);
347         assertEquals(p, expected);
348     }
349 
350     @Test(dataProvider="parseSuccess")
factory_parse_minus(String text, Period expected)351     public void factory_parse_minus(String text, Period expected) {
352         Period p = null;
353         try {
354             p = Period.parse("-" + text);
355         } catch (DateTimeParseException ex) {
356             assertEquals(expected.getYears() == Integer.MIN_VALUE ||
357                     expected.getMonths() == Integer.MIN_VALUE ||
358                     expected.getDays() == Integer.MIN_VALUE, true);
359             return;
360         }
361         // not inside try/catch or it breaks test
362         assertEquals(p, expected.negated());
363     }
364 
365     @Test(dataProvider="parseSuccess")
factory_parse_lowerCase(String text, Period expected)366     public void factory_parse_lowerCase(String text, Period expected) {
367         Period p = Period.parse(text.toLowerCase(Locale.ENGLISH));
368         assertEquals(p, expected);
369     }
370 
371     @DataProvider(name="parseFailure")
data_parseFailure()372     Object[][] data_parseFailure() {
373         return new Object[][] {
374                 {""},
375                 {"PTD"},
376                 {"AT0D"},
377                 {"PA0D"},
378                 {"PT0A"},
379 
380                 {"PT+D"},
381                 {"PT-D"},
382                 {"PT.D"},
383                 {"PTAD"},
384 
385                 {"PT+0D"},
386                 {"PT-0D"},
387                 {"PT+1D"},
388                 {"PT-.D"},
389 
390                 {"P1Y1MT1D"},
391                 {"P1YMD"},
392                 {"P1Y2Y"},
393                 {"PT1M+3S"},
394 
395                 {"P1M2Y"},
396                 {"P1W2Y"},
397                 {"P1D2Y"},
398                 {"P1W2M"},
399                 {"P1D2M"},
400                 {"P1D2W"},
401 
402                 {"PT1S1"},
403                 {"PT1S."},
404                 {"PT1SA"},
405                 {"PT1M1"},
406                 {"PT1M."},
407                 {"PT1MA"},
408 
409                 {"P"+ (((long) Integer.MAX_VALUE) + 1) + "Y"},
410                 {"P"+ (((long) Integer.MAX_VALUE) + 1) + "M"},
411                 {"P"+ (((long) Integer.MAX_VALUE) + 1) + "D"},
412                 {"P"+ (((long) Integer.MIN_VALUE) - 1) + "Y"},
413                 {"P"+ (((long) Integer.MIN_VALUE) - 1) + "M"},
414                 {"P"+ (((long) Integer.MIN_VALUE) - 1) + "D"},
415 
416                 {"Rubbish"},
417         };
418     }
419 
420     @Test(dataProvider="parseFailure", expectedExceptions=DateTimeParseException.class)
factory_parseFailures(String text)421     public void factory_parseFailures(String text) {
422         try {
423             Period.parse(text);
424         } catch (DateTimeParseException ex) {
425             assertEquals(ex.getParsedString(), text);
426             throw ex;
427         }
428     }
429 
430     @Test(expectedExceptions=NullPointerException.class)
factory_parse_null()431     public void factory_parse_null() {
432         Period.parse(null);
433     }
434 
435     //-----------------------------------------------------------------------
436     // between(LocalDate,LocalDate)
437     //-----------------------------------------------------------------------
438     @DataProvider(name="between")
data_between()439     Object[][] data_between() {
440         return new Object[][] {
441                 {2010, 1, 1, 2010, 1, 1, 0, 0, 0},
442                 {2010, 1, 1, 2010, 1, 2, 0, 0, 1},
443                 {2010, 1, 1, 2010, 1, 31, 0, 0, 30},
444                 {2010, 1, 1, 2010, 2, 1, 0, 1, 0},
445                 {2010, 1, 1, 2010, 2, 28, 0, 1, 27},
446                 {2010, 1, 1, 2010, 3, 1, 0, 2, 0},
447                 {2010, 1, 1, 2010, 12, 31, 0, 11, 30},
448                 {2010, 1, 1, 2011, 1, 1, 1, 0, 0},
449                 {2010, 1, 1, 2011, 12, 31, 1, 11, 30},
450                 {2010, 1, 1, 2012, 1, 1, 2, 0, 0},
451 
452                 {2010, 1, 10, 2010, 1, 1, 0, 0, -9},
453                 {2010, 1, 10, 2010, 1, 2, 0, 0, -8},
454                 {2010, 1, 10, 2010, 1, 9, 0, 0, -1},
455                 {2010, 1, 10, 2010, 1, 10, 0, 0, 0},
456                 {2010, 1, 10, 2010, 1, 11, 0, 0, 1},
457                 {2010, 1, 10, 2010, 1, 31, 0, 0, 21},
458                 {2010, 1, 10, 2010, 2, 1, 0, 0, 22},
459                 {2010, 1, 10, 2010, 2, 9, 0, 0, 30},
460                 {2010, 1, 10, 2010, 2, 10, 0, 1, 0},
461                 {2010, 1, 10, 2010, 2, 28, 0, 1, 18},
462                 {2010, 1, 10, 2010, 3, 1, 0, 1, 19},
463                 {2010, 1, 10, 2010, 3, 9, 0, 1, 27},
464                 {2010, 1, 10, 2010, 3, 10, 0, 2, 0},
465                 {2010, 1, 10, 2010, 12, 31, 0, 11, 21},
466                 {2010, 1, 10, 2011, 1, 1, 0, 11, 22},
467                 {2010, 1, 10, 2011, 1, 9, 0, 11, 30},
468                 {2010, 1, 10, 2011, 1, 10, 1, 0, 0},
469 
470                 {2010, 3, 30, 2011, 5, 1, 1, 1, 1},
471                 {2010, 4, 30, 2011, 5, 1, 1, 0, 1},
472 
473                 {2010, 2, 28, 2012, 2, 27, 1, 11, 30},
474                 {2010, 2, 28, 2012, 2, 28, 2, 0, 0},
475                 {2010, 2, 28, 2012, 2, 29, 2, 0, 1},
476 
477                 {2012, 2, 28, 2014, 2, 27, 1, 11, 30},
478                 {2012, 2, 28, 2014, 2, 28, 2, 0, 0},
479                 {2012, 2, 28, 2014, 3, 1, 2, 0, 1},
480 
481                 {2012, 2, 29, 2014, 2, 28, 1, 11, 30},
482                 {2012, 2, 29, 2014, 3, 1, 2, 0, 1},
483                 {2012, 2, 29, 2014, 3, 2, 2, 0, 2},
484 
485                 {2012, 2, 29, 2016, 2, 28, 3, 11, 30},
486                 {2012, 2, 29, 2016, 2, 29, 4, 0, 0},
487                 {2012, 2, 29, 2016, 3, 1, 4, 0, 1},
488 
489                 {2010, 1, 1, 2009, 12, 31, 0, 0, -1},
490                 {2010, 1, 1, 2009, 12, 30, 0, 0, -2},
491                 {2010, 1, 1, 2009, 12, 2, 0, 0, -30},
492                 {2010, 1, 1, 2009, 12, 1, 0, -1, 0},
493                 {2010, 1, 1, 2009, 11, 30, 0, -1, -1},
494                 {2010, 1, 1, 2009, 11, 2, 0, -1, -29},
495                 {2010, 1, 1, 2009, 11, 1, 0, -2, 0},
496                 {2010, 1, 1, 2009, 1, 2, 0, -11, -30},
497                 {2010, 1, 1, 2009, 1, 1, -1, 0, 0},
498 
499                 {2010, 1, 15, 2010, 1, 15, 0, 0, 0},
500                 {2010, 1, 15, 2010, 1, 14, 0, 0, -1},
501                 {2010, 1, 15, 2010, 1, 1, 0, 0, -14},
502                 {2010, 1, 15, 2009, 12, 31, 0, 0, -15},
503                 {2010, 1, 15, 2009, 12, 16, 0, 0, -30},
504                 {2010, 1, 15, 2009, 12, 15, 0, -1, 0},
505                 {2010, 1, 15, 2009, 12, 14, 0, -1, -1},
506 
507                 {2010, 2, 28, 2009, 3, 1, 0, -11, -27},
508                 {2010, 2, 28, 2009, 2, 28, -1, 0, 0},
509                 {2010, 2, 28, 2009, 2, 27, -1, 0, -1},
510 
511                 {2010, 2, 28, 2008, 2, 29, -1, -11, -28},
512                 {2010, 2, 28, 2008, 2, 28, -2, 0, 0},
513                 {2010, 2, 28, 2008, 2, 27, -2, 0, -1},
514 
515                 {2012, 2, 29, 2009, 3, 1, -2, -11, -28},
516                 {2012, 2, 29, 2009, 2, 28, -3, 0, -1},
517                 {2012, 2, 29, 2009, 2, 27, -3, 0, -2},
518 
519                 {2012, 2, 29, 2008, 3, 1, -3, -11, -28},
520                 {2012, 2, 29, 2008, 2, 29, -4, 0, 0},
521                 {2012, 2, 29, 2008, 2, 28, -4, 0, -1},
522         };
523     }
524 
525     @Test(dataProvider="between")
factory_between_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de)526     public void factory_between_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) {
527         LocalDate start = LocalDate.of(y1, m1, d1);
528         LocalDate end = LocalDate.of(y2, m2, d2);
529         Period test = Period.between(start, end);
530         assertPeriod(test, ye, me, de);
531         //assertEquals(start.plus(test), end);
532     }
533 
534     @Test(expectedExceptions=NullPointerException.class)
factory_between_LocalDate_nullFirst()535     public void factory_between_LocalDate_nullFirst() {
536         Period.between((LocalDate) null, LocalDate.of(2010, 1, 1));
537     }
538 
539     @Test(expectedExceptions=NullPointerException.class)
factory_between_LocalDate_nullSecond()540     public void factory_between_LocalDate_nullSecond() {
541         Period.between(LocalDate.of(2010, 1, 1), (LocalDate) null);
542     }
543 
544     //-----------------------------------------------------------------------
545     // isZero()
546     //-----------------------------------------------------------------------
547     @Test
test_isZero()548     public void test_isZero() {
549         assertEquals(Period.of(0, 0, 0).isZero(), true);
550         assertEquals(Period.of(1, 2, 3).isZero(), false);
551         assertEquals(Period.of(1, 0, 0).isZero(), false);
552         assertEquals(Period.of(0, 2, 0).isZero(), false);
553         assertEquals(Period.of(0, 0, 3).isZero(), false);
554     }
555 
556     //-----------------------------------------------------------------------
557     // isNegative()
558     //-----------------------------------------------------------------------
559     @Test
test_isPositive()560     public void test_isPositive() {
561         assertEquals(Period.of(0, 0, 0).isNegative(), false);
562         assertEquals(Period.of(1, 2, 3).isNegative(), false);
563         assertEquals(Period.of(1, 0, 0).isNegative(), false);
564         assertEquals(Period.of(0, 2, 0).isNegative(), false);
565         assertEquals(Period.of(0, 0, 3).isNegative(), false);
566 
567         assertEquals(Period.of(-1, -2, -3).isNegative(), true);
568         assertEquals(Period.of(-1, -2, 3).isNegative(), true);
569         assertEquals(Period.of(1, -2, -3).isNegative(), true);
570         assertEquals(Period.of(-1, 2, -3).isNegative(), true);
571         assertEquals(Period.of(-1, 2, 3).isNegative(), true);
572         assertEquals(Period.of(1, -2, 3).isNegative(), true);
573         assertEquals(Period.of(1, 2, -3).isNegative(), true);
574     }
575 
576     //-----------------------------------------------------------------------
577     // withYears()
578     //-----------------------------------------------------------------------
579     @Test
test_withYears()580     public void test_withYears() {
581         assertPeriod(Period.of(1, 2, 3).withYears(1), 1, 2, 3);
582         assertPeriod(Period.of(1, 2, 3).withYears(10), 10, 2, 3);
583         assertPeriod(Period.of(1, 2, 3).withYears(-10), -10, 2, 3);
584         assertPeriod(Period.of(-1, -2, -3).withYears(10), 10, -2, -3);
585         assertPeriod(Period.of(1, 2, 3).withYears(0), 0, 2, 3);
586     }
587 
588     //-----------------------------------------------------------------------
589     // withMonths()
590     //-----------------------------------------------------------------------
591     @Test
test_withMonths()592     public void test_withMonths() {
593         assertPeriod(Period.of(1, 2, 3).withMonths(2), 1, 2, 3);
594         assertPeriod(Period.of(1, 2, 3).withMonths(10), 1, 10, 3);
595         assertPeriod(Period.of(1, 2, 3).withMonths(-10), 1, -10, 3);
596         assertPeriod(Period.of(-1, -2, -3).withMonths(10), -1, 10, -3);
597         assertPeriod(Period.of(1, 2, 3).withMonths(0), 1, 0, 3);
598     }
599 
600     //-----------------------------------------------------------------------
601     // withDays()
602     //-----------------------------------------------------------------------
603     @Test
test_withDays()604     public void test_withDays() {
605         assertPeriod(Period.of(1, 2, 3).withDays(3), 1, 2, 3);
606         assertPeriod(Period.of(1, 2, 3).withDays(10), 1, 2, 10);
607         assertPeriod(Period.of(1, 2, 3).withDays(-10), 1, 2, -10);
608         assertPeriod(Period.of(-1, -2, -3).withDays(10), -1, -2, 10);
609         assertPeriod(Period.of(1, 2, 3).withDays(0), 1, 2, 0);
610     }
611 
612     //-----------------------------------------------------------------------
613     // plus(Period)
614     //-----------------------------------------------------------------------
615     @DataProvider(name="plus")
data_plus()616     Object[][] data_plus() {
617         return new Object[][] {
618                 {pymd(0, 0, 0), pymd(0, 0, 0), pymd(0, 0, 0)},
619                 {pymd(0, 0, 0), pymd(5, 0, 0), pymd(5, 0, 0)},
620                 {pymd(0, 0, 0), pymd(-5, 0, 0), pymd(-5, 0, 0)},
621                 {pymd(0, 0, 0), pymd(0, 5, 0), pymd(0, 5, 0)},
622                 {pymd(0, 0, 0), pymd(0, -5, 0), pymd(0, -5, 0)},
623                 {pymd(0, 0, 0), pymd(0, 0, 5), pymd(0, 0, 5)},
624                 {pymd(0, 0, 0), pymd(0, 0, -5), pymd(0, 0, -5)},
625                 {pymd(0, 0, 0), pymd(2, 3, 4), pymd(2, 3, 4)},
626                 {pymd(0, 0, 0), pymd(-2, -3, -4), pymd(-2, -3, -4)},
627 
628                 {pymd(4, 5, 6), pymd(2, 3, 4), pymd(6, 8, 10)},
629                 {pymd(4, 5, 6), pymd(-2, -3, -4), pymd(2, 2, 2)},
630         };
631     }
632 
633     @Test(dataProvider="plus")
test_plus_TemporalAmount(Period base, Period add, Period expected)634     public void test_plus_TemporalAmount(Period base, Period add, Period expected) {
635         assertEquals(base.plus(add), expected);
636     }
637 
638     @Test(expectedExceptions = DateTimeException.class)
test_plus_TemporalAmount_nonISO()639     public void test_plus_TemporalAmount_nonISO() {
640         pymd(4, 5, 6).plus(ThaiBuddhistChronology.INSTANCE.period(1, 0, 0));
641     }
642 
643     @Test(expectedExceptions = DateTimeException.class)
test_plus_TemporalAmount_DaysHours()644     public void test_plus_TemporalAmount_DaysHours() {
645         TemporalAmount amount = new TemporalAmount() {
646             @Override
647             public long get(TemporalUnit unit) {
648                 if (unit == DAYS) {
649                     return 1;
650                 } else {
651                     return 2;
652                 }
653             }
654             @Override
655             public List<TemporalUnit> getUnits() {
656                 List<TemporalUnit> list = new ArrayList<>();
657                 list.add(DAYS);
658                 list.add(HOURS);
659                 return list;
660             }
661             @Override
662             public Temporal addTo(Temporal temporal) {
663                 throw new UnsupportedOperationException();
664             }
665             @Override
666             public Temporal subtractFrom(Temporal temporal) {
667                 throw new UnsupportedOperationException();
668             }
669         };
670         pymd(4, 5, 6).plus(amount);
671     }
672 
673     //-----------------------------------------------------------------------
674     // plusYears()
675     //-----------------------------------------------------------------------
676     @Test
test_plusYears()677     public void test_plusYears() {
678         assertPeriod(Period.of(1, 2, 3).plusYears(0), 1, 2, 3);
679         assertPeriod(Period.of(1, 2, 3).plusYears(10), 11, 2, 3);
680         assertPeriod(Period.of(1, 2, 3).plusYears(-10), -9, 2, 3);
681         assertPeriod(Period.of(1, 2, 3).plusYears(-1), 0, 2, 3);
682 
683         assertPeriod(Period.of(1, 2, 3).plus(Period.ofYears(0)), 1, 2, 3);
684         assertPeriod(Period.of(1, 2, 3).plus(Period.ofYears(10)), 11, 2, 3);
685         assertPeriod(Period.of(1, 2, 3).plus(Period.ofYears(-10)), -9, 2, 3);
686         assertPeriod(Period.of(1, 2, 3).plus(Period.ofYears(-1)), 0, 2, 3);
687     }
688 
689     @Test(expectedExceptions=ArithmeticException.class)
test_plusYears_overflowTooBig()690     public void test_plusYears_overflowTooBig() {
691         Period test = Period.ofYears(Integer.MAX_VALUE);
692         test.plusYears(1);
693     }
694 
695     @Test(expectedExceptions=ArithmeticException.class)
test_plusYears_overflowTooSmall()696     public void test_plusYears_overflowTooSmall() {
697         Period test = Period.ofYears(Integer.MIN_VALUE);
698         test.plusYears(-1);
699     }
700 
701     //-----------------------------------------------------------------------
702     // plusMonths()
703     //-----------------------------------------------------------------------
704     @Test
test_plusMonths()705     public void test_plusMonths() {
706         assertPeriod(Period.of(1, 2, 3).plusMonths(0), 1, 2, 3);
707         assertPeriod(Period.of(1, 2, 3).plusMonths(10), 1, 12, 3);
708         assertPeriod(Period.of(1, 2, 3).plusMonths(-10), 1, -8, 3);
709         assertPeriod(Period.of(1, 2, 3).plusMonths(-2), 1, 0, 3);
710 
711         assertPeriod(Period.of(1, 2, 3).plus(Period.ofMonths(0)), 1, 2, 3);
712         assertPeriod(Period.of(1, 2, 3).plus(Period.ofMonths(10)), 1, 12, 3);
713         assertPeriod(Period.of(1, 2, 3).plus(Period.ofMonths(-10)), 1, -8, 3);
714         assertPeriod(Period.of(1, 2, 3).plus(Period.ofMonths(-2)), 1, 0, 3);
715     }
716 
717     @Test(expectedExceptions=ArithmeticException.class)
test_plusMonths_overflowTooBig()718     public void test_plusMonths_overflowTooBig() {
719         Period test = Period.ofMonths(Integer.MAX_VALUE);
720         test.plusMonths(1);
721     }
722 
723     @Test(expectedExceptions=ArithmeticException.class)
test_plusMonths_overflowTooSmall()724     public void test_plusMonths_overflowTooSmall() {
725         Period test = Period.ofMonths(Integer.MIN_VALUE);
726         test.plusMonths(-1);
727     }
728 
729     //-----------------------------------------------------------------------
730     // plusDays()
731     //-----------------------------------------------------------------------
732     @Test
test_plusDays()733     public void test_plusDays() {
734         assertPeriod(Period.of(1, 2, 3).plusDays(0), 1, 2, 3);
735         assertPeriod(Period.of(1, 2, 3).plusDays(10), 1, 2, 13);
736         assertPeriod(Period.of(1, 2, 3).plusDays(-10), 1, 2, -7);
737         assertPeriod(Period.of(1, 2, 3).plusDays(-3), 1, 2, 0);
738 
739         assertPeriod(Period.of(1, 2, 3).plus(Period.ofDays(0)), 1, 2, 3);
740         assertPeriod(Period.of(1, 2, 3).plus(Period.ofDays(10)), 1, 2, 13);
741         assertPeriod(Period.of(1, 2, 3).plus(Period.ofDays(-10)), 1, 2, -7);
742         assertPeriod(Period.of(1, 2, 3).plus(Period.ofDays(-3)), 1, 2, 0);
743     }
744 
745     @Test(expectedExceptions=ArithmeticException.class)
test_plusDays_overflowTooBig()746     public void test_plusDays_overflowTooBig() {
747         Period test = Period.ofDays(Integer.MAX_VALUE);
748         test.plusDays(1);
749     }
750 
751     @Test(expectedExceptions=ArithmeticException.class)
test_plusDays_overflowTooSmall()752     public void test_plusDays_overflowTooSmall() {
753         Period test = Period.ofDays(Integer.MIN_VALUE);
754         test.plusDays(-1);
755     }
756 
757     //-----------------------------------------------------------------------
758     // minus(Period)
759     //-----------------------------------------------------------------------
760     @DataProvider(name="minus")
data_minus()761     Object[][] data_minus() {
762         return new Object[][] {
763                 {pymd(0, 0, 0), pymd(0, 0, 0), pymd(0, 0, 0)},
764                 {pymd(0, 0, 0), pymd(5, 0, 0), pymd(-5, 0, 0)},
765                 {pymd(0, 0, 0), pymd(-5, 0, 0), pymd(5, 0, 0)},
766                 {pymd(0, 0, 0), pymd(0, 5, 0), pymd(0, -5, 0)},
767                 {pymd(0, 0, 0), pymd(0, -5, 0), pymd(0, 5, 0)},
768                 {pymd(0, 0, 0), pymd(0, 0, 5), pymd(0, 0, -5)},
769                 {pymd(0, 0, 0), pymd(0, 0, -5), pymd(0, 0, 5)},
770                 {pymd(0, 0, 0), pymd(2, 3, 4), pymd(-2, -3, -4)},
771                 {pymd(0, 0, 0), pymd(-2, -3, -4), pymd(2, 3, 4)},
772 
773                 {pymd(4, 5, 6), pymd(2, 3, 4), pymd(2, 2, 2)},
774                 {pymd(4, 5, 6), pymd(-2, -3, -4), pymd(6, 8, 10)},
775         };
776     }
777 
778     @Test(dataProvider="minus")
test_minus_TemporalAmount(Period base, Period subtract, Period expected)779     public void test_minus_TemporalAmount(Period base, Period subtract, Period expected) {
780         assertEquals(base.minus(subtract), expected);
781     }
782 
783     @Test(expectedExceptions = DateTimeException.class)
test_minus_TemporalAmount_nonISO()784     public void test_minus_TemporalAmount_nonISO() {
785         pymd(4, 5, 6).minus(ThaiBuddhistChronology.INSTANCE.period(1, 0, 0));
786     }
787 
788     @Test(expectedExceptions = DateTimeException.class)
test_minus_TemporalAmount_DaysHours()789     public void test_minus_TemporalAmount_DaysHours() {
790         TemporalAmount amount = new TemporalAmount() {
791             @Override
792             public long get(TemporalUnit unit) {
793                 if (unit == DAYS) {
794                     return 1;
795                 } else {
796                     return 2;
797                 }
798             }
799             @Override
800             public List<TemporalUnit> getUnits() {
801                 List<TemporalUnit> list = new ArrayList<>();
802                 list.add(DAYS);
803                 list.add(HOURS);
804                 return list;
805             }
806             @Override
807             public Temporal addTo(Temporal temporal) {
808                 throw new UnsupportedOperationException();
809             }
810             @Override
811             public Temporal subtractFrom(Temporal temporal) {
812                 throw new UnsupportedOperationException();
813             }
814         };
815         pymd(4, 5, 6).minus(amount);
816     }
817 
818     //-----------------------------------------------------------------------
819     // minusYears()
820     //-----------------------------------------------------------------------
821     @Test
test_minusYears()822     public void test_minusYears() {
823         assertPeriod(Period.of(1, 2, 3).minusYears(0), 1, 2, 3);
824         assertPeriod(Period.of(1, 2, 3).minusYears(10), -9, 2, 3);
825         assertPeriod(Period.of(1, 2, 3).minusYears(-10), 11, 2, 3);
826         assertPeriod(Period.of(1, 2, 3).minusYears(-1), 2, 2, 3);
827 
828         assertPeriod(Period.of(1, 2, 3).minus(Period.ofYears(0)), 1, 2, 3);
829         assertPeriod(Period.of(1, 2, 3).minus(Period.ofYears(10)), -9, 2, 3);
830         assertPeriod(Period.of(1, 2, 3).minus(Period.ofYears(-10)), 11, 2, 3);
831         assertPeriod(Period.of(1, 2, 3).minus(Period.ofYears(-1)), 2, 2, 3);
832     }
833 
834     @Test(expectedExceptions=ArithmeticException.class)
test_minusYears_overflowTooBig()835     public void test_minusYears_overflowTooBig() {
836         Period test = Period.ofYears(Integer.MAX_VALUE);
837         test.minusYears(-1);
838     }
839 
840     @Test(expectedExceptions=ArithmeticException.class)
test_minusYears_overflowTooSmall()841     public void test_minusYears_overflowTooSmall() {
842         Period test = Period.ofYears(Integer.MIN_VALUE);
843         test.minusYears(1);
844     }
845 
846     //-----------------------------------------------------------------------
847     // minusMonths()
848     //-----------------------------------------------------------------------
849     @Test
test_minusMonths()850     public void test_minusMonths() {
851         assertPeriod(Period.of(1, 2, 3).minusMonths(0), 1, 2, 3);
852         assertPeriod(Period.of(1, 2, 3).minusMonths(10), 1, -8, 3);
853         assertPeriod(Period.of(1, 2, 3).minusMonths(-10), 1, 12, 3);
854         assertPeriod(Period.of(1, 2, 3).minusMonths(-2), 1, 4, 3);
855 
856         assertPeriod(Period.of(1, 2, 3).minus(Period.ofMonths(0)), 1, 2, 3);
857         assertPeriod(Period.of(1, 2, 3).minus(Period.ofMonths(10)), 1, -8, 3);
858         assertPeriod(Period.of(1, 2, 3).minus(Period.ofMonths(-10)), 1, 12, 3);
859         assertPeriod(Period.of(1, 2, 3).minus(Period.ofMonths(-2)), 1, 4, 3);
860     }
861 
862     @Test(expectedExceptions=ArithmeticException.class)
test_minusMonths_overflowTooBig()863     public void test_minusMonths_overflowTooBig() {
864         Period test = Period.ofMonths(Integer.MAX_VALUE);
865         test.minusMonths(-1);
866     }
867 
868     @Test(expectedExceptions=ArithmeticException.class)
test_minusMonths_overflowTooSmall()869     public void test_minusMonths_overflowTooSmall() {
870         Period test = Period.ofMonths(Integer.MIN_VALUE);
871         test.minusMonths(1);
872     }
873 
874     //-----------------------------------------------------------------------
875     // minusDays()
876     //-----------------------------------------------------------------------
877     @Test
test_minusDays()878     public void test_minusDays() {
879         assertPeriod(Period.of(1, 2, 3).minusDays(0), 1, 2, 3);
880         assertPeriod(Period.of(1, 2, 3).minusDays(10), 1, 2, -7);
881         assertPeriod(Period.of(1, 2, 3).minusDays(-10), 1, 2, 13);
882         assertPeriod(Period.of(1, 2, 3).minusDays(-3), 1, 2, 6);
883 
884         assertPeriod(Period.of(1, 2, 3).minus(Period.ofDays(0)), 1, 2, 3);
885         assertPeriod(Period.of(1, 2, 3).minus(Period.ofDays(10)), 1, 2, -7);
886         assertPeriod(Period.of(1, 2, 3).minus(Period.ofDays(-10)), 1, 2, 13);
887         assertPeriod(Period.of(1, 2, 3).minus(Period.ofDays(-3)), 1, 2, 6);
888     }
889 
890     @Test(expectedExceptions=ArithmeticException.class)
test_minusDays_overflowTooBig()891     public void test_minusDays_overflowTooBig() {
892         Period test = Period.ofDays(Integer.MAX_VALUE);
893         test.minusDays(-1);
894     }
895 
896     @Test(expectedExceptions=ArithmeticException.class)
test_minusDays_overflowTooSmall()897     public void test_minusDays_overflowTooSmall() {
898         Period test = Period.ofDays(Integer.MIN_VALUE);
899         test.minusDays(1);
900     }
901 
902     //-----------------------------------------------------------------------
903     // multipliedBy()
904     //-----------------------------------------------------------------------
905     @Test
test_multipliedBy()906     public void test_multipliedBy() {
907         Period test = Period.of(1, 2, 3);
908         assertPeriod(test.multipliedBy(0), 0, 0, 0);
909         assertPeriod(test.multipliedBy(1), 1, 2, 3);
910         assertPeriod(test.multipliedBy(2), 2, 4, 6);
911         assertPeriod(test.multipliedBy(-3), -3, -6, -9);
912     }
913 
914     @Test
test_multipliedBy_zeroBase()915     public void test_multipliedBy_zeroBase() {
916         assertPeriod(Period.ZERO.multipliedBy(2), 0, 0, 0);
917     }
918 
919     @Test(expectedExceptions=ArithmeticException.class)
test_multipliedBy_overflowTooBig()920     public void test_multipliedBy_overflowTooBig() {
921         Period test = Period.ofYears(Integer.MAX_VALUE / 2 + 1);
922         test.multipliedBy(2);
923     }
924 
925     @Test(expectedExceptions=ArithmeticException.class)
test_multipliedBy_overflowTooSmall()926     public void test_multipliedBy_overflowTooSmall() {
927         Period test = Period.ofYears(Integer.MIN_VALUE / 2 - 1);
928         test.multipliedBy(2);
929     }
930 
931     //-----------------------------------------------------------------------
932     // negated()
933     //-----------------------------------------------------------------------
934     @Test
test_negated()935     public void test_negated() {
936         assertPeriod(Period.of(0, 0, 0).negated(), 0 ,0, 0);
937         assertPeriod(Period.of(1, 2, 3).negated(), -1, -2, -3);
938         assertPeriod(Period.of(-1, -2, -3).negated(), 1, 2, 3);
939         assertPeriod(Period.of(-1, 2, -3).negated(), 1, -2, 3);
940         assertPeriod(Period.of(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).negated(),
941                 -Integer.MAX_VALUE, -Integer.MAX_VALUE, -Integer.MAX_VALUE);
942     }
943 
944     @Test(expectedExceptions=ArithmeticException.class)
test_negated_overflow_years()945     public void test_negated_overflow_years() {
946         Period.ofYears(Integer.MIN_VALUE).negated();
947     }
948 
949     @Test(expectedExceptions=ArithmeticException.class)
test_negated_overflow_months()950     public void test_negated_overflow_months() {
951         Period.ofMonths(Integer.MIN_VALUE).negated();
952     }
953 
954     @Test(expectedExceptions=ArithmeticException.class)
test_negated_overflow_days()955     public void test_negated_overflow_days() {
956         Period.ofDays(Integer.MIN_VALUE).negated();
957     }
958 
959     //-----------------------------------------------------------------------
960     // normalized()
961     //-----------------------------------------------------------------------
962     @DataProvider(name="normalized")
data_normalized()963     Object[][] data_normalized() {
964         return new Object[][] {
965                 {0, 0,  0, 0},
966                 {1, 0,  1, 0},
967                 {-1, 0,  -1, 0},
968 
969                 {1, 1,  1, 1},
970                 {1, 2,  1, 2},
971                 {1, 11,  1, 11},
972                 {1, 12,  2, 0},
973                 {1, 13,  2, 1},
974                 {1, 23,  2, 11},
975                 {1, 24,  3, 0},
976                 {1, 25,  3, 1},
977 
978                 {1, -1,  0, 11},
979                 {1, -2,  0, 10},
980                 {1, -11,  0, 1},
981                 {1, -12,  0, 0},
982                 {1, -13,  0, -1},
983                 {1, -23,  0, -11},
984                 {1, -24,  -1, 0},
985                 {1, -25,  -1, -1},
986                 {1, -35,  -1, -11},
987                 {1, -36,  -2, 0},
988                 {1, -37,  -2, -1},
989 
990                 {-1, 1,  0, -11},
991                 {-1, 11,  0, -1},
992                 {-1, 12,  0, 0},
993                 {-1, 13,  0, 1},
994                 {-1, 23,  0, 11},
995                 {-1, 24,  1, 0},
996                 {-1, 25,  1, 1},
997 
998                 {-1, -1,  -1, -1},
999                 {-1, -11,  -1, -11},
1000                 {-1, -12,  -2, 0},
1001                 {-1, -13,  -2, -1},
1002         };
1003     }
1004 
1005     @Test(dataProvider="normalized")
test_normalized(int inputYears, int inputMonths, int expectedYears, int expectedMonths)1006     public void test_normalized(int inputYears, int inputMonths, int expectedYears, int expectedMonths) {
1007         assertPeriod(Period.of(inputYears, inputMonths, 0).normalized(), expectedYears, expectedMonths, 0);
1008     }
1009 
1010     @Test(dataProvider="normalized")
test_normalized_daysUnaffected(int inputYears, int inputMonths, int expectedYears, int expectedMonths)1011     public void test_normalized_daysUnaffected(int inputYears, int inputMonths, int expectedYears, int expectedMonths) {
1012         assertPeriod(Period.of(inputYears, inputMonths, 5).normalized(), expectedYears, expectedMonths, 5);
1013     }
1014 
1015     @Test(expectedExceptions=ArithmeticException.class)
test_normalized_min()1016     public void test_normalized_min() {
1017         Period base = Period.of(Integer.MIN_VALUE, -12, 0);
1018         base.normalized();
1019     }
1020 
1021     @Test(expectedExceptions=ArithmeticException.class)
test_normalized_max()1022     public void test_normalized_max() {
1023         Period base = Period.of(Integer.MAX_VALUE, 12, 0);
1024         base.normalized();
1025     }
1026 
1027     //-----------------------------------------------------------------------
1028     // addTo()
1029     //-----------------------------------------------------------------------
1030     @DataProvider(name="addTo")
data_addTo()1031     Object[][] data_addTo() {
1032         return new Object[][] {
1033                 {pymd(0, 0, 0),  date(2012, 6, 30), date(2012, 6, 30)},
1034 
1035                 {pymd(1, 0, 0),  date(2012, 6, 10), date(2013, 6, 10)},
1036                 {pymd(0, 1, 0),  date(2012, 6, 10), date(2012, 7, 10)},
1037                 {pymd(0, 0, 1),  date(2012, 6, 10), date(2012, 6, 11)},
1038 
1039                 {pymd(-1, 0, 0),  date(2012, 6, 10), date(2011, 6, 10)},
1040                 {pymd(0, -1, 0),  date(2012, 6, 10), date(2012, 5, 10)},
1041                 {pymd(0, 0, -1),  date(2012, 6, 10), date(2012, 6, 9)},
1042 
1043                 {pymd(1, 2, 3),  date(2012, 6, 27), date(2013, 8, 30)},
1044                 {pymd(1, 2, 3),  date(2012, 6, 28), date(2013, 8, 31)},
1045                 {pymd(1, 2, 3),  date(2012, 6, 29), date(2013, 9, 1)},
1046                 {pymd(1, 2, 3),  date(2012, 6, 30), date(2013, 9, 2)},
1047                 {pymd(1, 2, 3),  date(2012, 7, 1), date(2013, 9, 4)},
1048 
1049                 {pymd(1, 0, 0),  date(2011, 2, 28), date(2012, 2, 28)},
1050                 {pymd(4, 0, 0),  date(2011, 2, 28), date(2015, 2, 28)},
1051                 {pymd(1, 0, 0),  date(2012, 2, 29), date(2013, 2, 28)},
1052                 {pymd(4, 0, 0),  date(2012, 2, 29), date(2016, 2, 29)},
1053 
1054                 {pymd(1, 1, 0),  date(2011, 1, 29), date(2012, 2, 29)},
1055                 {pymd(1, 2, 0),  date(2012, 2, 29), date(2013, 4, 29)},
1056         };
1057     }
1058 
1059     @Test(dataProvider="addTo")
test_addTo(Period period, LocalDate baseDate, LocalDate expected)1060     public void test_addTo(Period period, LocalDate baseDate, LocalDate expected) {
1061         assertEquals(period.addTo(baseDate), expected);
1062     }
1063 
1064     @Test(dataProvider="addTo")
test_addTo_usingLocalDatePlus(Period period, LocalDate baseDate, LocalDate expected)1065     public void test_addTo_usingLocalDatePlus(Period period, LocalDate baseDate, LocalDate expected) {
1066         assertEquals(baseDate.plus(period), expected);
1067     }
1068 
1069     @Test(expectedExceptions=NullPointerException.class)
test_addTo_nullZero()1070     public void test_addTo_nullZero() {
1071         Period.ZERO.addTo(null);
1072     }
1073 
1074     @Test(expectedExceptions=NullPointerException.class)
test_addTo_nullNonZero()1075     public void test_addTo_nullNonZero() {
1076         Period.ofDays(2).addTo(null);
1077     }
1078 
1079     //-----------------------------------------------------------------------
1080     // subtractFrom()
1081     //-----------------------------------------------------------------------
1082     @DataProvider(name="subtractFrom")
data_subtractFrom()1083     Object[][] data_subtractFrom() {
1084         return new Object[][] {
1085                 {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)},
1086 
1087                 {pymd(1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)},
1088                 {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 5, 10)},
1089                 {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 9)},
1090 
1091                 {pymd(-1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)},
1092                 {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 7, 10)},
1093                 {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 11)},
1094 
1095                 {pymd(1, 2, 3), date(2012, 8, 30), date(2011, 6, 27)},
1096                 {pymd(1, 2, 3), date(2012, 8, 31), date(2011, 6, 27)},
1097                 {pymd(1, 2, 3), date(2012, 9, 1), date(2011, 6, 28)},
1098                 {pymd(1, 2, 3), date(2012, 9, 2), date(2011, 6, 29)},
1099                 {pymd(1, 2, 3), date(2012, 9, 3), date(2011, 6, 30)},
1100                 {pymd(1, 2, 3), date(2012, 9, 4), date(2011, 7, 1)},
1101 
1102                 {pymd(1, 0, 0), date(2011, 2, 28), date(2010, 2, 28)},
1103                 {pymd(4, 0, 0), date(2011, 2, 28), date(2007, 2, 28)},
1104                 {pymd(1, 0, 0), date(2012, 2, 29), date(2011, 2, 28)},
1105                 {pymd(4, 0, 0), date(2012, 2, 29), date(2008, 2, 29)},
1106 
1107                 {pymd(1, 1, 0), date(2013, 3, 29), date(2012, 2, 29)},
1108                 {pymd(1, 2, 0), date(2012, 2, 29), date(2010, 12, 29)},
1109         };
1110     }
1111 
1112     @Test(dataProvider="subtractFrom")
test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected)1113     public void test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected) {
1114         assertEquals(period.subtractFrom(baseDate), expected);
1115     }
1116 
1117     @Test(dataProvider="subtractFrom")
test_subtractFrom_usingLocalDateMinus(Period period, LocalDate baseDate, LocalDate expected)1118     public void test_subtractFrom_usingLocalDateMinus(Period period, LocalDate baseDate, LocalDate expected) {
1119         assertEquals(baseDate.minus(period), expected);
1120     }
1121 
1122     @Test(expectedExceptions=NullPointerException.class)
test_subtractFrom_nullZero()1123     public void test_subtractFrom_nullZero() {
1124         Period.ZERO.subtractFrom(null);
1125     }
1126 
1127     @Test(expectedExceptions=NullPointerException.class)
test_subtractFrom_nullNonZero()1128     public void test_subtractFrom_nullNonZero() {
1129         Period.ofDays(2).subtractFrom(null);
1130     }
1131 
1132     //-----------------------------------------------------------------------
1133     // get units
1134     //-----------------------------------------------------------------------
1135     @Test
test_Period_getUnits()1136     public void test_Period_getUnits() {
1137         Period period = Period.of(2012, 1, 1);
1138         List<TemporalUnit> units = period.getUnits();
1139         assertEquals(units.size(), 3, "Period.getUnits should return 3 units");
1140         assertEquals(units.get(0), ChronoUnit.YEARS, "Period.getUnits contains ChronoUnit.YEARS");
1141         assertEquals(units.get(1), ChronoUnit.MONTHS, "Period.getUnits contains ChronoUnit.MONTHS");
1142         assertEquals(units.get(2), ChronoUnit.DAYS, "Period.getUnits contains ChronoUnit.DAYS");
1143     }
1144 
1145 
1146     @DataProvider(name="GoodTemporalUnit")
data_goodTemporalUnit()1147     Object[][] data_goodTemporalUnit() {
1148         return new Object[][] {
1149             {2, ChronoUnit.DAYS},
1150             {2, ChronoUnit.MONTHS},
1151             {2, ChronoUnit.YEARS},
1152         };
1153     }
1154 
1155     @Test(dataProvider="GoodTemporalUnit")
test_good_getUnit(long amount, TemporalUnit unit)1156     public void test_good_getUnit(long amount, TemporalUnit unit) {
1157         Period period = Period.of(2, 2, 2);
1158         long actual = period.get(unit);
1159         assertEquals(actual, amount, "Value of unit: " + unit);
1160     }
1161 
1162     @DataProvider(name="BadTemporalUnit")
data_badTemporalUnit()1163     Object[][] data_badTemporalUnit() {
1164         return new Object[][] {
1165             {ChronoUnit.MICROS},
1166             {ChronoUnit.MILLIS},
1167             {ChronoUnit.HALF_DAYS},
1168             {ChronoUnit.DECADES},
1169             {ChronoUnit.CENTURIES},
1170             {ChronoUnit.MILLENNIA},
1171         };
1172     }
1173 
1174     @Test(dataProvider="BadTemporalUnit", expectedExceptions=DateTimeException.class)
test_bad_getUnit(TemporalUnit unit)1175     public void test_bad_getUnit(TemporalUnit unit) {
1176         Period period = Period.of(2, 2, 2);
1177         period.get(unit);
1178     }
1179 
1180     //-----------------------------------------------------------------------
1181     // equals() / hashCode()
1182     //-----------------------------------------------------------------------
test_equals()1183     public void test_equals() {
1184         assertEquals(Period.of(1, 0, 0).equals(Period.ofYears(1)), true);
1185         assertEquals(Period.of(0, 1, 0).equals(Period.ofMonths(1)), true);
1186         assertEquals(Period.of(0, 0, 1).equals(Period.ofDays(1)), true);
1187         assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 3)), true);
1188 
1189         assertEquals(Period.ofYears(1).equals(Period.ofYears(1)), true);
1190         assertEquals(Period.ofYears(1).equals(Period.ofYears(2)), false);
1191 
1192         assertEquals(Period.ofMonths(1).equals(Period.ofMonths(1)), true);
1193         assertEquals(Period.ofMonths(1).equals(Period.ofMonths(2)), false);
1194 
1195         assertEquals(Period.ofDays(1).equals(Period.ofDays(1)), true);
1196         assertEquals(Period.ofDays(1).equals(Period.ofDays(2)), false);
1197 
1198         assertEquals(Period.of(1, 2, 3).equals(Period.of(0, 2, 3)), false);
1199         assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 0, 3)), false);
1200         assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 0)), false);
1201     }
1202 
test_equals_self()1203     public void test_equals_self() {
1204         Period test = Period.of(1, 2, 3);
1205         assertEquals(test.equals(test), true);
1206     }
1207 
test_equals_null()1208     public void test_equals_null() {
1209         Period test = Period.of(1, 2, 3);
1210         assertEquals(test.equals(null), false);
1211     }
1212 
test_equals_otherClass()1213     public void test_equals_otherClass() {
1214         Period test = Period.of(1, 2, 3);
1215         assertEquals(test.equals(""), false);
1216     }
1217 
1218     //-----------------------------------------------------------------------
test_hashCode()1219     public void test_hashCode() {
1220         Period test5 = Period.ofDays(5);
1221         Period test6 = Period.ofDays(6);
1222         Period test5M = Period.ofMonths(5);
1223         Period test5Y = Period.ofYears(5);
1224         assertEquals(test5.hashCode() == test5.hashCode(), true);
1225         assertEquals(test5.hashCode() == test6.hashCode(), false);
1226     }
1227 
1228     //-----------------------------------------------------------------------
1229     // toString()
1230     //-----------------------------------------------------------------------
1231     @DataProvider(name="toStringAndParse")
data_toString()1232     Object[][] data_toString() {
1233         return new Object[][] {
1234                 {Period.ZERO, "P0D"},
1235                 {Period.ofDays(0), "P0D"},
1236                 {Period.ofYears(1), "P1Y"},
1237                 {Period.ofMonths(1), "P1M"},
1238                 {Period.ofDays(1), "P1D"},
1239                 {Period.of(1, 2, 0), "P1Y2M"},
1240                 {Period.of(0, 2, 3), "P2M3D"},
1241                 {Period.of(1, 2, 3), "P1Y2M3D"},
1242         };
1243     }
1244 
1245     @Test(dataProvider="toStringAndParse")
test_toString(Period input, String expected)1246     public void test_toString(Period input, String expected) {
1247         assertEquals(input.toString(), expected);
1248     }
1249 
1250     @Test(dataProvider="toStringAndParse")
test_parse(Period test, String expected)1251     public void test_parse(Period test, String expected) {
1252         assertEquals(Period.parse(expected), test);
1253     }
1254 
1255     //-----------------------------------------------------------------------
assertPeriod(Period test, int y, int m, int d)1256     private void assertPeriod(Period test, int y, int m, int d) {
1257         assertEquals(test.getYears(), y, "years");
1258         assertEquals(test.getMonths(), m, "months");
1259         assertEquals(test.getDays(), d, "days");
1260         assertEquals(test.toTotalMonths(), y * 12L + m, "totalMonths");
1261     }
1262 
pymd(int y, int m, int d)1263     private static Period pymd(int y, int m, int d) {
1264         return Period.of(y, m, d);
1265     }
1266 
date(int y, int m, int d)1267     private static LocalDate date(int y, int m, int d) {
1268         return LocalDate.of(y, m, d);
1269     }
1270 
1271 }
1272