jdk/src/share/classes/java/time/Period.java
changeset 15658 55b829ca2334
parent 15289 3ac550392e43
child 16852 60207b2b4b42
equal deleted inserted replaced
15657:c588664d547e 15658:55b829ca2334
    59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    61  */
    61  */
    62 package java.time;
    62 package java.time;
    63 
    63 
    64 import static java.time.LocalTime.NANOS_PER_DAY;
       
    65 import static java.time.LocalTime.NANOS_PER_HOUR;
       
    66 import static java.time.LocalTime.NANOS_PER_MINUTE;
       
    67 import static java.time.LocalTime.NANOS_PER_SECOND;
       
    68 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
       
    69 import static java.time.temporal.ChronoField.EPOCH_MONTH;
       
    70 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
    64 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
    71 import static java.time.temporal.ChronoField.NANO_OF_DAY;
       
    72 import static java.time.temporal.ChronoField.YEAR;
       
    73 import static java.time.temporal.ChronoUnit.DAYS;
    65 import static java.time.temporal.ChronoUnit.DAYS;
    74 import static java.time.temporal.ChronoUnit.MONTHS;
    66 import static java.time.temporal.ChronoUnit.MONTHS;
    75 import static java.time.temporal.ChronoUnit.NANOS;
       
    76 import static java.time.temporal.ChronoUnit.YEARS;
    67 import static java.time.temporal.ChronoUnit.YEARS;
    77 
    68 
       
    69 import java.io.DataInput;
       
    70 import java.io.DataOutput;
       
    71 import java.io.IOException;
       
    72 import java.io.InvalidObjectException;
       
    73 import java.io.ObjectStreamException;
    78 import java.io.Serializable;
    74 import java.io.Serializable;
       
    75 import java.time.chrono.ChronoLocalDate;
       
    76 import java.time.chrono.Chronology;
    79 import java.time.format.DateTimeParseException;
    77 import java.time.format.DateTimeParseException;
    80 import java.time.temporal.Chrono;
       
    81 import java.time.temporal.ChronoField;
       
    82 import java.time.temporal.ChronoUnit;
    78 import java.time.temporal.ChronoUnit;
    83 import java.time.temporal.Temporal;
    79 import java.time.temporal.Temporal;
    84 import java.time.temporal.TemporalAccessor;
    80 import java.time.temporal.TemporalAmount;
    85 import java.time.temporal.TemporalAdder;
       
    86 import java.time.temporal.TemporalSubtractor;
       
    87 import java.time.temporal.TemporalUnit;
    81 import java.time.temporal.TemporalUnit;
    88 import java.time.temporal.ValueRange;
    82 import java.time.temporal.ValueRange;
       
    83 import java.util.Arrays;
       
    84 import java.util.Collections;
       
    85 import java.util.List;
    89 import java.util.Objects;
    86 import java.util.Objects;
       
    87 import java.util.regex.Matcher;
       
    88 import java.util.regex.Pattern;
    90 
    89 
    91 /**
    90 /**
    92  * A period of time, measured using the most common units, such as '3 Months, 4 Days and 7 Hours'.
    91  * A date-based amount of time, such as '2 years, 3 months and 4 days'.
    93  * <p>
    92  * <p>
    94  * A {@code Period} represents an amount of time measured in terms of the most commonly used units:
    93  * This class models a quantity or amount of time in terms of years, months and days.
    95  * <p><ul>
    94  * See {@link Duration} for the time-based equivalent to this class.
    96  * <li>{@link ChronoUnit#YEARS YEARS}</li>
    95  * <p>
    97  * <li>{@link ChronoUnit#MONTHS MONTHS}</li>
    96  * Durations and period differ in their treatment of daylight savings time
    98  * <li>{@link ChronoUnit#DAYS DAYS}</li>
    97  * when added to {@link ZonedDateTime}. A {@code Duration} will add an exact
    99  * <li>time units with an {@linkplain TemporalUnit#isDurationEstimated() exact duration}</li>
    98  * number of seconds, thus a duration of one day is always exactly 24 hours.
   100  * </ul><p>
    99  * By contrast, a {@code Period} will add a conceptual day, trying to maintain
   101  * The period may be used with any calendar system with the exception is methods with an "ISO" suffix.
   100  * the local time.
   102  * The meaning of a "year" or a "month" is only applied when the object is added to a date.
   101  * <p>
       
   102  * For example, consider adding a period of one day and a duration of one day to
       
   103  * 18:00 on the evening before a daylight savings gap. The {@code Period} will add
       
   104  * the conceptual day and result in a {@code ZonedDateTime} at 18:00 the following day.
       
   105  * By contrast, the {@code Duration} will add exactly 24 hours, resulting in a
       
   106  * {@code ZonedDateTime} at 19:00 the following day (assuming a one hour DST gap).
       
   107  * <p>
       
   108  * The supported units of a period are {@link ChronoUnit#YEARS YEARS},
       
   109  * {@link ChronoUnit#MONTHS MONTHS} and {@link ChronoUnit#DAYS DAYS}.
       
   110  * All three fields are always present, but may be set to zero.
       
   111  * <p>
       
   112  * The period may be used with any calendar system.
       
   113  * The meaning of a "year" or "month" is only applied when the object is added to a date.
   103  * <p>
   114  * <p>
   104  * The period is modeled as a directed amount of time, meaning that individual parts of the
   115  * The period is modeled as a directed amount of time, meaning that individual parts of the
   105  * period may be negative.
   116  * period may be negative.
       
   117  * <p>
       
   118  * The months and years fields may be {@linkplain #normalized() normalized}.
       
   119  * The normalization assumes a 12 month year, so is not appropriate for all calendar systems.
   106  *
   120  *
   107  * <h3>Specification for implementors</h3>
   121  * <h3>Specification for implementors</h3>
   108  * This class is immutable and thread-safe.
   122  * This class is immutable and thread-safe.
   109  * The maximum number of hours that can be stored is about 2.5 million, limited by storing
       
   110  * a single {@code long} nanoseconds for all time units internally.
       
   111  *
   123  *
   112  * @since 1.8
   124  * @since 1.8
   113  */
   125  */
   114 public final class Period
   126 public final class Period
   115         implements TemporalAdder, TemporalSubtractor, Serializable {
   127         implements TemporalAmount, Serializable {
   116     // maximum hours is 2,562,047
       
   117 
   128 
   118     /**
   129     /**
   119      * A constant for a period of zero.
   130      * A constant for a period of zero.
   120      */
   131      */
   121     public static final Period ZERO = new Period(0, 0, 0, 0);
   132     public static final Period ZERO = new Period(0, 0, 0);
   122     /**
   133     /**
   123      * Serialization version.
   134      * Serialization version.
   124      */
   135      */
   125     private static final long serialVersionUID = -8290556941213247973L;
   136     private static final long serialVersionUID = -3587258372562876L;
       
   137     /**
       
   138      * The pattern for parsing.
       
   139      */
       
   140     private final static Pattern PATTERN =
       
   141             Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)Y)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)D)?", Pattern.CASE_INSENSITIVE);
       
   142     /**
       
   143      * The set of supported units.
       
   144      */
       
   145     private final static List<TemporalUnit> SUPPORTED_UNITS =
       
   146             Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS));
   126 
   147 
   127     /**
   148     /**
   128      * The number of years.
   149      * The number of years.
   129      */
   150      */
   130     private final int years;
   151     private final int years;
   134     private final int months;
   155     private final int months;
   135     /**
   156     /**
   136      * The number of days.
   157      * The number of days.
   137      */
   158      */
   138     private final int days;
   159     private final int days;
   139     /**
   160 
   140      * The number of nanoseconds.
   161     //-----------------------------------------------------------------------
   141      */
   162     /**
   142     private final long nanos;
   163      * Obtains a {@code Period} representing a number of years.
   143 
   164      * <p>
   144     //-----------------------------------------------------------------------
   165      * The resulting period will have the specified years.
   145     /**
   166      * The months and days units will be zero.
   146      * Obtains a {@code Period} from date-based and time-based fields.
   167      *
   147      * <p>
   168      * @param years  the number of years, positive or negative
   148      * This creates an instance based on years, months, days, hours, minutes and seconds.
   169      * @return the period of years, not null
   149      * Within a period, the time fields are always normalized.
   170      */
       
   171     public static Period ofYears(int years) {
       
   172         return create(years, 0, 0);
       
   173     }
       
   174 
       
   175     /**
       
   176      * Obtains a {@code Period} representing a number of months.
       
   177      * <p>
       
   178      * The resulting period will have the specified months.
       
   179      * The years and days units will be zero.
       
   180      *
       
   181      * @param months  the number of months, positive or negative
       
   182      * @return the period of months, not null
       
   183      */
       
   184     public static Period ofMonths(int months) {
       
   185         return create(0, months, 0);
       
   186     }
       
   187 
       
   188     /**
       
   189      * Obtains a {@code Period} representing a number of days.
       
   190      * <p>
       
   191      * The resulting period will have the specified days.
       
   192      * The years and months units will be zero.
       
   193      *
       
   194      * @param days  the number of days, positive or negative
       
   195      * @return the period of days, not null
       
   196      */
       
   197     public static Period ofDays(int days) {
       
   198         return create(0, 0, days);
       
   199     }
       
   200 
       
   201     //-----------------------------------------------------------------------
       
   202     /**
       
   203      * Obtains a {@code Period} representing a number of years, months and days.
       
   204      * <p>
       
   205      * This creates an instance based on years, months and days.
   150      *
   206      *
   151      * @param years  the amount of years, may be negative
   207      * @param years  the amount of years, may be negative
   152      * @param months  the amount of months, may be negative
   208      * @param months  the amount of months, may be negative
   153      * @param days  the amount of days, may be negative
   209      * @param days  the amount of days, may be negative
   154      * @param hours  the amount of hours, may be negative
   210      * @return the period of years, months and days, not null
   155      * @param minutes  the amount of minutes, may be negative
   211      */
   156      * @param seconds  the amount of seconds, may be negative
   212     public static Period of(int years, int months, int days) {
   157      * @return the period, not null
   213         return create(years, months, days);
   158      */
       
   159     public static Period of(int years, int months, int days, int hours, int minutes, int seconds) {
       
   160         return of(years, months, days, hours, minutes, seconds, 0);
       
   161     }
       
   162 
       
   163     /**
       
   164      * Obtains a {@code Period} from date-based and time-based fields.
       
   165      * <p>
       
   166      * This creates an instance based on years, months, days, hours, minutes, seconds and nanoseconds.
       
   167      * Within a period, the time fields are always normalized.
       
   168      *
       
   169      * @param years  the amount of years, may be negative
       
   170      * @param months  the amount of months, may be negative
       
   171      * @param days  the amount of days, may be negative
       
   172      * @param hours  the amount of hours, may be negative
       
   173      * @param minutes  the amount of minutes, may be negative
       
   174      * @param seconds  the amount of seconds, may be negative
       
   175      * @param nanos  the amount of nanos, may be negative
       
   176      * @return the period, not null
       
   177      */
       
   178     public static Period of(int years, int months, int days, int hours, int minutes, int seconds, long nanos) {
       
   179         if ((years | months | days | hours | minutes | seconds | nanos) == 0) {
       
   180             return ZERO;
       
   181         }
       
   182         long totSecs = Math.addExact(hours * 3600L, minutes * 60L) + seconds;
       
   183         long totNanos = Math.addExact(Math.multiplyExact(totSecs, 1_000_000_000L), nanos);
       
   184         return create(years, months, days, totNanos);
       
   185     }
       
   186 
       
   187     //-----------------------------------------------------------------------
       
   188     /**
       
   189      * Obtains a {@code Period} from date-based fields.
       
   190      * <p>
       
   191      * This creates an instance based on years, months and days.
       
   192      *
       
   193      * @param years  the amount of years, may be negative
       
   194      * @param months  the amount of months, may be negative
       
   195      * @param days  the amount of days, may be negative
       
   196      * @return the period, not null
       
   197      */
       
   198     public static Period ofDate(int years, int months, int days) {
       
   199         return of(years, months, days, 0, 0, 0, 0);
       
   200     }
       
   201 
       
   202     //-----------------------------------------------------------------------
       
   203     /**
       
   204      * Obtains a {@code Period} from time-based fields.
       
   205      * <p>
       
   206      * This creates an instance based on hours, minutes and seconds.
       
   207      * Within a period, the time fields are always normalized.
       
   208      *
       
   209      * @param hours  the amount of hours, may be negative
       
   210      * @param minutes  the amount of minutes, may be negative
       
   211      * @param seconds  the amount of seconds, may be negative
       
   212      * @return the period, not null
       
   213      */
       
   214     public static Period ofTime(int hours, int minutes, int seconds) {
       
   215         return of(0, 0, 0, hours, minutes, seconds, 0);
       
   216     }
       
   217 
       
   218     /**
       
   219      * Obtains a {@code Period} from time-based fields.
       
   220      * <p>
       
   221      * This creates an instance based on hours, minutes, seconds and nanoseconds.
       
   222      * Within a period, the time fields are always normalized.
       
   223      *
       
   224      * @param hours  the amount of hours, may be negative
       
   225      * @param minutes  the amount of minutes, may be negative
       
   226      * @param seconds  the amount of seconds, may be negative
       
   227      * @param nanos  the amount of nanos, may be negative
       
   228      * @return the period, not null
       
   229      */
       
   230     public static Period ofTime(int hours, int minutes, int seconds, long nanos) {
       
   231         return of(0, 0, 0, hours, minutes, seconds, nanos);
       
   232     }
       
   233 
       
   234     //-----------------------------------------------------------------------
       
   235     /**
       
   236      * Obtains an instance of {@code Period} from a period in the specified unit.
       
   237      * <p>
       
   238      * The parameters represent the two parts of a phrase like '6 Days'. For example:
       
   239      * <pre>
       
   240      *  Period.of(3, SECONDS);
       
   241      *  Period.of(5, YEARS);
       
   242      * </pre>
       
   243      * The specified unit must be one of the supported units from {@link ChronoUnit},
       
   244      * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an
       
   245      * {@linkplain TemporalUnit#isDurationEstimated() exact duration}.
       
   246      * Other units throw an exception.
       
   247      *
       
   248      * @param amount  the amount of the period, measured in terms of the unit, positive or negative
       
   249      * @param unit  the unit that the period is measured in, must have an exact duration, not null
       
   250      * @return the period, not null
       
   251      * @throws DateTimeException if the period unit is invalid
       
   252      * @throws ArithmeticException if a numeric overflow occurs
       
   253      */
       
   254     public static Period of(long amount, TemporalUnit unit) {
       
   255         return ZERO.plus(amount, unit);
       
   256     }
       
   257 
       
   258     //-----------------------------------------------------------------------
       
   259     /**
       
   260      * Obtains a {@code Period} from a {@code Duration}.
       
   261      * <p>
       
   262      * This converts the duration to a period.
       
   263      * Within a period, the time fields are always normalized.
       
   264      * The years, months and days fields will be zero.
       
   265      * <p>
       
   266      * To populate the days field, call {@link #normalizedHoursToDays()} on the created period.
       
   267      *
       
   268      * @param duration  the duration to convert, not null
       
   269      * @return the period, not null
       
   270      * @throws ArithmeticException if numeric overflow occurs
       
   271      */
       
   272     public static Period of(Duration duration) {
       
   273         Objects.requireNonNull(duration, "duration");
       
   274         if (duration.isZero()) {
       
   275             return ZERO;
       
   276         }
       
   277         return new Period(0, 0, 0, duration.toNanos());
       
   278     }
       
   279 
       
   280     //-----------------------------------------------------------------------
       
   281     /**
       
   282      * Returns a {@code Period} consisting of the number of years, months, days,
       
   283      * hours, minutes, seconds, and nanoseconds between two {@code TemporalAccessor} instances.
       
   284      * <p>
       
   285      * The start date is included, but the end date is not. Only whole years count.
       
   286      * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days.
       
   287      * <p>
       
   288      * This method examines the {@link ChronoField fields} {@code YEAR}, {@code MONTH_OF_YEAR},
       
   289      * {@code DAY_OF_MONTH} and {@code NANO_OF_DAY}
       
   290      * The difference between each of the fields is calculated independently from the others.
       
   291      * At least one of the four fields must be present.
       
   292      * <p>
       
   293      * The four units are typically retained without normalization.
       
   294      * However, years and months are normalized if the range of months is fixed, as it is with ISO.
       
   295      * <p>
       
   296      * The result of this method can be a negative period if the end is before the start.
       
   297      * The negative sign can be different in each of the four major units.
       
   298      *
       
   299      * @param start  the start date, inclusive, not null
       
   300      * @param end  the end date, exclusive, not null
       
   301      * @return the period between the date-times, not null
       
   302      * @throws DateTimeException if the two date-times do have similar available fields
       
   303      * @throws ArithmeticException if numeric overflow occurs
       
   304      */
       
   305     public static Period between(TemporalAccessor start, TemporalAccessor end) {
       
   306         if (Chrono.from(start).equals(Chrono.from(end)) == false) {
       
   307             throw new DateTimeException("Unable to calculate period as date-times have different chronologies");
       
   308         }
       
   309         int years = 0;
       
   310         int months = 0;
       
   311         int days = 0;
       
   312         long nanos = 0;
       
   313         boolean valid = false;
       
   314         if (start.isSupported(YEAR)) {
       
   315             years = Math.toIntExact(Math.subtractExact(end.getLong(YEAR), start.getLong(YEAR)));
       
   316             valid = true;
       
   317         }
       
   318         if (start.isSupported(MONTH_OF_YEAR)) {
       
   319             months = Math.toIntExact(Math.subtractExact(end.getLong(MONTH_OF_YEAR), start.getLong(MONTH_OF_YEAR)));
       
   320             ValueRange startRange = Chrono.from(start).range(MONTH_OF_YEAR);
       
   321             ValueRange endRange = Chrono.from(end).range(MONTH_OF_YEAR);
       
   322             if (startRange.isFixed() && startRange.isIntValue() && startRange.equals(endRange)) {
       
   323                 int monthCount = (int) (startRange.getMaximum() - startRange.getMinimum() + 1);
       
   324                 long totMonths = ((long) months) + years * monthCount;
       
   325                 months = (int) (totMonths % monthCount);
       
   326                 years = Math.toIntExact(totMonths / monthCount);
       
   327             }
       
   328             valid = true;
       
   329         }
       
   330         if (start.isSupported(DAY_OF_MONTH)) {
       
   331             days = Math.toIntExact(Math.subtractExact(end.getLong(DAY_OF_MONTH), start.getLong(DAY_OF_MONTH)));
       
   332             valid = true;
       
   333         }
       
   334         if (start.isSupported(NANO_OF_DAY)) {
       
   335             nanos = Math.subtractExact(end.getLong(NANO_OF_DAY), start.getLong(NANO_OF_DAY));
       
   336             valid = true;
       
   337         }
       
   338         if (valid == false) {
       
   339             throw new DateTimeException("Unable to calculate period as date-times do not have any valid fields");
       
   340         }
       
   341         return create(years, months, days, nanos);
       
   342     }
   214     }
   343 
   215 
   344     //-----------------------------------------------------------------------
   216     //-----------------------------------------------------------------------
   345     /**
   217     /**
   346      * Obtains a {@code Period} consisting of the number of years, months,
   218      * Obtains a {@code Period} consisting of the number of years, months,
   356      * The result of this method can be a negative period if the end is before the start.
   228      * The result of this method can be a negative period if the end is before the start.
   357      * The negative sign will be the same in each of year, month and day.
   229      * The negative sign will be the same in each of year, month and day.
   358      *
   230      *
   359      * @param startDate  the start date, inclusive, not null
   231      * @param startDate  the start date, inclusive, not null
   360      * @param endDate  the end date, exclusive, not null
   232      * @param endDate  the end date, exclusive, not null
   361      * @return the period between the dates, not null
   233      * @return the period between this date and the end date, not null
   362      * @throws ArithmeticException if numeric overflow occurs
   234      * @see ChronoLocalDate#periodUntil(ChronoLocalDate)
   363      */
   235      */
   364     public static Period betweenISO(LocalDate startDate, LocalDate endDate) {
   236     public static Period between(LocalDate startDate, LocalDate endDate) {
   365         long startMonth = startDate.getLong(EPOCH_MONTH);
   237         return startDate.periodUntil(endDate);
   366         long endMonth = endDate.getLong(EPOCH_MONTH);
   238     }
   367         long totalMonths = endMonth - startMonth;  // safe
   239 
   368         int days = endDate.getDayOfMonth() - startDate.getDayOfMonth();
   240     //-----------------------------------------------------------------------
   369         if (totalMonths > 0 && days < 0) {
   241     /**
   370             totalMonths--;
   242      * Obtains a {@code Period} from a text string such as {@code PnYnMnD}.
   371             LocalDate calcDate = startDate.plusMonths(totalMonths);
       
   372             days = (int) (endDate.toEpochDay() - calcDate.toEpochDay());  // safe
       
   373         } else if (totalMonths < 0 && days > 0) {
       
   374             totalMonths++;
       
   375             days -= endDate.lengthOfMonth();
       
   376         }
       
   377         long years = totalMonths / 12;  // safe
       
   378         int months = (int) (totalMonths % 12);  // safe
       
   379         return ofDate(Math.toIntExact(years), months, days);
       
   380     }
       
   381 
       
   382     //-----------------------------------------------------------------------
       
   383     /**
       
   384      * Obtains a {@code Period} consisting of the number of hours, minutes,
       
   385      * seconds and nanoseconds between two times.
       
   386      * <p>
       
   387      * The start time is included, but the end time is not.
       
   388      * The period is calculated from the difference between the nano-of-day values
       
   389      * of the two times. For example, from {@code 13:45:00} to {@code 14:50:30.123456789}
       
   390      * is {@code P1H5M30.123456789S}.
       
   391      * <p>
       
   392      * The result of this method can be a negative period if the end is before the start.
       
   393      *
       
   394      * @param startTime  the start time, inclusive, not null
       
   395      * @param endTime  the end time, exclusive, not null
       
   396      * @return the period between the times, not null
       
   397      * @throws ArithmeticException if numeric overflow occurs
       
   398      */
       
   399     public static Period betweenISO(LocalTime startTime, LocalTime endTime) {
       
   400         return create(0, 0, 0, endTime.toNanoOfDay() - startTime.toNanoOfDay());
       
   401     }
       
   402 
       
   403     //-----------------------------------------------------------------------
       
   404     /**
       
   405      * Obtains a {@code Period} from a text string such as {@code PnYnMnDTnHnMn.nS}.
       
   406      * <p>
   243      * <p>
   407      * This will parse the string produced by {@code toString()} which is
   244      * This will parse the string produced by {@code toString()} which is
   408      * a subset of the ISO-8601 period format {@code PnYnMnDTnHnMn.nS}.
   245      * based on the ISO-8601 period format {@code PnYnMnD}.
   409      * <p>
   246      * <p>
   410      * The string consists of a series of numbers with a suffix identifying their meaning.
   247      * The string starts with an optional sign, denoted by the ASCII negative
   411      * The values, and suffixes, must be in the sequence year, month, day, hour, minute, second.
   248      * or positive symbol. If negative, the whole period is negated.
   412      * Any of the number/suffix pairs may be omitted providing at least one is present.
   249      * The ASCII letter "P" is next in upper or lower case.
   413      * If the period is zero, the value is normally represented as {@code PT0S}.
   250      * There are then three sections, each consisting of a number and a suffix.
   414      * The numbers must consist of ASCII digits.
   251      * At least one of the three sections must be present.
   415      * Any of the numbers may be negative. Negative zero is not accepted.
   252      * The sections have suffixes in ASCII of "Y", "M" and "D" for
   416      * The number of nanoseconds is expressed as an optional fraction of the seconds.
   253      * years, months and days, accepted in upper or lower case.
   417      * There must be at least one digit before any decimal point.
   254      * The suffixes must occur in order.
   418      * There must be between 1 and 9 inclusive digits after any decimal point.
   255      * The number part of each section must consist of ASCII digits.
   419      * The letters will all be accepted in upper or lower case.
   256      * The number may be prefixed by the ASCII negative or positive symbol.
   420      * The decimal point may be either a dot or a comma.
   257      * The number must parse to an {@code int}.
       
   258      * <p>
       
   259      * The leading plus/minus sign, and negative values for other units are
       
   260      * not part of the ISO-8601 standard.
   421      *
   261      *
   422      * @param text  the text to parse, not null
   262      * @param text  the text to parse, not null
   423      * @return the parsed period, not null
   263      * @return the parsed period, not null
   424      * @throws DateTimeParseException if the text cannot be parsed to a period
   264      * @throws DateTimeParseException if the text cannot be parsed to a period
   425      */
   265      */
   426     public static Period parse(final CharSequence text) {
   266     public static Period parse(CharSequence text) {
   427         Objects.requireNonNull(text, "text");
   267         Objects.requireNonNull(text, "text");
   428         return new PeriodParser(text).parse();
   268         Matcher matcher = PATTERN.matcher(text);
       
   269         if (matcher.matches()) {
       
   270             int negate = ("-".equals(matcher.group(1)) ? -1 : 1);
       
   271             String yearMatch = matcher.group(2);
       
   272             String monthMatch = matcher.group(3);
       
   273             String dayMatch = matcher.group(4);
       
   274             if (yearMatch != null || monthMatch != null || dayMatch != null) {
       
   275                 try {
       
   276                     return create(parseNumber(text, yearMatch, negate),
       
   277                             parseNumber(text, monthMatch, negate),
       
   278                             parseNumber(text, dayMatch, negate));
       
   279                 } catch (NumberFormatException ex) {
       
   280                     throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Period", text, 0).initCause(ex);
       
   281                 }
       
   282             }
       
   283         }
       
   284         throw new DateTimeParseException("Text cannot be parsed to a Period", text, 0);
       
   285     }
       
   286 
       
   287     private static int parseNumber(CharSequence text, String str, int negate) {
       
   288         if (str == null) {
       
   289             return 0;
       
   290         }
       
   291         int val = Integer.parseInt(str);
       
   292         try {
       
   293             return Math.multiplyExact(val, negate);
       
   294         } catch (ArithmeticException ex) {
       
   295             throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Period", text, 0).initCause(ex);
       
   296         }
   429     }
   297     }
   430 
   298 
   431     //-----------------------------------------------------------------------
   299     //-----------------------------------------------------------------------
   432     /**
   300     /**
   433      * Creates an instance.
   301      * Creates an instance.
   434      *
   302      *
   435      * @param years  the amount
   303      * @param years  the amount
   436      * @param months  the amount
   304      * @param months  the amount
   437      * @param days  the amount
   305      * @param days  the amount
   438      * @param nanos  the amount
   306      */
   439      */
   307     private static Period create(int years, int months, int days) {
   440     private static Period create(int years, int months, int days, long nanos) {
   308         if ((years | months | days) == 0) {
   441         if ((years | months | days | nanos) == 0) {
       
   442             return ZERO;
   309             return ZERO;
   443         }
   310         }
   444         return new Period(years, months, days, nanos);
   311         return new Period(years, months, days);
   445     }
   312     }
   446 
   313 
   447     /**
   314     /**
   448      * Constructor.
   315      * Constructor.
   449      *
   316      *
   450      * @param years  the amount
   317      * @param years  the amount
   451      * @param months  the amount
   318      * @param months  the amount
   452      * @param days  the amount
   319      * @param days  the amount
   453      * @param nanos  the amount
   320      */
   454      */
   321     private Period(int years, int months, int days) {
   455     private Period(int years, int months, int days, long nanos) {
       
   456         this.years = years;
   322         this.years = years;
   457         this.months = months;
   323         this.months = months;
   458         this.days = days;
   324         this.days = days;
   459         this.nanos = nanos;
   325     }
   460     }
   326 
   461 
   327     //-----------------------------------------------------------------------
   462     /**
   328     /**
   463      * Resolves singletons.
   329      * Gets the value of the requested unit.
   464      *
   330      * <p>
   465      * @return the resolved instance
   331      * This returns a value for each of the three supported units,
   466      */
   332      * {@link ChronoUnit#YEARS YEARS}, {@link ChronoUnit#MONTHS MONTHS} and
   467     private Object readResolve() {
   333      * {@link ChronoUnit#DAYS DAYS}.
   468         if ((years | months | days | nanos) == 0) {
   334      * All other units throw an exception.
   469             return ZERO;
   335      *
   470         }
   336      * @param unit the {@code TemporalUnit} for which to return the value
   471         return this;
   337      * @return the long value of the unit
   472     }
   338      * @throws DateTimeException if the unit is not supported
   473 
   339      */
   474     //-----------------------------------------------------------------------
   340     @Override
   475     /**
   341     public long get(TemporalUnit unit) {
   476      * Checks if this period is zero-length.
   342         if (unit == ChronoUnit.YEARS) {
       
   343             return getYears();
       
   344         } else if (unit == ChronoUnit.MONTHS) {
       
   345             return getMonths();
       
   346         } else if (unit == ChronoUnit.DAYS) {
       
   347             return getDays();
       
   348         } else {
       
   349             throw new DateTimeException("Unsupported unit: " + unit.getName());
       
   350         }
       
   351     }
       
   352 
       
   353     /**
       
   354      * Gets the set of units supported by this period.
       
   355      * <p>
       
   356      * The supported units are {@link ChronoUnit#YEARS YEARS},
       
   357      * {@link ChronoUnit#MONTHS MONTHS} and {@link ChronoUnit#DAYS DAYS}.
       
   358      * They are returned in the order years, months, days.
       
   359      * <p>
       
   360      * This set can be used in conjunction with {@link #get(TemporalUnit)}
       
   361      * to access the entire state of the period.
       
   362      *
       
   363      * @return a list containing the years, months and days units, not null
       
   364      */
       
   365     @Override
       
   366     public List<TemporalUnit> getUnits() {
       
   367         return SUPPORTED_UNITS;
       
   368     }
       
   369 
       
   370     //-----------------------------------------------------------------------
       
   371     /**
       
   372      * Checks if all three units of this period are zero.
       
   373      * <p>
       
   374      * A zero period has the value zero for the years, months and days units.
   477      *
   375      *
   478      * @return true if this period is zero-length
   376      * @return true if this period is zero-length
   479      */
   377      */
   480     public boolean isZero() {
   378     public boolean isZero() {
   481         return (this == ZERO);
   379         return (this == ZERO);
   482     }
   380     }
   483 
   381 
   484     /**
   382     /**
   485      * Checks if this period is fully positive, excluding zero.
   383      * Checks if any of the three units of this period are negative.
   486      * <p>
   384      * <p>
   487      * This checks whether all the amounts in the period are positive,
   385      * This checks whether the years, months or days units are less than zero.
   488      * defined as greater than zero.
   386      *
   489      *
   387      * @return true if any unit of this period is negative
   490      * @return true if this period is fully positive excluding zero
   388      */
   491      */
   389     public boolean isNegative() {
   492     public boolean isPositive() {
   390         return years < 0 || months < 0 || days < 0;
   493         return ((years | months | days | nanos) > 0);
       
   494     }
   391     }
   495 
   392 
   496     //-----------------------------------------------------------------------
   393     //-----------------------------------------------------------------------
   497     /**
   394     /**
   498      * Gets the amount of years of this period.
   395      * Gets the amount of years of this period.
   499      *
   396      * <p>
   500      * @return the amount of years of this period
   397      * This returns the years unit.
       
   398      * <p>
       
   399      * The months unit is not normalized with the years unit.
       
   400      * This means that a period of "15 months" is different to a period
       
   401      * of "1 year and 3 months".
       
   402      *
       
   403      * @return the amount of years of this period, may be negative
   501      */
   404      */
   502     public int getYears() {
   405     public int getYears() {
   503         return years;
   406         return years;
   504     }
   407     }
   505 
   408 
   506     /**
   409     /**
   507      * Gets the amount of months of this period.
   410      * Gets the amount of months of this period.
   508      *
   411      * <p>
   509      * @return the amount of months of this period
   412      * This returns the months unit.
       
   413      * <p>
       
   414      * The months unit is not normalized with the years unit.
       
   415      * This means that a period of "15 months" is different to a period
       
   416      * of "1 year and 3 months".
       
   417      *
       
   418      * @return the amount of months of this period, may be negative
   510      */
   419      */
   511     public int getMonths() {
   420     public int getMonths() {
   512         return months;
   421         return months;
   513     }
   422     }
   514 
   423 
   515     /**
   424     /**
   516      * Gets the amount of days of this period.
   425      * Gets the amount of days of this period.
   517      *
   426      * <p>
   518      * @return the amount of days of this period
   427      * This returns the days unit.
       
   428      *
       
   429      * @return the amount of days of this period, may be negative
   519      */
   430      */
   520     public int getDays() {
   431     public int getDays() {
   521         return days;
   432         return days;
   522     }
   433     }
   523 
   434 
   524     /**
       
   525      * Gets the amount of hours of this period.
       
   526      * <p>
       
   527      * Within a period, the time fields are always normalized.
       
   528      *
       
   529      * @return the amount of hours of this period
       
   530      */
       
   531     public int getHours() {
       
   532         return (int) (nanos / NANOS_PER_HOUR);
       
   533     }
       
   534 
       
   535     /**
       
   536      * Gets the amount of minutes within an hour of this period.
       
   537      * <p>
       
   538      * Within a period, the time fields are always normalized.
       
   539      *
       
   540      * @return the amount of minutes within an hour of this period
       
   541      */
       
   542     public int getMinutes() {
       
   543         return (int) ((nanos / NANOS_PER_MINUTE) % 60);
       
   544     }
       
   545 
       
   546     /**
       
   547      * Gets the amount of seconds within a minute of this period.
       
   548      * <p>
       
   549      * Within a period, the time fields are always normalized.
       
   550      *
       
   551      * @return the amount of seconds within a minute of this period
       
   552      */
       
   553     public int getSeconds() {
       
   554         return (int) ((nanos / NANOS_PER_SECOND) % 60);
       
   555     }
       
   556 
       
   557     /**
       
   558      * Gets the amount of nanoseconds within a second of this period.
       
   559      * <p>
       
   560      * Within a period, the time fields are always normalized.
       
   561      *
       
   562      * @return the amount of nanoseconds within a second of this period
       
   563      */
       
   564     public int getNanos() {
       
   565         return (int) (nanos % NANOS_PER_SECOND);  // safe from overflow
       
   566     }
       
   567 
       
   568     /**
       
   569      * Gets the total amount of the time units of this period, measured in nanoseconds.
       
   570      * <p>
       
   571      * Within a period, the time fields are always normalized.
       
   572      *
       
   573      * @return the total amount of time unit nanoseconds of this period
       
   574      */
       
   575     public long getTimeNanos() {
       
   576         return nanos;
       
   577     }
       
   578 
       
   579     //-----------------------------------------------------------------------
   435     //-----------------------------------------------------------------------
   580     /**
   436     /**
   581      * Returns a copy of this period with the specified amount of years.
   437      * Returns a copy of this period with the specified amount of years.
   582      * <p>
   438      * <p>
   583      * This method will only affect the years field.
   439      * This sets the amount of the years unit in a copy of this period.
   584      * All other units are unaffected.
   440      * The months and days units are unaffected.
   585      * <p>
   441      * <p>
   586      * This instance is immutable and unaffected by this method call.
   442      * The months unit is not normalized with the years unit.
   587      *
   443      * This means that a period of "15 months" is different to a period
   588      * @param years  the years to represent
   444      * of "1 year and 3 months".
       
   445      * <p>
       
   446      * This instance is immutable and unaffected by this method call.
       
   447      *
       
   448      * @param years  the years to represent, may be negative
   589      * @return a {@code Period} based on this period with the requested years, not null
   449      * @return a {@code Period} based on this period with the requested years, not null
   590      */
   450      */
   591     public Period withYears(int years) {
   451     public Period withYears(int years) {
   592         if (years == this.years) {
   452         if (years == this.years) {
   593             return this;
   453             return this;
   594         }
   454         }
   595         return create(years, months, days, nanos);
   455         return create(years, months, days);
   596     }
   456     }
   597 
   457 
   598     /**
   458     /**
   599      * Returns a copy of this period with the specified amount of months.
   459      * Returns a copy of this period with the specified amount of months.
   600      * <p>
   460      * <p>
   601      * This method will only affect the months field.
   461      * This sets the amount of the months unit in a copy of this period.
   602      * All other units are unaffected.
   462      * The years and days units are unaffected.
   603      * <p>
   463      * <p>
   604      * This instance is immutable and unaffected by this method call.
   464      * The months unit is not normalized with the years unit.
   605      *
   465      * This means that a period of "15 months" is different to a period
   606      * @param months  the months to represent
   466      * of "1 year and 3 months".
       
   467      * <p>
       
   468      * This instance is immutable and unaffected by this method call.
       
   469      *
       
   470      * @param months  the months to represent, may be negative
   607      * @return a {@code Period} based on this period with the requested months, not null
   471      * @return a {@code Period} based on this period with the requested months, not null
   608      */
   472      */
   609     public Period withMonths(int months) {
   473     public Period withMonths(int months) {
   610         if (months == this.months) {
   474         if (months == this.months) {
   611             return this;
   475             return this;
   612         }
   476         }
   613         return create(years, months, days, nanos);
   477         return create(years, months, days);
   614     }
   478     }
   615 
   479 
   616     /**
   480     /**
   617      * Returns a copy of this period with the specified amount of days.
   481      * Returns a copy of this period with the specified amount of days.
   618      * <p>
   482      * <p>
   619      * This method will only affect the days field.
   483      * This sets the amount of the days unit in a copy of this period.
   620      * All other units are unaffected.
   484      * The years and months units are unaffected.
   621      * <p>
   485      * <p>
   622      * This instance is immutable and unaffected by this method call.
   486      * This instance is immutable and unaffected by this method call.
   623      *
   487      *
   624      * @param days  the days to represent
   488      * @param days  the days to represent, may be negative
   625      * @return a {@code Period} based on this period with the requested days, not null
   489      * @return a {@code Period} based on this period with the requested days, not null
   626      */
   490      */
   627     public Period withDays(int days) {
   491     public Period withDays(int days) {
   628         if (days == this.days) {
   492         if (days == this.days) {
   629             return this;
   493             return this;
   630         }
   494         }
   631         return create(years, months, days, nanos);
   495         return create(years, months, days);
   632     }
       
   633 
       
   634     /**
       
   635      * Returns a copy of this period with the specified total amount of time units
       
   636      * expressed in nanoseconds.
       
   637      * <p>
       
   638      * Within a period, the time fields are always normalized.
       
   639      * This method will affect all the time units - hours, minutes, seconds and nanos.
       
   640      * The date units are unaffected.
       
   641      * <p>
       
   642      * This instance is immutable and unaffected by this method call.
       
   643      *
       
   644      * @param nanos  the nanoseconds to represent
       
   645      * @return a {@code Period} based on this period with the requested nanoseconds, not null
       
   646      */
       
   647     public Period withTimeNanos(long nanos) {
       
   648         if (nanos == this.nanos) {
       
   649             return this;
       
   650         }
       
   651         return create(years, months, days, nanos);
       
   652     }
   496     }
   653 
   497 
   654     //-----------------------------------------------------------------------
   498     //-----------------------------------------------------------------------
   655     /**
   499     /**
   656      * Returns a copy of this period with the specified period added.
   500      * Returns a copy of this period with the specified period added.
   657      * <p>
   501      * <p>
   658      * This operates separately on the years, months, days and the normalized time.
   502      * This operates separately on the years, months, days and the normalized time.
   659      * There is no further normalization beyond the normalized time.
   503      * There is no further normalization beyond the normalized time.
   660      * <p>
   504      * <p>
   661      * This instance is immutable and unaffected by this method call.
   505      * For example, "1 year, 6 months and 3 days" plus "2 years, 2 months and 2 days"
   662      *
   506      * returns "3 years, 8 months and 5 days".
   663      * @param other  the period to add, not null
   507      * <p>
       
   508      * This instance is immutable and unaffected by this method call.
       
   509      *
       
   510      * @param amountToAdd  the period to add, not null
   664      * @return a {@code Period} based on this period with the requested period added, not null
   511      * @return a {@code Period} based on this period with the requested period added, not null
   665      * @throws ArithmeticException if numeric overflow occurs
   512      * @throws ArithmeticException if numeric overflow occurs
   666      */
   513      */
   667     public Period plus(Period other) {
   514     public Period plus(Period amountToAdd) {
   668         return create(
   515         return create(
   669                 Math.addExact(years, other.years),
   516                 Math.addExact(years, amountToAdd.years),
   670                 Math.addExact(months, other.months),
   517                 Math.addExact(months, amountToAdd.months),
   671                 Math.addExact(days, other.days),
   518                 Math.addExact(days, amountToAdd.days));
   672                 Math.addExact(nanos, other.nanos));
   519     }
   673     }
   520 
   674 
   521     /**
   675     /**
   522      * Returns a copy of this period with the specified years added.
   676      * Returns a copy of this period with the specified period added.
   523      * <p>
   677      * <p>
   524      * This adds the amount to the years unit in a copy of this period.
   678      * The specified unit must be one of the supported units from {@link ChronoUnit},
   525      * The months and days units are unaffected.
   679      * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an
   526      * For example, "1 year, 6 months and 3 days" plus 2 years returns "3 years, 6 months and 3 days".
   680      * {@linkplain TemporalUnit#isDurationEstimated() exact duration}.
   527      * <p>
   681      * Other units throw an exception.
   528      * This instance is immutable and unaffected by this method call.
   682      * <p>
   529      *
   683      * This instance is immutable and unaffected by this method call.
   530      * @param yearsToAdd  the years to add, positive or negative
   684      *
   531      * @return a {@code Period} based on this period with the specified years added, not null
   685      * @param amount  the amount to add, positive or negative
   532      * @throws ArithmeticException if numeric overflow occurs
   686      * @param unit  the unit that the amount is expressed in, not null
   533      */
   687      * @return a {@code Period} based on this period with the requested amount added, not null
   534     public Period plusYears(long yearsToAdd) {
   688      * @throws ArithmeticException if numeric overflow occurs
   535         if (yearsToAdd == 0) {
   689      */
   536             return this;
   690     public Period plus(long amount, TemporalUnit unit) {
   537         }
   691         Objects.requireNonNull(unit, "unit");
   538         return create(Math.toIntExact(Math.addExact(years, yearsToAdd)), months, days);
   692         if (unit instanceof ChronoUnit) {
   539     }
   693             if (unit == YEARS || unit == MONTHS || unit == DAYS || unit.isDurationEstimated() == false) {
   540 
   694                 if (amount == 0) {
   541     /**
   695                     return this;
   542      * Returns a copy of this period with the specified months added.
   696                 }
   543      * <p>
   697                 switch((ChronoUnit) unit) {
   544      * This adds the amount to the months unit in a copy of this period.
   698                     case NANOS: return plusNanos(amount);
   545      * The years and days units are unaffected.
   699                     case MICROS: return plusNanos(Math.multiplyExact(amount, 1000L));
   546      * For example, "1 year, 6 months and 3 days" plus 2 months returns "1 year, 8 months and 3 days".
   700                     case MILLIS: return plusNanos(Math.multiplyExact(amount, 1000_000L));
   547      * <p>
   701                     case SECONDS: return plusSeconds(amount);
   548      * This instance is immutable and unaffected by this method call.
   702                     case MINUTES: return plusMinutes(amount);
   549      *
   703                     case HOURS: return plusHours(amount);
   550      * @param monthsToAdd  the months to add, positive or negative
   704                     case HALF_DAYS: return plusNanos(Math.multiplyExact(amount, 12 * NANOS_PER_HOUR));
   551      * @return a {@code Period} based on this period with the specified months added, not null
   705                     case DAYS: return plusDays(amount);
   552      * @throws ArithmeticException if numeric overflow occurs
   706                     case MONTHS: return plusMonths(amount);
   553      */
   707                     case YEARS: return plusYears(amount);
   554     public Period plusMonths(long monthsToAdd) {
   708                     default: throw new DateTimeException("Unsupported unit: " + unit.getName());
   555         if (monthsToAdd == 0) {
   709                 }
   556             return this;
   710             }
   557         }
   711         }
   558         return create(years, Math.toIntExact(Math.addExact(months, monthsToAdd)), days);
   712         if (unit.isDurationEstimated()) {
   559     }
   713             throw new DateTimeException("Unsupported unit: " + unit.getName());
   560 
   714         }
   561     /**
   715         return plusNanos(Duration.of(amount, unit).toNanos());
   562      * Returns a copy of this period with the specified days added.
   716     }
   563      * <p>
   717 
   564      * This adds the amount to the days unit in a copy of this period.
   718     public Period plusYears(long amount) {
   565      * The years and months units are unaffected.
   719         return create(Math.toIntExact(Math.addExact(years, amount)), months, days, nanos);
   566      * For example, "1 year, 6 months and 3 days" plus 2 days returns "1 year, 6 months and 5 days".
   720     }
   567      * <p>
   721 
   568      * This instance is immutable and unaffected by this method call.
   722     public Period plusMonths(long amount) {
   569      *
   723         return create(years, Math.toIntExact(Math.addExact(months, amount)), days, nanos);
   570      * @param daysToAdd  the days to add, positive or negative
   724     }
   571      * @return a {@code Period} based on this period with the specified days added, not null
   725 
   572      * @throws ArithmeticException if numeric overflow occurs
   726     public Period plusDays(long amount) {
   573      */
   727         return create(years, months, Math.toIntExact(Math.addExact(days, amount)), nanos);
   574     public Period plusDays(long daysToAdd) {
   728     }
   575         if (daysToAdd == 0) {
   729 
   576             return this;
   730     public Period plusHours(long amount) {
   577         }
   731         return plusNanos(Math.multiplyExact(amount, NANOS_PER_HOUR));
   578         return create(years, months, Math.toIntExact(Math.addExact(days, daysToAdd)));
   732     }
       
   733 
       
   734     public Period plusMinutes(long amount) {
       
   735         return plusNanos(Math.multiplyExact(amount, NANOS_PER_MINUTE));
       
   736     }
       
   737 
       
   738     public Period plusSeconds(long amount) {
       
   739         return plusNanos(Math.multiplyExact(amount, NANOS_PER_SECOND));
       
   740     }
       
   741 
       
   742     public Period plusNanos(long amount) {
       
   743         return create(years, months, days, Math.addExact(nanos,  amount));
       
   744     }
   579     }
   745 
   580 
   746     //-----------------------------------------------------------------------
   581     //-----------------------------------------------------------------------
   747     /**
   582     /**
   748      * Returns a copy of this period with the specified period subtracted.
   583      * Returns a copy of this period with the specified period subtracted.
   749      * <p>
   584      * <p>
   750      * This operates separately on the years, months, days and the normalized time.
   585      * This operates separately on the years, months, days and the normalized time.
   751      * There is no further normalization beyond the normalized time.
   586      * There is no further normalization beyond the normalized time.
   752      * <p>
   587      * <p>
   753      * This instance is immutable and unaffected by this method call.
   588      * For example, "1 year, 6 months and 3 days" minus "2 years, 2 months and 2 days"
   754      *
   589      * returns "-1 years, 4 months and 1 day".
   755      * @param other  the period to subtract, not null
   590      * <p>
       
   591      * This instance is immutable and unaffected by this method call.
       
   592      *
       
   593      * @param amountToSubtract  the period to subtract, not null
   756      * @return a {@code Period} based on this period with the requested period subtracted, not null
   594      * @return a {@code Period} based on this period with the requested period subtracted, not null
   757      * @throws ArithmeticException if numeric overflow occurs
   595      * @throws ArithmeticException if numeric overflow occurs
   758      */
   596      */
   759     public Period minus(Period other) {
   597     public Period minus(Period amountToSubtract) {
   760         return create(
   598         return create(
   761                 Math.subtractExact(years, other.years),
   599                 Math.subtractExact(years, amountToSubtract.years),
   762                 Math.subtractExact(months, other.months),
   600                 Math.subtractExact(months, amountToSubtract.months),
   763                 Math.subtractExact(days, other.days),
   601                 Math.subtractExact(days, amountToSubtract.days));
   764                 Math.subtractExact(nanos, other.nanos));
   602     }
   765     }
   603 
   766 
   604     /**
   767     /**
   605      * Returns a copy of this period with the specified years subtracted.
   768      * Returns a copy of this period with the specified period subtracted.
   606      * <p>
   769      * <p>
   607      * This subtracts the amount from the years unit in a copy of this period.
   770      * The specified unit must be one of the supported units from {@link ChronoUnit},
   608      * The months and days units are unaffected.
   771      * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an
   609      * For example, "1 year, 6 months and 3 days" minus 2 years returns "-1 years, 6 months and 3 days".
   772      * {@linkplain TemporalUnit#isDurationEstimated() exact duration}.
   610      * <p>
   773      * Other units throw an exception.
   611      * This instance is immutable and unaffected by this method call.
   774      * <p>
   612      *
   775      * This instance is immutable and unaffected by this method call.
   613      * @param yearsToSubtract  the years to subtract, positive or negative
   776      *
   614      * @return a {@code Period} based on this period with the specified years subtracted, not null
   777      * @param amount  the amount to subtract, positive or negative
   615      * @throws ArithmeticException if numeric overflow occurs
   778      * @param unit  the unit that the amount is expressed in, not null
   616      */
   779      * @return a {@code Period} based on this period with the requested amount subtracted, not null
   617     public Period minusYears(long yearsToSubtract) {
   780      * @throws ArithmeticException if numeric overflow occurs
   618         return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));
   781      */
   619     }
   782     public Period minus(long amount, TemporalUnit unit) {
   620 
   783         return (amount == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amount, unit));
   621     /**
   784     }
   622      * Returns a copy of this period with the specified months subtracted.
   785 
   623      * <p>
   786     public Period minusYears(long amount) {
   624      * This subtracts the amount from the months unit in a copy of this period.
   787         return (amount == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-amount));
   625      * The years and days units are unaffected.
   788     }
   626      * For example, "1 year, 6 months and 3 days" minus 2 months returns "1 year, 4 months and 3 days".
   789 
   627      * <p>
   790     public Period minusMonths(long amount) {
   628      * This instance is immutable and unaffected by this method call.
   791         return (amount == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-amount));
   629      *
   792     }
   630      * @param monthsToSubtract  the years to subtract, positive or negative
   793 
   631      * @return a {@code Period} based on this period with the specified months subtracted, not null
   794     public Period minusDays(long amount) {
   632      * @throws ArithmeticException if numeric overflow occurs
   795         return (amount == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-amount));
   633      */
   796     }
   634     public Period minusMonths(long monthsToSubtract) {
   797 
   635         return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));
   798     public Period minusHours(long amount) {
   636     }
   799         return (amount == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-amount));
   637 
   800     }
   638     /**
   801 
   639      * Returns a copy of this period with the specified days subtracted.
   802     public Period minusMinutes(long amount) {
   640      * <p>
   803         return (amount == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-amount));
   641      * This subtracts the amount from the days unit in a copy of this period.
   804     }
   642      * The years and months units are unaffected.
   805 
   643      * For example, "1 year, 6 months and 3 days" minus 2 days returns "1 year, 6 months and 1 day".
   806     public Period minusSeconds(long amount) {
   644      * <p>
   807         return (amount == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-amount));
   645      * This instance is immutable and unaffected by this method call.
   808     }
   646      *
   809 
   647      * @param daysToSubtract  the months to subtract, positive or negative
   810     public Period minusNanos(long amount) {
   648      * @return a {@code Period} based on this period with the specified days subtracted, not null
   811         return (amount == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-amount));
   649      * @throws ArithmeticException if numeric overflow occurs
       
   650      */
       
   651     public Period minusDays(long daysToSubtract) {
       
   652         return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
   812     }
   653     }
   813 
   654 
   814     //-----------------------------------------------------------------------
   655     //-----------------------------------------------------------------------
   815     /**
   656     /**
   816      * Returns a new instance with each element in this period multiplied
   657      * Returns a new instance with each element in this period multiplied
   817      * by the specified scalar.
   658      * by the specified scalar.
   818      * <p>
   659      * <p>
   819      * This simply multiplies each field, years, months, days and normalized time,
   660      * This returns a period with each of the years, months and days units
   820      * by the scalar. No normalization is performed.
   661      * individually multiplied.
       
   662      * For example, a period of "2 years, -3 months and 4 days" multiplied by
       
   663      * 3 will return "6 years, -9 months and 12 days".
       
   664      * No normalization is performed.
   821      *
   665      *
   822      * @param scalar  the scalar to multiply by, not null
   666      * @param scalar  the scalar to multiply by, not null
   823      * @return a {@code Period} based on this period with the amounts multiplied by the scalar, not null
   667      * @return a {@code Period} based on this period with the amounts multiplied by the scalar, not null
   824      * @throws ArithmeticException if numeric overflow occurs
   668      * @throws ArithmeticException if numeric overflow occurs
   825      */
   669      */
   828             return this;
   672             return this;
   829         }
   673         }
   830         return create(
   674         return create(
   831                 Math.multiplyExact(years, scalar),
   675                 Math.multiplyExact(years, scalar),
   832                 Math.multiplyExact(months, scalar),
   676                 Math.multiplyExact(months, scalar),
   833                 Math.multiplyExact(days, scalar),
   677                 Math.multiplyExact(days, scalar));
   834                 Math.multiplyExact(nanos, scalar));
       
   835     }
   678     }
   836 
   679 
   837     /**
   680     /**
   838      * Returns a new instance with each amount in this period negated.
   681      * Returns a new instance with each amount in this period negated.
       
   682      * <p>
       
   683      * This returns a period with each of the years, months and days units
       
   684      * individually negated.
       
   685      * For example, a period of "2 years, -3 months and 4 days" will be
       
   686      * negated to "-2 years, 3 months and -4 days".
       
   687      * No normalization is performed.
   839      *
   688      *
   840      * @return a {@code Period} based on this period with the amounts negated, not null
   689      * @return a {@code Period} based on this period with the amounts negated, not null
   841      * @throws ArithmeticException if numeric overflow occurs
   690      * @throws ArithmeticException if numeric overflow occurs, which only happens if
       
   691      *  one of the units has the value {@code Long.MIN_VALUE}
   842      */
   692      */
   843     public Period negated() {
   693     public Period negated() {
   844         return multipliedBy(-1);
   694         return multipliedBy(-1);
   845     }
   695     }
   846 
   696 
   847     //-----------------------------------------------------------------------
   697     //-----------------------------------------------------------------------
   848     /**
   698     /**
   849      * Returns a copy of this period with the days and hours normalized using a 24 hour day.
   699      * Returns a copy of this period with the years and months normalized
   850      * <p>
   700      * using a 12 month year.
   851      * This normalizes the days and hours units, leaving years and months unchanged.
   701      * <p>
   852      * The hours unit is adjusted to have an absolute value less than 23,
   702      * This normalizes the years and months units, leaving the days unit unchanged.
   853      * with the days unit being adjusted to compensate.
       
   854      * For example, a period of {@code P1DT27H} will be normalized to {@code P2DT3H}.
       
   855      * <p>
       
   856      * The sign of the days and hours units will be the same after normalization.
       
   857      * For example, a period of {@code P1DT-51H} will be normalized to {@code P-1DT-3H}.
       
   858      * Since all time units are always normalized, if the hours units changes sign then
       
   859      * other time units will also be affected.
       
   860      * <p>
       
   861      * This instance is immutable and unaffected by this method call.
       
   862      *
       
   863      * @return a {@code Period} based on this period with excess hours normalized to days, not null
       
   864      * @throws ArithmeticException if numeric overflow occurs
       
   865      */
       
   866     public Period normalizedHoursToDays() {
       
   867         // logic uses if statements to normalize signs to avoid unnecessary overflows
       
   868         long totalDays = (nanos / NANOS_PER_DAY) + days;  // no overflow
       
   869         long splitNanos = nanos % NANOS_PER_DAY;
       
   870         if (totalDays > 0 && splitNanos < 0) {
       
   871             splitNanos += NANOS_PER_DAY;
       
   872             totalDays--;
       
   873         } else if (totalDays < 0 && splitNanos > 0) {
       
   874             splitNanos -= NANOS_PER_DAY;
       
   875             totalDays++;
       
   876         }
       
   877         if (totalDays == days && splitNanos == nanos) {
       
   878             return this;
       
   879         }
       
   880         return create(years, months, Math.toIntExact(totalDays), splitNanos);
       
   881     }
       
   882 
       
   883     /**
       
   884      * Returns a copy of this period with any days converted to hours using a 24 hour day.
       
   885      * <p>
       
   886      * The days unit is reduced to zero, with the hours unit increased by 24 times the
       
   887      * days unit to compensate. Other units are unaffected.
       
   888      * For example, a period of {@code P2DT4H} will be normalized to {@code PT52H}.
       
   889      * <p>
       
   890      * This instance is immutable and unaffected by this method call.
       
   891      *
       
   892      * @return a {@code Period} based on this period with days normalized to hours, not null
       
   893      * @throws ArithmeticException if numeric overflow occurs
       
   894      */
       
   895     public Period normalizedDaysToHours() {
       
   896         if (days == 0) {
       
   897             return this;
       
   898         }
       
   899         return create(years, months, 0, Math.addExact(Math.multiplyExact(days, NANOS_PER_DAY), nanos));
       
   900     }
       
   901 
       
   902     /**
       
   903      * Returns a copy of this period with the years and months normalized using a 12 month year.
       
   904      * <p>
       
   905      * This normalizes the years and months units, leaving other units unchanged.
       
   906      * The months unit is adjusted to have an absolute value less than 11,
   703      * The months unit is adjusted to have an absolute value less than 11,
   907      * with the years unit being adjusted to compensate.
   704      * with the years unit being adjusted to compensate. For example, a period of
   908      * For example, a period of {@code P1Y15M} will be normalized to {@code P2Y3M}.
   705      * "1 Year and 15 months" will be normalized to "2 years and 3 months".
   909      * <p>
   706      * <p>
   910      * The sign of the years and months units will be the same after normalization.
   707      * The sign of the years and months units will be the same after normalization.
   911      * For example, a period of {@code P1Y-25M} will be normalized to {@code P-1Y-1M}.
   708      * For example, a period of "1 year and -25 months" will be normalized to
   912      * <p>
   709      * "-1 year and -1 month".
   913      * This normalization uses a 12 month year it is not valid for all calendar systems.
   710      * <p>
   914      * <p>
   711      * This normalization uses a 12 month year which is not valid for all calendar systems.
   915      * This instance is immutable and unaffected by this method call.
   712      * <p>
   916      *
   713      * This instance is immutable and unaffected by this method call.
   917      * @return a {@code Period} based on this period with years and months normalized, not null
   714      *
   918      * @throws ArithmeticException if numeric overflow occurs
   715      * @return a {@code Period} based on this period with excess months normalized to years, not null
   919      */
   716      * @throws ArithmeticException if numeric overflow occurs
   920     public Period normalizedMonthsISO() {
   717      */
   921         long totalMonths = years * 12L + months;  // no overflow
   718     public Period normalized() {
       
   719         long totalMonths = toTotalMonths();
   922         long splitYears = totalMonths / 12;
   720         long splitYears = totalMonths / 12;
   923         int splitMonths = (int) (totalMonths % 12);  // no overflow
   721         int splitMonths = (int) (totalMonths % 12);  // no overflow
   924         if (splitYears == years && splitMonths == months) {
   722         if (splitYears == years && splitMonths == months) {
   925             return this;
   723             return this;
   926         }
   724         }
   927         return create(Math.toIntExact(splitYears), splitMonths, days, nanos);
   725         return create(Math.toIntExact(splitYears), splitMonths, days);
   928     }
   726     }
   929 
   727 
   930     //-------------------------------------------------------------------------
   728     /**
   931     /**
   729      * Gets the total number of months in this period using a 12 month year.
   932      * Converts this period to one that only has date units.
   730      * <p>
   933      * <p>
   731      * This returns the total number of months in the period by multiplying the
   934      * The resulting period will have the same years, months and days as this period
   732      * number of years by 12 and adding the number of months.
   935      * but the time units will all be zero. No normalization occurs in the calculation.
   733      * <p>
   936      * For example, a period of {@code P1Y3MT12H} will be converted to {@code P1Y3M}.
   734      * This uses a 12 month year which is not valid for all calendar systems.
   937      * <p>
   735      * <p>
   938      * This instance is immutable and unaffected by this method call.
   736      * This instance is immutable and unaffected by this method call.
   939      *
   737      *
   940      * @return a {@code Period} based on this period with the time units set to zero, not null
   738      * @return the total number of months in the period, may be negative
   941      */
   739      */
   942     public Period toDateOnly() {
   740     public long toTotalMonths() {
   943         if (nanos == 0) {
   741         return years * 12L + months;  // no overflow
   944             return this;
       
   945         }
       
   946         return create(years, months, days, 0);
       
   947     }
   742     }
   948 
   743 
   949     //-------------------------------------------------------------------------
   744     //-------------------------------------------------------------------------
   950     /**
   745     /**
   951      * Adds this period to the specified temporal object.
   746      * Adds this period to the specified temporal object.
   952      * <p>
   747      * <p>
   953      * This returns a temporal object of the same observable type as the input
   748      * This returns a temporal object of the same observable type as the input
   954      * with this period added.
   749      * with this period added.
   955      * <p>
   750      * <p>
   956      * In most cases, it is clearer to reverse the calling pattern by using
   751      * In most cases, it is clearer to reverse the calling pattern by using
   957      * {@link Temporal#plus(TemporalAdder)}.
   752      * {@link Temporal#plus(TemporalAmount)}.
   958      * <pre>
   753      * <pre>
   959      *   // these two lines are equivalent, but the second approach is recommended
   754      *   // these two lines are equivalent, but the second approach is recommended
   960      *   dateTime = thisPeriod.addTo(dateTime);
   755      *   dateTime = thisPeriod.addTo(dateTime);
   961      *   dateTime = dateTime.plus(thisPeriod);
   756      *   dateTime = dateTime.plus(thisPeriod);
   962      * </pre>
   757      * </pre>
   963      * <p>
   758      * <p>
   964      * The calculation will add the years, then months, then days, then nanos.
   759      * The calculation will add the years, then months, then days.
   965      * Only non-zero amounts will be added.
   760      * Only non-zero amounts will be added.
   966      * If the date-time has a calendar system with a fixed number of months in a
   761      * If the date-time has a calendar system with a fixed number of months in a
   967      * year, then the years and months will be combined before being added.
   762      * year, then the years and months will be combined before being added.
   968      * <p>
   763      * <p>
   969      * This instance is immutable and unaffected by this method call.
   764      * This instance is immutable and unaffected by this method call.
   975      */
   770      */
   976     @Override
   771     @Override
   977     public Temporal addTo(Temporal temporal) {
   772     public Temporal addTo(Temporal temporal) {
   978         Objects.requireNonNull(temporal, "temporal");
   773         Objects.requireNonNull(temporal, "temporal");
   979         if ((years | months) != 0) {
   774         if ((years | months) != 0) {
   980             ValueRange startRange = Chrono.from(temporal).range(MONTH_OF_YEAR);
   775             long monthRange = monthRange(temporal);
   981             if (startRange.isFixed() && startRange.isIntValue()) {
   776             if (monthRange >= 0) {
   982                 long monthCount = startRange.getMaximum() - startRange.getMinimum() + 1;
   777                 temporal = temporal.plus(years * monthRange + months, MONTHS);
   983                 temporal = temporal.plus(years * monthCount + months, MONTHS);
       
   984             } else {
   778             } else {
   985                 if (years != 0) {
   779                 if (years != 0) {
   986                     temporal = temporal.plus(years, YEARS);
   780                     temporal = temporal.plus(years, YEARS);
   987                 }
   781                 }
   988                 if (months != 0) {
   782                 if (months != 0) {
   991             }
   785             }
   992         }
   786         }
   993         if (days != 0) {
   787         if (days != 0) {
   994             temporal = temporal.plus(days, DAYS);
   788             temporal = temporal.plus(days, DAYS);
   995         }
   789         }
   996         if (nanos != 0) {
       
   997             temporal = temporal.plus(nanos, NANOS);
       
   998         }
       
   999         return temporal;
   790         return temporal;
  1000     }
   791     }
  1001 
   792 
  1002     /**
   793     /**
  1003      * Subtracts this period from the specified temporal object.
   794      * Subtracts this period from the specified temporal object.
  1004      * <p>
   795      * <p>
  1005      * This returns a temporal object of the same observable type as the input
   796      * This returns a temporal object of the same observable type as the input
  1006      * with this period subtracted.
   797      * with this period subtracted.
  1007      * <p>
   798      * <p>
  1008      * In most cases, it is clearer to reverse the calling pattern by using
   799      * In most cases, it is clearer to reverse the calling pattern by using
  1009      * {@link Temporal#minus(TemporalSubtractor)}.
   800      * {@link Temporal#minus(TemporalAmount)}.
  1010      * <pre>
   801      * <pre>
  1011      *   // these two lines are equivalent, but the second approach is recommended
   802      *   // these two lines are equivalent, but the second approach is recommended
  1012      *   dateTime = thisPeriod.subtractFrom(dateTime);
   803      *   dateTime = thisPeriod.subtractFrom(dateTime);
  1013      *   dateTime = dateTime.minus(thisPeriod);
   804      *   dateTime = dateTime.minus(thisPeriod);
  1014      * </pre>
   805      * </pre>
  1015      * <p>
   806      * <p>
  1016      * The calculation will subtract the years, then months, then days, then nanos.
   807      * The calculation will subtract the years, then months, then days.
  1017      * Only non-zero amounts will be subtracted.
   808      * Only non-zero amounts will be subtracted.
  1018      * If the date-time has a calendar system with a fixed number of months in a
   809      * If the date-time has a calendar system with a fixed number of months in a
  1019      * year, then the years and months will be combined before being subtracted.
   810      * year, then the years and months will be combined before being subtracted.
  1020      * <p>
   811      * <p>
  1021      * This instance is immutable and unaffected by this method call.
   812      * This instance is immutable and unaffected by this method call.
  1027      */
   818      */
  1028     @Override
   819     @Override
  1029     public Temporal subtractFrom(Temporal temporal) {
   820     public Temporal subtractFrom(Temporal temporal) {
  1030         Objects.requireNonNull(temporal, "temporal");
   821         Objects.requireNonNull(temporal, "temporal");
  1031         if ((years | months) != 0) {
   822         if ((years | months) != 0) {
  1032             ValueRange startRange = Chrono.from(temporal).range(MONTH_OF_YEAR);
   823             long monthRange = monthRange(temporal);
  1033             if (startRange.isFixed() && startRange.isIntValue()) {
   824             if (monthRange >= 0) {
  1034                 long monthCount = startRange.getMaximum() - startRange.getMinimum() + 1;
   825                 temporal = temporal.minus(years * monthRange + months, MONTHS);
  1035                 temporal = temporal.minus(years * monthCount + months, MONTHS);
       
  1036             } else {
   826             } else {
  1037                 if (years != 0) {
   827                 if (years != 0) {
  1038                     temporal = temporal.minus(years, YEARS);
   828                     temporal = temporal.minus(years, YEARS);
  1039                 }
   829                 }
  1040                 if (months != 0) {
   830                 if (months != 0) {
  1043             }
   833             }
  1044         }
   834         }
  1045         if (days != 0) {
   835         if (days != 0) {
  1046             temporal = temporal.minus(days, DAYS);
   836             temporal = temporal.minus(days, DAYS);
  1047         }
   837         }
  1048         if (nanos != 0) {
       
  1049             temporal = temporal.minus(nanos, NANOS);
       
  1050         }
       
  1051         return temporal;
   838         return temporal;
  1052     }
   839     }
  1053 
   840 
  1054     //-----------------------------------------------------------------------
   841     /**
  1055     /**
   842      * Calculates the range of months based on the temporal.
  1056      * Converts this period to one that only has time units.
   843      *
  1057      * <p>
   844      * @param temporal  the temporal, not null
  1058      * The resulting period will have the same time units as this period
   845      * @return the month range, negative if not fixed range
  1059      * but the date units will all be zero. No normalization occurs in the calculation.
   846      */
  1060      * For example, a period of {@code P1Y3MT12H} will be converted to {@code PT12H}.
   847     private long monthRange(Temporal temporal) {
  1061      * <p>
   848         ValueRange startRange = Chronology.from(temporal).range(MONTH_OF_YEAR);
  1062      * This instance is immutable and unaffected by this method call.
   849         if (startRange.isFixed() && startRange.isIntValue()) {
  1063      *
   850             return startRange.getMaximum() - startRange.getMinimum() + 1;
  1064      * @return a {@code Period} based on this period with the date units set to zero, not null
   851         }
  1065      */
   852         return -1;
  1066     public Period toTimeOnly() {
       
  1067         if ((years | months | days) == 0) {
       
  1068             return this;
       
  1069         }
       
  1070         return create(0, 0, 0, nanos);
       
  1071     }
       
  1072 
       
  1073     //-------------------------------------------------------------------------
       
  1074     /**
       
  1075      * Calculates the duration of this period.
       
  1076      * <p>
       
  1077      * The calculation uses the hours, minutes, seconds and nanoseconds fields.
       
  1078      * If years, months or days are present an exception is thrown.
       
  1079      * See {@link #toTimeOnly()} for a way to remove the date units and
       
  1080      * {@link #normalizedDaysToHours()} for a way to convert days to hours.
       
  1081      *
       
  1082      * @return a {@code Duration} equivalent to this period, not null
       
  1083      * @throws DateTimeException if the period cannot be converted as it contains years, months or days
       
  1084      */
       
  1085     public Duration toDuration() {
       
  1086         if ((years | months | days) != 0) {
       
  1087             throw new DateTimeException("Unable to convert period to duration as years/months/days are present: " + this);
       
  1088         }
       
  1089         return Duration.ofNanos(nanos);
       
  1090     }
   853     }
  1091 
   854 
  1092     //-----------------------------------------------------------------------
   855     //-----------------------------------------------------------------------
  1093     /**
   856     /**
  1094      * Checks if this period is equal to another period.
   857      * Checks if this period is equal to another period.
  1095      * <p>
   858      * <p>
  1096      * The comparison is based on the amounts held in the period.
   859      * The comparison is based on the amounts held in the period.
  1097      * To be equal, the years, months, days and normalized time fields must be equal.
   860      * To be equal, the years, months and days units must be individually equal.
       
   861      * Note that this means that a period of "15 Months" is not equal to a period
       
   862      * of "1 Year and 3 Months".
  1098      *
   863      *
  1099      * @param obj  the object to check, null returns false
   864      * @param obj  the object to check, null returns false
  1100      * @return true if this is equal to the other period
   865      * @return true if this is equal to the other period
  1101      */
   866      */
  1102     @Override
   867     @Override
  1104         if (this == obj) {
   869         if (this == obj) {
  1105             return true;
   870             return true;
  1106         }
   871         }
  1107         if (obj instanceof Period) {
   872         if (obj instanceof Period) {
  1108             Period other = (Period) obj;
   873             Period other = (Period) obj;
  1109             return years == other.years && months == other.months &&
   874             return years == other.years &&
  1110                     days == other.days && nanos == other.nanos;
   875                     months == other.months &&
       
   876                     days == other.days;
  1111         }
   877         }
  1112         return false;
   878         return false;
  1113     }
   879     }
  1114 
   880 
  1115     /**
   881     /**
  1117      *
   883      *
  1118      * @return a suitable hash code
   884      * @return a suitable hash code
  1119      */
   885      */
  1120     @Override
   886     @Override
  1121     public int hashCode() {
   887     public int hashCode() {
  1122         // ordered such that overflow from one field doesn't immediately affect the next field
   888         return years + Integer.rotateLeft(months, 8) + Integer.rotateLeft(days, 16);
  1123         return ((years << 27) | (years >>> 5)) ^
   889     }
  1124                 ((days << 21) | (days >>> 11)) ^
   890 
  1125                 ((months << 17) | (months >>> 15)) ^
   891     //-----------------------------------------------------------------------
  1126                 ((int) (nanos ^ (nanos >>> 32)));
   892     /**
  1127     }
   893      * Outputs this period as a {@code String}, such as {@code P6Y3M1D}.
  1128 
       
  1129     //-----------------------------------------------------------------------
       
  1130     /**
       
  1131      * Outputs this period as a {@code String}, such as {@code P6Y3M1DT12H}.
       
  1132      * <p>
   894      * <p>
  1133      * The output will be in the ISO-8601 period format.
   895      * The output will be in the ISO-8601 period format.
       
   896      * A zero period will be represented as zero days, 'P0D'.
  1134      *
   897      *
  1135      * @return a string representation of this period, not null
   898      * @return a string representation of this period, not null
  1136      */
   899      */
  1137     @Override
   900     @Override
  1138     public String toString() {
   901     public String toString() {
  1139         if (this == ZERO) {
   902         if (this == ZERO) {
  1140             return "PT0S";
   903             return "P0D";
  1141         } else {
   904         } else {
  1142             StringBuilder buf = new StringBuilder();
   905             StringBuilder buf = new StringBuilder();
  1143             buf.append('P');
   906             buf.append('P');
  1144             if (years != 0) {
   907             if (years != 0) {
  1145                 buf.append(years).append('Y');
   908                 buf.append(years).append('Y');
  1148                 buf.append(months).append('M');
   911                 buf.append(months).append('M');
  1149             }
   912             }
  1150             if (days != 0) {
   913             if (days != 0) {
  1151                 buf.append(days).append('D');
   914                 buf.append(days).append('D');
  1152             }
   915             }
  1153             if (nanos != 0) {
       
  1154                 buf.append('T');
       
  1155                 if (getHours() != 0) {
       
  1156                     buf.append(getHours()).append('H');
       
  1157                 }
       
  1158                 if (getMinutes() != 0) {
       
  1159                     buf.append(getMinutes()).append('M');
       
  1160                 }
       
  1161                 int secondPart = getSeconds();
       
  1162                 int nanoPart = getNanos();
       
  1163                 int secsNanosOr = secondPart | nanoPart;
       
  1164                 if (secsNanosOr != 0) {  // if either non-zero
       
  1165                     if ((secsNanosOr & Integer.MIN_VALUE) != 0) {  // if either less than zero
       
  1166                         buf.append('-');
       
  1167                         secondPart = Math.abs(secondPart);
       
  1168                         nanoPart = Math.abs(nanoPart);
       
  1169                     }
       
  1170                     buf.append(secondPart);
       
  1171                     if (nanoPart != 0) {
       
  1172                         int dotPos = buf.length();
       
  1173                         nanoPart += 1000_000_000;
       
  1174                         while (nanoPart % 10 == 0) {
       
  1175                             nanoPart /= 10;
       
  1176                         }
       
  1177                         buf.append(nanoPart);
       
  1178                         buf.setCharAt(dotPos, '.');
       
  1179                     }
       
  1180                     buf.append('S');
       
  1181                 }
       
  1182             }
       
  1183             return buf.toString();
   916             return buf.toString();
  1184         }
   917         }
  1185     }
   918     }
  1186 
   919 
       
   920     //-----------------------------------------------------------------------
       
   921     /**
       
   922      * Writes the object using a
       
   923      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
       
   924      * <pre>
       
   925      *  out.writeByte(14);  // identifies this as a Period
       
   926      *  out.writeInt(years);
       
   927      *  out.writeInt(months);
       
   928      *  out.writeInt(seconds);
       
   929      * </pre>
       
   930      *
       
   931      * @return the instance of {@code Ser}, not null
       
   932      */
       
   933     private Object writeReplace() {
       
   934         return new Ser(Ser.PERIOD_TYPE, this);
       
   935     }
       
   936 
       
   937     /**
       
   938      * Defend against malicious streams.
       
   939      * @return never
       
   940      * @throws java.io.InvalidObjectException always
       
   941      */
       
   942     private Object readResolve() throws ObjectStreamException {
       
   943         throw new InvalidObjectException("Deserialization via serialization delegate");
       
   944     }
       
   945 
       
   946     void writeExternal(DataOutput out) throws IOException {
       
   947         out.writeInt(years);
       
   948         out.writeInt(months);
       
   949         out.writeInt(days);
       
   950     }
       
   951 
       
   952     static Period readExternal(DataInput in) throws IOException {
       
   953         int years = in.readInt();
       
   954         int months = in.readInt();
       
   955         int days = in.readInt();
       
   956         return Period.of(years, months, days);
       
   957     }
       
   958 
  1187 }
   959 }