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 org.testng.Assert.assertEquals;
  63 
  64 import java.time.DateTimeException;
  65 import java.time.LocalDate;
  66 import java.time.Period;
  67 import java.time.format.DateTimeParseException;
  68 import java.time.temporal.ChronoUnit;
  69 import java.time.temporal.TemporalUnit;
  70 import java.util.List;
  71 import java.util.Locale;
  72 
  73 import org.testng.annotations.DataProvider;
  74 import org.testng.annotations.Test;
  75 
  76 /**
  77  * Test Period.
  78  */
  79 @Test
  80 public class TCKPeriod extends AbstractTCKTest {
  81 
  82     //-----------------------------------------------------------------------
  83     @Test
  84     public void test_serialization() throws Exception {
  85         assertSerializable(Period.ZERO);
  86         assertSerializable(Period.ofDays(1));
  87         assertSerializable(Period.of(1, 2, 3));
  88     }
  89 
  90     //-----------------------------------------------------------------------
  91     // ofYears(int)
  92     //-----------------------------------------------------------------------
  93     @Test
  94     public void factory_ofYears_int() {
  95         assertPeriod(Period.ofYears(0), 0, 0, 0);
  96         assertPeriod(Period.ofYears(1), 1, 0, 0);
  97         assertPeriod(Period.ofYears(234), 234, 0, 0);
  98         assertPeriod(Period.ofYears(-100), -100, 0, 0);
  99         assertPeriod(Period.ofYears(Integer.MAX_VALUE), Integer.MAX_VALUE, 0, 0);
 100         assertPeriod(Period.ofYears(Integer.MIN_VALUE), Integer.MIN_VALUE, 0, 0);
 101     }
 102 
 103     //-----------------------------------------------------------------------
 104     // ofMonths(int)
 105     //-----------------------------------------------------------------------
 106     @Test
 107     public void factory_ofMonths_int() {
 108         assertPeriod(Period.ofMonths(0), 0, 0, 0);
 109         assertPeriod(Period.ofMonths(1), 0, 1, 0);
 110         assertPeriod(Period.ofMonths(234), 0, 234, 0);
 111         assertPeriod(Period.ofMonths(-100), 0, -100, 0);
 112         assertPeriod(Period.ofMonths(Integer.MAX_VALUE), 0, Integer.MAX_VALUE, 0);
 113         assertPeriod(Period.ofMonths(Integer.MIN_VALUE), 0, Integer.MIN_VALUE, 0);
 114     }
 115 
 116     //-----------------------------------------------------------------------
 117     // ofDays(int)
 118     //-----------------------------------------------------------------------
 119     @Test
 120     public void factory_ofDay_int() {
 121         assertPeriod(Period.ofDays(0), 0, 0, 0);
 122         assertPeriod(Period.ofDays(1), 0, 0, 1);
 123         assertPeriod(Period.ofDays(234), 0, 0, 234);
 124         assertPeriod(Period.ofDays(-100), 0, 0, -100);
 125         assertPeriod(Period.ofDays(Integer.MAX_VALUE), 0, 0, Integer.MAX_VALUE);
 126         assertPeriod(Period.ofDays(Integer.MIN_VALUE), 0, 0, Integer.MIN_VALUE);
 127     }
 128 
 129     //-----------------------------------------------------------------------
 130     // of(int3)
 131     //-----------------------------------------------------------------------
 132     @Test
 133     public void factory_of_ints() {
 134         assertPeriod(Period.of(1, 2, 3), 1, 2, 3);
 135         assertPeriod(Period.of(0, 2, 3), 0, 2, 3);
 136         assertPeriod(Period.of(1, 0, 0), 1, 0, 0);
 137         assertPeriod(Period.of(0, 0, 0), 0, 0, 0);
 138         assertPeriod(Period.of(-1, -2, -3), -1, -2, -3);
 139     }
 140 
 141     //-----------------------------------------------------------------------
 142     // parse(String)
 143     //-----------------------------------------------------------------------
 144     @DataProvider(name="parseSuccess")
 145     Object[][] data_factory_parseSuccess() {
 146         return new Object[][] {
 147                 {"P1Y", Period.ofYears(1)},
 148                 {"P12Y", Period.ofYears(12)},
 149                 {"P987654321Y", Period.ofYears(987654321)},
 150                 {"P+1Y", Period.ofYears(1)},
 151                 {"P+12Y", Period.ofYears(12)},
 152                 {"P+987654321Y", Period.ofYears(987654321)},
 153                 {"P+0Y", Period.ofYears(0)},
 154                 {"P0Y", Period.ofYears(0)},
 155                 {"P-0Y", Period.ofYears(0)},
 156                 {"P-25Y", Period.ofYears(-25)},
 157                 {"P-987654321Y", Period.ofYears(-987654321)},
 158                 {"P" + Integer.MAX_VALUE + "Y", Period.ofYears(Integer.MAX_VALUE)},
 159                 {"P" + Integer.MIN_VALUE + "Y", Period.ofYears(Integer.MIN_VALUE)},
 160 
 161                 {"P1M", Period.ofMonths(1)},
 162                 {"P12M", Period.ofMonths(12)},
 163                 {"P987654321M", Period.ofMonths(987654321)},
 164                 {"P+1M", Period.ofMonths(1)},
 165                 {"P+12M", Period.ofMonths(12)},
 166                 {"P+987654321M", Period.ofMonths(987654321)},
 167                 {"P+0M", Period.ofMonths(0)},
 168                 {"P0M", Period.ofMonths(0)},
 169                 {"P-0M", Period.ofMonths(0)},
 170                 {"P-25M", Period.ofMonths(-25)},
 171                 {"P-987654321M", Period.ofMonths(-987654321)},
 172                 {"P" + Integer.MAX_VALUE + "M", Period.ofMonths(Integer.MAX_VALUE)},
 173                 {"P" + Integer.MIN_VALUE + "M", Period.ofMonths(Integer.MIN_VALUE)},
 174 
 175                 {"P1D", Period.ofDays(1)},
 176                 {"P12D", Period.ofDays(12)},
 177                 {"P987654321D", Period.ofDays(987654321)},
 178                 {"P+1D", Period.ofDays(1)},
 179                 {"P+12D", Period.ofDays(12)},
 180                 {"P+987654321D", Period.ofDays(987654321)},
 181                 {"P+0D", Period.ofDays(0)},
 182                 {"P0D", Period.ofDays(0)},
 183                 {"P-0D", Period.ofDays(0)},
 184                 {"P-25D", Period.ofDays(-25)},
 185                 {"P-987654321D", Period.ofDays(-987654321)},
 186                 {"P" + Integer.MAX_VALUE + "D", Period.ofDays(Integer.MAX_VALUE)},
 187                 {"P" + Integer.MIN_VALUE + "D", Period.ofDays(Integer.MIN_VALUE)},
 188 
 189                 {"P0Y0M0D", Period.of(0, 0, 0)},
 190                 {"P2Y0M0D", Period.of(2, 0, 0)},
 191                 {"P0Y3M0D", Period.of(0, 3, 0)},
 192                 {"P0Y0M4D", Period.of(0, 0, 4)},
 193                 {"P2Y3M25D", Period.of(2, 3, 25)},
 194                 {"P-2Y3M25D", Period.of(-2, 3, 25)},
 195                 {"P2Y-3M25D", Period.of(2, -3, 25)},
 196                 {"P2Y3M-25D", Period.of(2, 3, -25)},
 197                 {"P-2Y-3M-25D", Period.of(-2, -3, -25)},
 198         };
 199     }
 200 
 201     @Test(dataProvider="parseSuccess")
 202     public void factory_parse(String text, Period expected) {
 203         Period p = Period.parse(text);
 204         assertEquals(p, expected);
 205     }
 206 
 207     @Test(dataProvider="parseSuccess")
 208     public void factory_parse_plus(String text, Period expected) {
 209         Period p = Period.parse("+" + text);
 210         assertEquals(p, expected);
 211     }
 212 
 213     @Test(dataProvider="parseSuccess")
 214     public void factory_parse_minus(String text, Period expected) {
 215         Period p = null;
 216         try {
 217             p = Period.parse("-" + text);
 218         } catch (DateTimeParseException ex) {
 219             assertEquals(expected.getYears() == Integer.MIN_VALUE ||
 220                     expected.getMonths() == Integer.MIN_VALUE ||
 221                     expected.getDays() == Integer.MIN_VALUE, true);
 222             return;
 223         }
 224         // not inside try/catch or it breaks test
 225         assertEquals(p, expected.negated());
 226     }
 227 
 228     @Test(dataProvider="parseSuccess")
 229     public void factory_parse_lowerCase(String text, Period expected) {
 230         Period p = Period.parse(text.toLowerCase(Locale.ENGLISH));
 231         assertEquals(p, expected);
 232     }
 233 
 234     @DataProvider(name="parseFailure")
 235     Object[][] data_parseFailure() {
 236         return new Object[][] {
 237                 {""},
 238                 {"PTD"},
 239                 {"AT0D"},
 240                 {"PA0D"},
 241                 {"PT0A"},
 242 
 243                 {"PT+D"},
 244                 {"PT-D"},
 245                 {"PT.D"},
 246                 {"PTAD"},
 247 
 248                 {"PT+0D"},
 249                 {"PT-0D"},
 250                 {"PT+1D"},
 251                 {"PT-.D"},
 252 
 253                 {"P1Y1MT1D"},
 254                 {"P1YMD"},
 255                 {"P1Y2Y"},
 256                 {"PT1M+3S"},
 257 
 258                 {"PT1S1"},
 259                 {"PT1S."},
 260                 {"PT1SA"},
 261                 {"PT1M1"},
 262                 {"PT1M."},
 263                 {"PT1MA"},
 264 
 265                 {"P"+ (((long) Integer.MAX_VALUE) + 1) + "Y"},
 266                 {"P"+ (((long) Integer.MAX_VALUE) + 1) + "M"},
 267                 {"P"+ (((long) Integer.MAX_VALUE) + 1) + "D"},
 268                 {"P"+ (((long) Integer.MIN_VALUE) - 1) + "Y"},
 269                 {"P"+ (((long) Integer.MIN_VALUE) - 1) + "M"},
 270                 {"P"+ (((long) Integer.MIN_VALUE) - 1) + "D"},
 271 
 272                 {"Rubbish"},
 273         };
 274     }
 275 
 276     @Test(dataProvider="parseFailure", expectedExceptions=DateTimeParseException.class)
 277     public void factory_parseFailures(String text) {
 278         try {
 279             Period.parse(text);
 280         } catch (DateTimeParseException ex) {
 281             assertEquals(ex.getParsedString(), text);
 282             throw ex;
 283         }
 284     }
 285 
 286     @Test(expectedExceptions=NullPointerException.class)
 287     public void factory_parse_null() {
 288         Period.parse(null);
 289     }
 290 
 291     //-----------------------------------------------------------------------
 292     // between(LocalDate,LocalDate)
 293     //-----------------------------------------------------------------------
 294     @DataProvider(name="between")
 295     Object[][] data_between() {
 296         return new Object[][] {
 297                 {2010, 1, 1, 2010, 1, 1, 0, 0, 0},
 298                 {2010, 1, 1, 2010, 1, 2, 0, 0, 1},
 299                 {2010, 1, 1, 2010, 1, 31, 0, 0, 30},
 300                 {2010, 1, 1, 2010, 2, 1, 0, 1, 0},
 301                 {2010, 1, 1, 2010, 2, 28, 0, 1, 27},
 302                 {2010, 1, 1, 2010, 3, 1, 0, 2, 0},
 303                 {2010, 1, 1, 2010, 12, 31, 0, 11, 30},
 304                 {2010, 1, 1, 2011, 1, 1, 1, 0, 0},
 305                 {2010, 1, 1, 2011, 12, 31, 1, 11, 30},
 306                 {2010, 1, 1, 2012, 1, 1, 2, 0, 0},
 307 
 308                 {2010, 1, 10, 2010, 1, 1, 0, 0, -9},
 309                 {2010, 1, 10, 2010, 1, 2, 0, 0, -8},
 310                 {2010, 1, 10, 2010, 1, 9, 0, 0, -1},
 311                 {2010, 1, 10, 2010, 1, 10, 0, 0, 0},
 312                 {2010, 1, 10, 2010, 1, 11, 0, 0, 1},
 313                 {2010, 1, 10, 2010, 1, 31, 0, 0, 21},
 314                 {2010, 1, 10, 2010, 2, 1, 0, 0, 22},
 315                 {2010, 1, 10, 2010, 2, 9, 0, 0, 30},
 316                 {2010, 1, 10, 2010, 2, 10, 0, 1, 0},
 317                 {2010, 1, 10, 2010, 2, 28, 0, 1, 18},
 318                 {2010, 1, 10, 2010, 3, 1, 0, 1, 19},
 319                 {2010, 1, 10, 2010, 3, 9, 0, 1, 27},
 320                 {2010, 1, 10, 2010, 3, 10, 0, 2, 0},
 321                 {2010, 1, 10, 2010, 12, 31, 0, 11, 21},
 322                 {2010, 1, 10, 2011, 1, 1, 0, 11, 22},
 323                 {2010, 1, 10, 2011, 1, 9, 0, 11, 30},
 324                 {2010, 1, 10, 2011, 1, 10, 1, 0, 0},
 325 
 326                 {2010, 3, 30, 2011, 5, 1, 1, 1, 1},
 327                 {2010, 4, 30, 2011, 5, 1, 1, 0, 1},
 328 
 329                 {2010, 2, 28, 2012, 2, 27, 1, 11, 30},
 330                 {2010, 2, 28, 2012, 2, 28, 2, 0, 0},
 331                 {2010, 2, 28, 2012, 2, 29, 2, 0, 1},
 332 
 333                 {2012, 2, 28, 2014, 2, 27, 1, 11, 30},
 334                 {2012, 2, 28, 2014, 2, 28, 2, 0, 0},
 335                 {2012, 2, 28, 2014, 3, 1, 2, 0, 1},
 336 
 337                 {2012, 2, 29, 2014, 2, 28, 1, 11, 30},
 338                 {2012, 2, 29, 2014, 3, 1, 2, 0, 1},
 339                 {2012, 2, 29, 2014, 3, 2, 2, 0, 2},
 340 
 341                 {2012, 2, 29, 2016, 2, 28, 3, 11, 30},
 342                 {2012, 2, 29, 2016, 2, 29, 4, 0, 0},
 343                 {2012, 2, 29, 2016, 3, 1, 4, 0, 1},
 344 
 345                 {2010, 1, 1, 2009, 12, 31, 0, 0, -1},
 346                 {2010, 1, 1, 2009, 12, 30, 0, 0, -2},
 347                 {2010, 1, 1, 2009, 12, 2, 0, 0, -30},
 348                 {2010, 1, 1, 2009, 12, 1, 0, -1, 0},
 349                 {2010, 1, 1, 2009, 11, 30, 0, -1, -1},
 350                 {2010, 1, 1, 2009, 11, 2, 0, -1, -29},
 351                 {2010, 1, 1, 2009, 11, 1, 0, -2, 0},
 352                 {2010, 1, 1, 2009, 1, 2, 0, -11, -30},
 353                 {2010, 1, 1, 2009, 1, 1, -1, 0, 0},
 354 
 355                 {2010, 1, 15, 2010, 1, 15, 0, 0, 0},
 356                 {2010, 1, 15, 2010, 1, 14, 0, 0, -1},
 357                 {2010, 1, 15, 2010, 1, 1, 0, 0, -14},
 358                 {2010, 1, 15, 2009, 12, 31, 0, 0, -15},
 359                 {2010, 1, 15, 2009, 12, 16, 0, 0, -30},
 360                 {2010, 1, 15, 2009, 12, 15, 0, -1, 0},
 361                 {2010, 1, 15, 2009, 12, 14, 0, -1, -1},
 362 
 363                 {2010, 2, 28, 2009, 3, 1, 0, -11, -27},
 364                 {2010, 2, 28, 2009, 2, 28, -1, 0, 0},
 365                 {2010, 2, 28, 2009, 2, 27, -1, 0, -1},
 366 
 367                 {2010, 2, 28, 2008, 2, 29, -1, -11, -28},
 368                 {2010, 2, 28, 2008, 2, 28, -2, 0, 0},
 369                 {2010, 2, 28, 2008, 2, 27, -2, 0, -1},
 370 
 371                 {2012, 2, 29, 2009, 3, 1, -2, -11, -28},
 372                 {2012, 2, 29, 2009, 2, 28, -3, 0, -1},
 373                 {2012, 2, 29, 2009, 2, 27, -3, 0, -2},
 374 
 375                 {2012, 2, 29, 2008, 3, 1, -3, -11, -28},
 376                 {2012, 2, 29, 2008, 2, 29, -4, 0, 0},
 377                 {2012, 2, 29, 2008, 2, 28, -4, 0, -1},
 378         };
 379     }
 380 
 381     @Test(dataProvider="between")
 382     public void factory_between_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) {
 383         LocalDate start = LocalDate.of(y1, m1, d1);
 384         LocalDate end = LocalDate.of(y2, m2, d2);
 385         Period test = Period.between(start, end);
 386         assertPeriod(test, ye, me, de);
 387         //assertEquals(start.plus(test), end);
 388     }
 389 
 390     @Test(expectedExceptions=NullPointerException.class)
 391     public void factory_between_LocalDate_nullFirst() {
 392         Period.between((LocalDate) null, LocalDate.of(2010, 1, 1));
 393     }
 394 
 395     @Test(expectedExceptions=NullPointerException.class)
 396     public void factory_between_LocalDate_nullSecond() {
 397         Period.between(LocalDate.of(2010, 1, 1), (LocalDate) null);
 398     }
 399 
 400     //-----------------------------------------------------------------------
 401     // isZero()
 402     //-----------------------------------------------------------------------
 403     @Test
 404     public void test_isZero() {
 405         assertEquals(Period.of(0, 0, 0).isZero(), true);
 406         assertEquals(Period.of(1, 2, 3).isZero(), false);
 407         assertEquals(Period.of(1, 0, 0).isZero(), false);
 408         assertEquals(Period.of(0, 2, 0).isZero(), false);
 409         assertEquals(Period.of(0, 0, 3).isZero(), false);
 410     }
 411 
 412     //-----------------------------------------------------------------------
 413     // isNegative()
 414     //-----------------------------------------------------------------------
 415     @Test
 416     public void test_isPositive() {
 417         assertEquals(Period.of(0, 0, 0).isNegative(), false);
 418         assertEquals(Period.of(1, 2, 3).isNegative(), false);
 419         assertEquals(Period.of(1, 0, 0).isNegative(), false);
 420         assertEquals(Period.of(0, 2, 0).isNegative(), false);
 421         assertEquals(Period.of(0, 0, 3).isNegative(), false);
 422 
 423         assertEquals(Period.of(-1, -2, -3).isNegative(), true);
 424         assertEquals(Period.of(-1, -2, 3).isNegative(), true);
 425         assertEquals(Period.of(1, -2, -3).isNegative(), true);
 426         assertEquals(Period.of(-1, 2, -3).isNegative(), true);
 427         assertEquals(Period.of(-1, 2, 3).isNegative(), true);
 428         assertEquals(Period.of(1, -2, 3).isNegative(), true);
 429         assertEquals(Period.of(1, 2, -3).isNegative(), true);
 430     }
 431 
 432     //-----------------------------------------------------------------------
 433     // withYears()
 434     //-----------------------------------------------------------------------
 435     @Test
 436     public void test_withYears() {
 437         assertPeriod(Period.of(1, 2, 3).withYears(1), 1, 2, 3);
 438         assertPeriod(Period.of(1, 2, 3).withYears(10), 10, 2, 3);
 439         assertPeriod(Period.of(1, 2, 3).withYears(-10), -10, 2, 3);
 440         assertPeriod(Period.of(-1, -2, -3).withYears(10), 10, -2, -3);
 441         assertPeriod(Period.of(1, 2, 3).withYears(0), 0, 2, 3);
 442     }
 443 
 444     //-----------------------------------------------------------------------
 445     // withMonths()
 446     //-----------------------------------------------------------------------
 447     @Test
 448     public void test_withMonths() {
 449         assertPeriod(Period.of(1, 2, 3).withMonths(2), 1, 2, 3);
 450         assertPeriod(Period.of(1, 2, 3).withMonths(10), 1, 10, 3);
 451         assertPeriod(Period.of(1, 2, 3).withMonths(-10), 1, -10, 3);
 452         assertPeriod(Period.of(-1, -2, -3).withMonths(10), -1, 10, -3);
 453         assertPeriod(Period.of(1, 2, 3).withMonths(0), 1, 0, 3);
 454     }
 455 
 456     //-----------------------------------------------------------------------
 457     // withDays()
 458     //-----------------------------------------------------------------------
 459     @Test
 460     public void test_withDays() {
 461         assertPeriod(Period.of(1, 2, 3).withDays(3), 1, 2, 3);
 462         assertPeriod(Period.of(1, 2, 3).withDays(10), 1, 2, 10);
 463         assertPeriod(Period.of(1, 2, 3).withDays(-10), 1, 2, -10);
 464         assertPeriod(Period.of(-1, -2, -3).withDays(10), -1, -2, 10);
 465         assertPeriod(Period.of(1, 2, 3).withDays(0), 1, 2, 0);
 466     }
 467 
 468     //-----------------------------------------------------------------------
 469     // plusYears()
 470     //-----------------------------------------------------------------------
 471     @Test
 472     public void test_plusYears() {
 473         assertPeriod(Period.of(1, 2, 3).plusYears(0), 1, 2, 3);
 474         assertPeriod(Period.of(1, 2, 3).plusYears(10), 11, 2, 3);
 475         assertPeriod(Period.of(1, 2, 3).plusYears(-10), -9, 2, 3);
 476         assertPeriod(Period.of(1, 2, 3).plusYears(-1), 0, 2, 3);
 477     }
 478 
 479     @Test(expectedExceptions=ArithmeticException.class)
 480     public void test_plusYears_overflowTooBig() {
 481         Period test = Period.ofYears(Integer.MAX_VALUE);
 482         test.plusYears(1);
 483     }
 484 
 485     @Test(expectedExceptions=ArithmeticException.class)
 486     public void test_plusYears_overflowTooSmall() {
 487         Period test = Period.ofYears(Integer.MIN_VALUE);
 488         test.plusYears(-1);
 489     }
 490 
 491     //-----------------------------------------------------------------------
 492     // plusMonths()
 493     //-----------------------------------------------------------------------
 494     @Test
 495     public void test_plusMonths() {
 496         assertPeriod(Period.of(1, 2, 3).plusMonths(0), 1, 2, 3);
 497         assertPeriod(Period.of(1, 2, 3).plusMonths(10), 1, 12, 3);
 498         assertPeriod(Period.of(1, 2, 3).plusMonths(-10), 1, -8, 3);
 499         assertPeriod(Period.of(1, 2, 3).plusMonths(-2), 1, 0, 3);
 500     }
 501 
 502     @Test(expectedExceptions=ArithmeticException.class)
 503     public void test_plusMonths_overflowTooBig() {
 504         Period test = Period.ofMonths(Integer.MAX_VALUE);
 505         test.plusMonths(1);
 506     }
 507 
 508     @Test(expectedExceptions=ArithmeticException.class)
 509     public void test_plusMonths_overflowTooSmall() {
 510         Period test = Period.ofMonths(Integer.MIN_VALUE);
 511         test.plusMonths(-1);
 512     }
 513 
 514     //-----------------------------------------------------------------------
 515     // plusDays()
 516     //-----------------------------------------------------------------------
 517     @Test
 518     public void test_plusDays() {
 519         assertPeriod(Period.of(1, 2, 3).plusDays(0), 1, 2, 3);
 520         assertPeriod(Period.of(1, 2, 3).plusDays(10), 1, 2, 13);
 521         assertPeriod(Period.of(1, 2, 3).plusDays(-10), 1, 2, -7);
 522         assertPeriod(Period.of(1, 2, 3).plusDays(-3), 1, 2, 0);
 523     }
 524 
 525     @Test(expectedExceptions=ArithmeticException.class)
 526     public void test_plusDays_overflowTooBig() {
 527         Period test = Period.ofDays(Integer.MAX_VALUE);
 528         test.plusDays(1);
 529     }
 530 
 531     @Test(expectedExceptions=ArithmeticException.class)
 532     public void test_plusDays_overflowTooSmall() {
 533         Period test = Period.ofDays(Integer.MIN_VALUE);
 534         test.plusDays(-1);
 535     }
 536 
 537     //-----------------------------------------------------------------------
 538     // multipliedBy()
 539     //-----------------------------------------------------------------------
 540     @Test
 541     public void test_multipliedBy() {
 542         Period test = Period.of(1, 2, 3);
 543         assertPeriod(test.multipliedBy(0), 0, 0, 0);
 544         assertPeriod(test.multipliedBy(1), 1, 2, 3);
 545         assertPeriod(test.multipliedBy(2), 2, 4, 6);
 546         assertPeriod(test.multipliedBy(-3), -3, -6, -9);
 547     }
 548 
 549     @Test
 550     public void test_multipliedBy_zeroBase() {
 551         assertPeriod(Period.ZERO.multipliedBy(2), 0, 0, 0);
 552     }
 553 
 554     @Test(expectedExceptions=ArithmeticException.class)
 555     public void test_multipliedBy_overflowTooBig() {
 556         Period test = Period.ofYears(Integer.MAX_VALUE / 2 + 1);
 557         test.multipliedBy(2);
 558     }
 559 
 560     @Test(expectedExceptions=ArithmeticException.class)
 561     public void test_multipliedBy_overflowTooSmall() {
 562         Period test = Period.ofYears(Integer.MIN_VALUE / 2 - 1);
 563         test.multipliedBy(2);
 564     }
 565 
 566     //-----------------------------------------------------------------------
 567     // negated()
 568     //-----------------------------------------------------------------------
 569     @Test
 570     public void test_negated() {
 571         assertPeriod(Period.of(0, 0, 0).negated(), 0 ,0, 0);
 572         assertPeriod(Period.of(1, 2, 3).negated(), -1, -2, -3);
 573         assertPeriod(Period.of(-1, -2, -3).negated(), 1, 2, 3);
 574         assertPeriod(Period.of(-1, 2, -3).negated(), 1, -2, 3);
 575         assertPeriod(Period.of(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).negated(),
 576                 -Integer.MAX_VALUE, -Integer.MAX_VALUE, -Integer.MAX_VALUE);
 577     }
 578 
 579     @Test(expectedExceptions=ArithmeticException.class)
 580     public void test_negated_overflow_years() {
 581         Period.ofYears(Integer.MIN_VALUE).negated();
 582     }
 583 
 584     @Test(expectedExceptions=ArithmeticException.class)
 585     public void test_negated_overflow_months() {
 586         Period.ofMonths(Integer.MIN_VALUE).negated();
 587     }
 588 
 589     @Test(expectedExceptions=ArithmeticException.class)
 590     public void test_negated_overflow_days() {
 591         Period.ofDays(Integer.MIN_VALUE).negated();
 592     }
 593 
 594     //-----------------------------------------------------------------------
 595     // normalized()
 596     //-----------------------------------------------------------------------
 597     @DataProvider(name="normalized")
 598     Object[][] data_normalized() {
 599         return new Object[][] {
 600                 {0, 0,  0, 0},
 601                 {1, 0,  1, 0},
 602                 {-1, 0,  -1, 0},
 603 
 604                 {1, 1,  1, 1},
 605                 {1, 2,  1, 2},
 606                 {1, 11,  1, 11},
 607                 {1, 12,  2, 0},
 608                 {1, 13,  2, 1},
 609                 {1, 23,  2, 11},
 610                 {1, 24,  3, 0},
 611                 {1, 25,  3, 1},
 612 
 613                 {1, -1,  0, 11},
 614                 {1, -2,  0, 10},
 615                 {1, -11,  0, 1},
 616                 {1, -12,  0, 0},
 617                 {1, -13,  0, -1},
 618                 {1, -23,  0, -11},
 619                 {1, -24,  -1, 0},
 620                 {1, -25,  -1, -1},
 621                 {1, -35,  -1, -11},
 622                 {1, -36,  -2, 0},
 623                 {1, -37,  -2, -1},
 624 
 625                 {-1, 1,  0, -11},
 626                 {-1, 11,  0, -1},
 627                 {-1, 12,  0, 0},
 628                 {-1, 13,  0, 1},
 629                 {-1, 23,  0, 11},
 630                 {-1, 24,  1, 0},
 631                 {-1, 25,  1, 1},
 632 
 633                 {-1, -1,  -1, -1},
 634                 {-1, -11,  -1, -11},
 635                 {-1, -12,  -2, 0},
 636                 {-1, -13,  -2, -1},
 637         };
 638     }
 639 
 640     @Test(dataProvider="normalized")
 641     public void test_normalized(int inputYears, int inputMonths, int expectedYears, int expectedMonths) {
 642         assertPeriod(Period.of(inputYears, inputMonths, 0).normalized(), expectedYears, expectedMonths, 0);
 643     }
 644 
 645     @Test(dataProvider="normalized")
 646     public void test_normalized_daysUnaffected(int inputYears, int inputMonths, int expectedYears, int expectedMonths) {
 647         assertPeriod(Period.of(inputYears, inputMonths, 5).normalized(), expectedYears, expectedMonths, 5);
 648     }
 649 
 650     @Test(expectedExceptions=ArithmeticException.class)
 651     public void test_normalized_min() {
 652         Period base = Period.of(Integer.MIN_VALUE, -12, 0);
 653         base.normalized();
 654     }
 655 
 656     @Test(expectedExceptions=ArithmeticException.class)
 657     public void test_normalized_max() {
 658         Period base = Period.of(Integer.MAX_VALUE, 12, 0);
 659         base.normalized();
 660     }
 661 
 662     //-----------------------------------------------------------------------
 663     // addTo()
 664     //-----------------------------------------------------------------------
 665     @DataProvider(name="addTo")
 666     Object[][] data_addTo() {
 667         return new Object[][] {
 668                 {pymd(0, 0, 0),  date(2012, 6, 30), date(2012, 6, 30)},
 669 
 670                 {pymd(1, 0, 0),  date(2012, 6, 10), date(2013, 6, 10)},
 671                 {pymd(0, 1, 0),  date(2012, 6, 10), date(2012, 7, 10)},
 672                 {pymd(0, 0, 1),  date(2012, 6, 10), date(2012, 6, 11)},
 673 
 674                 {pymd(-1, 0, 0),  date(2012, 6, 10), date(2011, 6, 10)},
 675                 {pymd(0, -1, 0),  date(2012, 6, 10), date(2012, 5, 10)},
 676                 {pymd(0, 0, -1),  date(2012, 6, 10), date(2012, 6, 9)},
 677 
 678                 {pymd(1, 2, 3),  date(2012, 6, 27), date(2013, 8, 30)},
 679                 {pymd(1, 2, 3),  date(2012, 6, 28), date(2013, 8, 31)},
 680                 {pymd(1, 2, 3),  date(2012, 6, 29), date(2013, 9, 1)},
 681                 {pymd(1, 2, 3),  date(2012, 6, 30), date(2013, 9, 2)},
 682                 {pymd(1, 2, 3),  date(2012, 7, 1), date(2013, 9, 4)},
 683 
 684                 {pymd(1, 0, 0),  date(2011, 2, 28), date(2012, 2, 28)},
 685                 {pymd(4, 0, 0),  date(2011, 2, 28), date(2015, 2, 28)},
 686                 {pymd(1, 0, 0),  date(2012, 2, 29), date(2013, 2, 28)},
 687                 {pymd(4, 0, 0),  date(2012, 2, 29), date(2016, 2, 29)},
 688 
 689                 {pymd(1, 1, 0),  date(2011, 1, 29), date(2012, 2, 29)},
 690                 {pymd(1, 2, 0),  date(2012, 2, 29), date(2013, 4, 29)},
 691         };
 692     }
 693 
 694     @Test(dataProvider="addTo")
 695     public void test_addTo(Period period, LocalDate baseDate, LocalDate expected) {
 696         assertEquals(period.addTo(baseDate), expected);
 697     }
 698 
 699     @Test(dataProvider="addTo")
 700     public void test_addTo_usingLocalDatePlus(Period period, LocalDate baseDate, LocalDate expected) {
 701         assertEquals(baseDate.plus(period), expected);
 702     }
 703 
 704     @Test(expectedExceptions=NullPointerException.class)
 705     public void test_addTo_nullZero() {
 706         Period.ZERO.addTo(null);
 707     }
 708 
 709     @Test(expectedExceptions=NullPointerException.class)
 710     public void test_addTo_nullNonZero() {
 711         Period.ofDays(2).addTo(null);
 712     }
 713 
 714     //-----------------------------------------------------------------------
 715     // subtractFrom()
 716     //-----------------------------------------------------------------------
 717     @DataProvider(name="subtractFrom")
 718     Object[][] data_subtractFrom() {
 719         return new Object[][] {
 720                 {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)},
 721 
 722                 {pymd(1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)},
 723                 {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 5, 10)},
 724                 {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 9)},
 725 
 726                 {pymd(-1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)},
 727                 {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 7, 10)},
 728                 {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 11)},
 729 
 730                 {pymd(1, 2, 3), date(2012, 8, 30), date(2011, 6, 27)},
 731                 {pymd(1, 2, 3), date(2012, 8, 31), date(2011, 6, 27)},
 732                 {pymd(1, 2, 3), date(2012, 9, 1), date(2011, 6, 28)},
 733                 {pymd(1, 2, 3), date(2012, 9, 2), date(2011, 6, 29)},
 734                 {pymd(1, 2, 3), date(2012, 9, 3), date(2011, 6, 30)},
 735                 {pymd(1, 2, 3), date(2012, 9, 4), date(2011, 7, 1)},
 736 
 737                 {pymd(1, 0, 0), date(2011, 2, 28), date(2010, 2, 28)},
 738                 {pymd(4, 0, 0), date(2011, 2, 28), date(2007, 2, 28)},
 739                 {pymd(1, 0, 0), date(2012, 2, 29), date(2011, 2, 28)},
 740                 {pymd(4, 0, 0), date(2012, 2, 29), date(2008, 2, 29)},
 741 
 742                 {pymd(1, 1, 0), date(2013, 3, 29), date(2012, 2, 29)},
 743                 {pymd(1, 2, 0), date(2012, 2, 29), date(2010, 12, 29)},
 744         };
 745     }
 746 
 747     @Test(dataProvider="subtractFrom")
 748     public void test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected) {
 749         assertEquals(period.subtractFrom(baseDate), expected);
 750     }
 751 
 752     @Test(dataProvider="subtractFrom")
 753     public void test_subtractFrom_usingLocalDateMinus(Period period, LocalDate baseDate, LocalDate expected) {
 754         assertEquals(baseDate.minus(period), expected);
 755     }
 756 
 757     @Test(expectedExceptions=NullPointerException.class)
 758     public void test_subtractFrom_nullZero() {
 759         Period.ZERO.subtractFrom(null);
 760     }
 761 
 762     @Test(expectedExceptions=NullPointerException.class)
 763     public void test_subtractFrom_nullNonZero() {
 764         Period.ofDays(2).subtractFrom(null);
 765     }
 766 
 767     //-----------------------------------------------------------------------
 768     // get units
 769     //-----------------------------------------------------------------------
 770     @Test
 771     public void test_Period_getUnits() {
 772         Period period = Period.of(2012, 1, 1);
 773         List<TemporalUnit> units = period.getUnits();
 774         assertEquals(units.size(), 3, "Period.getUnits should return 3 units");
 775         assertEquals(units.get(0), ChronoUnit.YEARS, "Period.getUnits contains ChronoUnit.YEARS");
 776         assertEquals(units.get(1), ChronoUnit.MONTHS, "Period.getUnits contains ChronoUnit.MONTHS");
 777         assertEquals(units.get(2), ChronoUnit.DAYS, "Period.getUnits contains ChronoUnit.DAYS");
 778     }
 779 
 780 
 781     @DataProvider(name="GoodTemporalUnit")
 782     Object[][] data_goodTemporalUnit() {
 783         return new Object[][] {
 784             {2, ChronoUnit.DAYS},
 785             {2, ChronoUnit.MONTHS},
 786             {2, ChronoUnit.YEARS},
 787         };
 788     }
 789 
 790     @Test(dataProvider="GoodTemporalUnit")
 791     public void test_good_getUnit(long amount, TemporalUnit unit) {
 792         Period period = Period.of(2, 2, 2);
 793         long actual = period.get(unit);
 794         assertEquals(actual, amount, "Value of unit: " + unit);
 795     }
 796 
 797     @DataProvider(name="BadTemporalUnit")
 798     Object[][] data_badTemporalUnit() {
 799         return new Object[][] {
 800             {ChronoUnit.MICROS},
 801             {ChronoUnit.MILLIS},
 802             {ChronoUnit.HALF_DAYS},
 803             {ChronoUnit.DECADES},
 804             {ChronoUnit.CENTURIES},
 805             {ChronoUnit.MILLENNIA},
 806         };
 807     }
 808 
 809     @Test(dataProvider="BadTemporalUnit", expectedExceptions=DateTimeException.class)
 810     public void test_bad_getUnit(TemporalUnit unit) {
 811         Period period = Period.of(2, 2, 2);
 812         period.get(unit);
 813     }
 814 
 815     //-----------------------------------------------------------------------
 816     // equals() / hashCode()
 817     //-----------------------------------------------------------------------
 818     public void test_equals() {
 819         assertEquals(Period.of(1, 0, 0).equals(Period.ofYears(1)), true);
 820         assertEquals(Period.of(0, 1, 0).equals(Period.ofMonths(1)), true);
 821         assertEquals(Period.of(0, 0, 1).equals(Period.ofDays(1)), true);
 822         assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 3)), true);
 823 
 824         assertEquals(Period.ofYears(1).equals(Period.ofYears(1)), true);
 825         assertEquals(Period.ofYears(1).equals(Period.ofYears(2)), false);
 826 
 827         assertEquals(Period.ofMonths(1).equals(Period.ofMonths(1)), true);
 828         assertEquals(Period.ofMonths(1).equals(Period.ofMonths(2)), false);
 829 
 830         assertEquals(Period.ofDays(1).equals(Period.ofDays(1)), true);
 831         assertEquals(Period.ofDays(1).equals(Period.ofDays(2)), false);
 832 
 833         assertEquals(Period.of(1, 2, 3).equals(Period.of(0, 2, 3)), false);
 834         assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 0, 3)), false);
 835         assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 0)), false);
 836     }
 837 
 838     public void test_equals_self() {
 839         Period test = Period.of(1, 2, 3);
 840         assertEquals(test.equals(test), true);
 841     }
 842 
 843     public void test_equals_null() {
 844         Period test = Period.of(1, 2, 3);
 845         assertEquals(test.equals(null), false);
 846     }
 847 
 848     public void test_equals_otherClass() {
 849         Period test = Period.of(1, 2, 3);
 850         assertEquals(test.equals(""), false);
 851     }
 852 
 853     //-----------------------------------------------------------------------
 854     public void test_hashCode() {
 855         Period test5 = Period.ofDays(5);
 856         Period test6 = Period.ofDays(6);
 857         Period test5M = Period.ofMonths(5);
 858         Period test5Y = Period.ofYears(5);
 859         assertEquals(test5.hashCode() == test5.hashCode(), true);
 860         assertEquals(test5.hashCode() == test6.hashCode(), false);
 861     }
 862 
 863     //-----------------------------------------------------------------------
 864     // toString()
 865     //-----------------------------------------------------------------------
 866     @DataProvider(name="toStringAndParse")
 867     Object[][] data_toString() {
 868         return new Object[][] {
 869                 {Period.ZERO, "P0D"},
 870                 {Period.ofDays(0), "P0D"},
 871                 {Period.ofYears(1), "P1Y"},
 872                 {Period.ofMonths(1), "P1M"},
 873                 {Period.ofDays(1), "P1D"},
 874                 {Period.of(1, 2, 0), "P1Y2M"},
 875                 {Period.of(0, 2, 3), "P2M3D"},
 876                 {Period.of(1, 2, 3), "P1Y2M3D"},
 877         };
 878     }
 879 
 880     @Test(dataProvider="toStringAndParse")
 881     public void test_toString(Period input, String expected) {
 882         assertEquals(input.toString(), expected);
 883     }
 884 
 885     @Test(dataProvider="toStringAndParse")
 886     public void test_parse(Period test, String expected) {
 887         assertEquals(Period.parse(expected), test);
 888     }
 889 
 890     //-----------------------------------------------------------------------
 891     private void assertPeriod(Period test, int y, int m, int d) {
 892         assertEquals(test.getYears(), y, "years");
 893         assertEquals(test.getMonths(), m, "months");
 894         assertEquals(test.getDays(), d, "days");
 895         assertEquals(test.toTotalMonths(), y * 12L + m, "totalMonths");
 896     }
 897 
 898     private static Period pymd(int y, int m, int d) {
 899         return Period.of(y, m, d);
 900     }
 901 
 902     private static LocalDate date(int y, int m, int d) {
 903         return LocalDate.of(y, m, d);
 904     }
 905 
 906 }