Home | History | Annotate | Download | only in time
      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
     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
    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
    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
    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
    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
    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
    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)
    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)
    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)
    248     public void factory_from_TemporalAmount_NonISO() {
    249         Period.from(ThaiBuddhistChronology.INSTANCE.period(1, 1, 1));
    250     }
    251 
    252     @Test(expectedExceptions = DateTimeException.class)
    253     public void factory_from_TemporalAmount_Duration() {
    254         Period.from(Duration.ZERO);
    255     }
    256 
    257     @Test(expectedExceptions = NullPointerException.class)
    258     public void factory_from_TemporalAmount_null() {
    259         Period.from(null);
    260     }
    261 
    262     //-----------------------------------------------------------------------
    263     // parse(String)
    264     //-----------------------------------------------------------------------
    265     @DataProvider(name="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")
    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")
    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")
    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")
    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")
    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)
    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)
    431     public void factory_parse_null() {
    432         Period.parse(null);
    433     }
    434 
    435     //-----------------------------------------------------------------------
    436     // between(LocalDate,LocalDate)
    437     //-----------------------------------------------------------------------
    438     @DataProvider(name="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")
    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)
    535     public void factory_between_LocalDate_nullFirst() {
    536         Period.between((LocalDate) null, LocalDate.of(2010, 1, 1));
    537     }
    538 
    539     @Test(expectedExceptions=NullPointerException.class)
    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
    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
    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
    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
    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
    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")
    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")
    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)
    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)
    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
    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)
    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)
    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
    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)
    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)
    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
    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)
    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)
    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")
    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")
    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)
    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)
    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
    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)
    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)
    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
    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)
    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)
    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
    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)
    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)
    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
    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
    915     public void test_multipliedBy_zeroBase() {
    916         assertPeriod(Period.ZERO.multipliedBy(2), 0, 0, 0);
    917     }
    918 
    919     @Test(expectedExceptions=ArithmeticException.class)
    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)
    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
    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)
    945     public void test_negated_overflow_years() {
    946         Period.ofYears(Integer.MIN_VALUE).negated();
    947     }
    948 
    949     @Test(expectedExceptions=ArithmeticException.class)
    950     public void test_negated_overflow_months() {
    951         Period.ofMonths(Integer.MIN_VALUE).negated();
    952     }
    953 
    954     @Test(expectedExceptions=ArithmeticException.class)
    955     public void test_negated_overflow_days() {
    956         Period.ofDays(Integer.MIN_VALUE).negated();
    957     }
    958 
    959     //-----------------------------------------------------------------------
    960     // normalized()
    961     //-----------------------------------------------------------------------
    962     @DataProvider(name="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")
   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")
   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)
   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)
   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")
   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")
   1060     public void test_addTo(Period period, LocalDate baseDate, LocalDate expected) {
   1061         assertEquals(period.addTo(baseDate), expected);
   1062     }
   1063 
   1064     @Test(dataProvider="addTo")
   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)
   1070     public void test_addTo_nullZero() {
   1071         Period.ZERO.addTo(null);
   1072     }
   1073 
   1074     @Test(expectedExceptions=NullPointerException.class)
   1075     public void test_addTo_nullNonZero() {
   1076         Period.ofDays(2).addTo(null);
   1077     }
   1078 
   1079     //-----------------------------------------------------------------------
   1080     // subtractFrom()
   1081     //-----------------------------------------------------------------------
   1082     @DataProvider(name="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")
   1113     public void test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected) {
   1114         assertEquals(period.subtractFrom(baseDate), expected);
   1115     }
   1116 
   1117     @Test(dataProvider="subtractFrom")
   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)
   1123     public void test_subtractFrom_nullZero() {
   1124         Period.ZERO.subtractFrom(null);
   1125     }
   1126 
   1127     @Test(expectedExceptions=NullPointerException.class)
   1128     public void test_subtractFrom_nullNonZero() {
   1129         Period.ofDays(2).subtractFrom(null);
   1130     }
   1131 
   1132     //-----------------------------------------------------------------------
   1133     // get units
   1134     //-----------------------------------------------------------------------
   1135     @Test
   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")
   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")
   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")
   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)
   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     //-----------------------------------------------------------------------
   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 
   1203     public void test_equals_self() {
   1204         Period test = Period.of(1, 2, 3);
   1205         assertEquals(test.equals(test), true);
   1206     }
   1207 
   1208     public void test_equals_null() {
   1209         Period test = Period.of(1, 2, 3);
   1210         assertEquals(test.equals(null), false);
   1211     }
   1212 
   1213     public void test_equals_otherClass() {
   1214         Period test = Period.of(1, 2, 3);
   1215         assertEquals(test.equals(""), false);
   1216     }
   1217 
   1218     //-----------------------------------------------------------------------
   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")
   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")
   1246     public void test_toString(Period input, String expected) {
   1247         assertEquals(input.toString(), expected);
   1248     }
   1249 
   1250     @Test(dataProvider="toStringAndParse")
   1251     public void test_parse(Period test, String expected) {
   1252         assertEquals(Period.parse(expected), test);
   1253     }
   1254 
   1255     //-----------------------------------------------------------------------
   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 
   1263     private static Period pymd(int y, int m, int d) {
   1264         return Period.of(y, m, d);
   1265     }
   1266 
   1267     private static LocalDate date(int y, int m, int d) {
   1268         return LocalDate.of(y, m, d);
   1269     }
   1270 
   1271 }
   1272