Created
January 31, 2013 17:02
-
-
Save jodastephen/4684361 to your computer and use it in GitHub Desktop.
APPLIED. Patch to ThreeTen for Period/Duration #248
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/share/classes/java/time/Duration.java b/src/share/classes/java/time/Duration.java | |
--- a/src/share/classes/java/time/Duration.java | |
+++ b/src/share/classes/java/time/Duration.java | |
@@ -62,9 +62,13 @@ | |
package java.time; | |
import static java.time.LocalTime.SECONDS_PER_DAY; | |
+import static java.time.LocalTime.SECONDS_PER_HOUR; | |
+import static java.time.LocalTime.SECONDS_PER_MINUTE; | |
import static java.time.temporal.ChronoField.INSTANT_SECONDS; | |
import static java.time.temporal.ChronoField.NANO_OF_SECOND; | |
import static java.time.temporal.ChronoUnit.DAYS; | |
+import static java.time.temporal.ChronoUnit.NANOS; | |
+import static java.time.temporal.ChronoUnit.SECONDS; | |
import java.io.DataInput; | |
import java.io.DataOutput; | |
@@ -76,22 +80,24 @@ | |
import java.math.BigInteger; | |
import java.math.RoundingMode; | |
import java.time.format.DateTimeParseException; | |
-import java.time.temporal.ChronoField; | |
import java.time.temporal.ChronoUnit; | |
import java.time.temporal.Temporal; | |
import java.time.temporal.TemporalAccessor; | |
import java.time.temporal.TemporalAmount; | |
import java.time.temporal.TemporalUnit; | |
-import java.util.ArrayList; | |
+import java.util.Arrays; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.Objects; | |
/** | |
- * A duration between two instants on the time-line. | |
+ * A time-based amount of time, such as '34.5 seconds'. | |
* <p> | |
- * This class models a duration of time and is not tied to any instant. | |
- * The model is of a directed duration, meaning that the duration may be negative. | |
+ * This class models a quantity or amount of time in terms of seconds and nanoseconds. | |
+ * It can be accessed using other duration-based units, such as minutes and hours. | |
+ * In addition, the {@link ChronoUnit#DAYS DAYS} unit can be used and is treated as | |
+ * exactly equal to 24 hours, thus ignoring daylight savings effects. | |
+ * See {@link Period} for the date-based equivalent to this class. | |
* <p> | |
* A physical duration could be of infinite length. | |
* For practicality, the duration is stored with constraints similar to {@link Instant}. | |
@@ -101,6 +107,7 @@ | |
* The range of a duration requires the storage of a number larger than a {@code long}. | |
* To achieve this, the class stores a {@code long} representing seconds and an {@code int} | |
* representing nanosecond-of-second, which will always be between 0 and 999,999,999. | |
+ * The model is of a directed duration, meaning that the duration may be negative. | |
* <p> | |
* The duration is measured in "seconds", but these are not necessarily identical to | |
* the scientific "SI second" definition based on atomic clocks. | |
@@ -145,6 +152,52 @@ | |
//----------------------------------------------------------------------- | |
/** | |
+ * Obtains an instance of {@code Duration} from a number of standard 24 hour days. | |
+ * <p> | |
+ * The seconds are calculated based on the standard definition of a day, | |
+ * where each day is 86400 seconds which implies a 24 hour day. | |
+ * The nanosecond in second field is set to zero. | |
+ * | |
+ * @param days the number of days, positive or negative | |
+ * @return a {@code Duration}, not null | |
+ * @throws ArithmeticException if the input days exceeds the capacity of {@code Duration} | |
+ */ | |
+ public static Duration ofDays(long days) { | |
+ return create(Math.multiplyExact(days, SECONDS_PER_DAY), 0); | |
+ } | |
+ | |
+ /** | |
+ * Obtains an instance of {@code Duration} from a number of standard length hours. | |
+ * <p> | |
+ * The seconds are calculated based on the standard definition of an hour, | |
+ * where each hour is 3600 seconds. | |
+ * The nanosecond in second field is set to zero. | |
+ * | |
+ * @param hours the number of hours, positive or negative | |
+ * @return a {@code Duration}, not null | |
+ * @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration} | |
+ */ | |
+ public static Duration ofHours(long hours) { | |
+ return create(Math.multiplyExact(hours, SECONDS_PER_HOUR), 0); | |
+ } | |
+ | |
+ /** | |
+ * Obtains an instance of {@code Duration} from a number of standard length minutes. | |
+ * <p> | |
+ * The seconds are calculated based on the standard definition of a minute, | |
+ * where each minute is 60 seconds. | |
+ * The nanosecond in second field is set to zero. | |
+ * | |
+ * @param minutes the number of minutes, positive or negative | |
+ * @return a {@code Duration}, not null | |
+ * @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration} | |
+ */ | |
+ public static Duration ofMinutes(long minutes) { | |
+ return create(Math.multiplyExact(minutes, SECONDS_PER_MINUTE), 0); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ /** | |
* Obtains an instance of {@code Duration} from a number of seconds. | |
* <p> | |
* The nanosecond in second field is set to zero. | |
@@ -177,7 +230,7 @@ | |
*/ | |
public static Duration ofSeconds(long seconds, long nanoAdjustment) { | |
long secs = Math.addExact(seconds, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND)); | |
- int nos = (int)Math.floorMod(nanoAdjustment, NANOS_PER_SECOND); | |
+ int nos = (int) Math.floorMod(nanoAdjustment, NANOS_PER_SECOND); | |
return create(secs, nos); | |
} | |
@@ -221,52 +274,6 @@ | |
//----------------------------------------------------------------------- | |
/** | |
- * Obtains an instance of {@code Duration} from a number of standard length minutes. | |
- * <p> | |
- * The seconds are calculated based on the standard definition of a minute, | |
- * where each minute is 60 seconds. | |
- * The nanosecond in second field is set to zero. | |
- * | |
- * @param minutes the number of minutes, positive or negative | |
- * @return a {@code Duration}, not null | |
- * @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration} | |
- */ | |
- public static Duration ofMinutes(long minutes) { | |
- return create(Math.multiplyExact(minutes, 60), 0); | |
- } | |
- | |
- /** | |
- * Obtains an instance of {@code Duration} from a number of standard length hours. | |
- * <p> | |
- * The seconds are calculated based on the standard definition of an hour, | |
- * where each hour is 3600 seconds. | |
- * The nanosecond in second field is set to zero. | |
- * | |
- * @param hours the number of hours, positive or negative | |
- * @return a {@code Duration}, not null | |
- * @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration} | |
- */ | |
- public static Duration ofHours(long hours) { | |
- return create(Math.multiplyExact(hours, 3600), 0); | |
- } | |
- | |
- /** | |
- * Obtains an instance of {@code Duration} from a number of standard 24 hour days. | |
- * <p> | |
- * The seconds are calculated based on the standard definition of a day, | |
- * where each day is 86400 seconds which implies a 24 hour day. | |
- * The nanosecond in second field is set to zero. | |
- * | |
- * @param days the number of days, positive or negative | |
- * @return a {@code Duration}, not null | |
- * @throws ArithmeticException if the input days exceeds the capacity of {@code Duration} | |
- */ | |
- public static Duration ofDays(long days) { | |
- return create(Math.multiplyExact(days, 86400), 0); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- /** | |
* Obtains an instance of {@code Duration} from a duration in the specified unit. | |
* <p> | |
* The parameters represent the two parts of a phrase like '6 Hours'. For example: | |
@@ -290,54 +297,6 @@ | |
//----------------------------------------------------------------------- | |
/** | |
- * Gets the value of the seconds or nanos of Duration. | |
- * @param unit the requested unit either {@code ChronoUnit.SECONDS} or | |
- * {@code ChronoUnit.NANOS}, not null | |
- * @return the value of the requested unit | |
- * @throws DateTimeException if the unit is not {@code ChronoUnit.SECONDS} or | |
- * {@code ChronoUnit.NANOS} | |
- */ | |
- @Override | |
- public long get(TemporalUnit unit) { | |
- if (unit == ChronoUnit.SECONDS) { | |
- return seconds; | |
- } else if (unit == ChronoUnit.NANOS) { | |
- return nanos; | |
- } else { | |
- throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
- } | |
- } | |
- | |
- /** | |
- * Private class to delay initialization of Duration Units until needed. | |
- * The circular dependency between Duration and ChronoUnit prevents | |
- * the simple initialization in Duration. | |
- */ | |
- private static class DurationUnits { | |
- private final static List<TemporalUnit> supportedUnits; | |
- static { | |
- ArrayList<TemporalUnit> tmp = new ArrayList<>(2); | |
- tmp.add(ChronoUnit.SECONDS); | |
- tmp.add(ChronoUnit.NANOS); | |
- supportedUnits = Collections.unmodifiableList(tmp); | |
- } | |
- static List<TemporalUnit> getUnits() { | |
- return supportedUnits; | |
- } | |
- } | |
- | |
- /** | |
- * Gets the set of ChronoUnits supported by {@code Duration}. | |
- * @return the {@code Set<TemporalUnit>} containing {@code ChronoUnit.SECONDS} | |
- * and {@code ChronoUnit.NANOS}. | |
- */ | |
- @Override | |
- public List<TemporalUnit> getUnits() { | |
- return DurationUnits.getUnits(); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- /** | |
* Obtains an instance of {@code Duration} representing the duration between two instants. | |
* <p> | |
* A {@code Duration} represents a directed distance between two points on the time-line. | |
@@ -472,6 +431,56 @@ | |
//----------------------------------------------------------------------- | |
/** | |
+ * Gets the value of the requested unit. | |
+ * <p> | |
+ * This returns a value for each of the two supported units, | |
+ * {@link ChronoUnit#SECONDS SECONDS} and {@link ChronoUnit#NANOS NANOS}. | |
+ * All other units throw an exception. | |
+ * | |
+ * @param unit the {@code TemporalUnit} for which to return the value | |
+ * @return the long value of the unit | |
+ * @throws DateTimeException if the unit is not supported | |
+ */ | |
+ @Override | |
+ public long get(TemporalUnit unit) { | |
+ if (unit == SECONDS) { | |
+ return seconds; | |
+ } else if (unit == NANOS) { | |
+ return nanos; | |
+ } else { | |
+ throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Gets the set of units supported by this duration. | |
+ * <p> | |
+ * The supported units are {@link ChronoUnit#SECONDS SECONDS}, | |
+ * and {@link ChronoUnit#NANOS NANOS}. | |
+ * They are returned in the order seconds, nanos. | |
+ * <p> | |
+ * This set can be used in conjunction with {@link #get(TemporalUnit)} | |
+ * to access the entire state of the period. | |
+ * | |
+ * @return a list containing the seconds and nanos units, not null | |
+ */ | |
+ @Override | |
+ public List<TemporalUnit> getUnits() { | |
+ return DurationUnits.UNITS; | |
+ } | |
+ | |
+ /** | |
+ * Private class to delay initialization of this list until needed. | |
+ * The circular dependency between Duration and ChronoUnit prevents | |
+ * the simple initialization in Duration. | |
+ */ | |
+ private static class DurationUnits { | |
+ final static List<TemporalUnit> UNITS = | |
+ Collections.unmodifiableList(Arrays.<TemporalUnit>asList(SECONDS, NANOS)); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ /** | |
* Checks if this duration is zero length. | |
* <p> | |
* A {@code Duration} represents a directed distance between two points on | |
@@ -485,19 +494,6 @@ | |
} | |
/** | |
- * Checks if this duration is positive, excluding zero. | |
- * <p> | |
- * A {@code Duration} represents a directed distance between two points on | |
- * the time-line and can therefore be positive, zero or negative. | |
- * This method checks whether the length is greater than zero. | |
- * | |
- * @return true if this duration has a total length greater than zero | |
- */ | |
- public boolean isPositive() { | |
- return seconds >= 0 && ((seconds | nanos) != 0); | |
- } | |
- | |
- /** | |
* Checks if this duration is negative, excluding zero. | |
* <p> | |
* A {@code Duration} represents a directed distance between two points on | |
@@ -549,6 +545,39 @@ | |
//----------------------------------------------------------------------- | |
/** | |
+ * Returns a copy of this duration with the specified amount of seconds. | |
+ * <p> | |
+ * This returns a duration with the specified seconds, retaining the | |
+ * nano-of-second part of this duration. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param seconds the seconds to represent, may be negative | |
+ * @return a {@code Duration} based on this period with the requested seconds, not null | |
+ */ | |
+ public Duration withSeconds(long seconds) { | |
+ return create(seconds, nanos); | |
+ } | |
+ | |
+ /** | |
+ * Returns a copy of this duration with the specified nano-of-second. | |
+ * <p> | |
+ * This returns a duration with the specified nano-of-second, retaining the | |
+ * seconds part of this duration. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999 | |
+ * @return a {@code Duration} based on this period with the requested nano-of-second, not null | |
+ * @throws DateTimeException if the nano-of-second is invalid | |
+ */ | |
+ public Duration withNanos(int nanoOfSecond) { | |
+ NANO_OF_SECOND.checkValidIntValue(nanoOfSecond); | |
+ return create(seconds, nanoOfSecond); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ /** | |
* Returns a copy of this duration with the specified duration added. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
@@ -602,6 +631,48 @@ | |
//----------------------------------------------------------------------- | |
/** | |
+ * Returns a copy of this duration with the specified duration in standard 24 hour days added. | |
+ * <p> | |
+ * The number of days is multiplied by 86400 to obtain the number of seconds to add. | |
+ * This is based on the standard definition of a day as 24 hours. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param daysToAdd the days to add, positive or negative | |
+ * @return a {@code Duration} based on this duration with the specified days added, not null | |
+ * @throws ArithmeticException if numeric overflow occurs | |
+ */ | |
+ public Duration plusDays(long daysToAdd) { | |
+ return plus(Math.multiplyExact(daysToAdd, SECONDS_PER_DAY), 0); | |
+ } | |
+ | |
+ /** | |
+ * Returns a copy of this duration with the specified duration in hours added. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param hoursToAdd the hours to add, positive or negative | |
+ * @return a {@code Duration} based on this duration with the specified hours added, not null | |
+ * @throws ArithmeticException if numeric overflow occurs | |
+ */ | |
+ public Duration plusHours(long hoursToAdd) { | |
+ return plus(Math.multiplyExact(hoursToAdd, SECONDS_PER_HOUR), 0); | |
+ } | |
+ | |
+ /** | |
+ * Returns a copy of this duration with the specified duration in minutes added. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param minutesToAdd the minutes to add, positive or negative | |
+ * @return a {@code Duration} based on this duration with the specified minutes added, not null | |
+ * @throws ArithmeticException if numeric overflow occurs | |
+ */ | |
+ public Duration plusMinutes(long minutesToAdd) { | |
+ return plus(Math.multiplyExact(minutesToAdd, SECONDS_PER_MINUTE), 0); | |
+ } | |
+ | |
+ /** | |
* Returns a copy of this duration with the specified duration in seconds added. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
@@ -701,6 +772,52 @@ | |
//----------------------------------------------------------------------- | |
/** | |
+ * Returns a copy of this duration with the specified duration in standard 24 hour days subtracted. | |
+ * <p> | |
+ * The number of days is multiplied by 86400 to obtain the number of seconds to subtract. | |
+ * This is based on the standard definition of a day as 24 hours. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param daysToSubtract the days to subtract, positive or negative | |
+ * @return a {@code Duration} based on this duration with the specified days subtracted, not null | |
+ * @throws ArithmeticException if numeric overflow occurs | |
+ */ | |
+ public Duration minusDays(long daysToSubtract) { | |
+ return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract)); | |
+ } | |
+ | |
+ /** | |
+ * Returns a copy of this duration with the specified duration in hours subtracted. | |
+ * <p> | |
+ * The number of hours is multiplied by 3600 to obtain the number of seconds to subtract. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param hoursToSubtract the hours to subtract, positive or negative | |
+ * @return a {@code Duration} based on this duration with the specified hours subtracted, not null | |
+ * @throws ArithmeticException if numeric overflow occurs | |
+ */ | |
+ public Duration minusHours(long hoursToSubtract) { | |
+ return (hoursToSubtract == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hoursToSubtract)); | |
+ } | |
+ | |
+ /** | |
+ * Returns a copy of this duration with the specified duration in minutes subtracted. | |
+ * <p> | |
+ * The number of hours is multiplied by 60 to obtain the number of seconds to subtract. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @param minutesToSubtract the minutes to subtract, positive or negative | |
+ * @return a {@code Duration} based on this duration with the specified minutes subtracted, not null | |
+ * @throws ArithmeticException if numeric overflow occurs | |
+ */ | |
+ public Duration minusMinutes(long minutesToSubtract) { | |
+ return (minutesToSubtract == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutesToSubtract)); | |
+ } | |
+ | |
+ /** | |
* Returns a copy of this duration with the specified duration in seconds subtracted. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
@@ -766,8 +883,7 @@ | |
* | |
* @param divisor the value to divide the duration by, positive or negative, not zero | |
* @return a {@code Duration} based on this duration divided by the specified divisor, not null | |
- * @throws ArithmeticException if the divisor is zero | |
- * @throws ArithmeticException if numeric overflow occurs | |
+ * @throws ArithmeticException if the divisor is zero or if numeric overflow occurs | |
*/ | |
public Duration dividedBy(long divisor) { | |
if (divisor == 0) { | |
@@ -851,8 +967,8 @@ | |
* dateTime = dateTime.plus(thisDuration); | |
* </pre> | |
* <p> | |
- * A {@code Duration} can only be added to a {@code Temporal} that | |
- * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}. | |
+ * The calculation will add the seconds, then nanos. | |
+ * Only non-zero amounts will be added. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
@@ -863,13 +979,13 @@ | |
*/ | |
@Override | |
public Temporal addTo(Temporal temporal) { | |
- long instantSecs = temporal.getLong(INSTANT_SECONDS); | |
- long instantNanos = temporal.getLong(NANO_OF_SECOND); | |
- instantSecs = Math.addExact(instantSecs, seconds); | |
- instantNanos = Math.addExact(instantNanos, nanos); | |
- instantSecs = Math.addExact(instantSecs, Math.floorDiv(instantNanos, NANOS_PER_SECOND)); | |
- instantNanos = Math.floorMod(instantNanos, NANOS_PER_SECOND); | |
- return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos); | |
+ if (seconds != 0) { | |
+ temporal = temporal.plus(seconds, SECONDS); | |
+ } | |
+ if (nanos != 0) { | |
+ temporal = temporal.plus(nanos, NANOS); | |
+ } | |
+ return temporal; | |
} | |
/** | |
@@ -886,8 +1002,8 @@ | |
* dateTime = dateTime.minus(thisDuration); | |
* </pre> | |
* <p> | |
- * A {@code Duration} can only be subtracted from a {@code Temporal} that | |
- * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}. | |
+ * The calculation will subtract the seconds, then nanos. | |
+ * Only non-zero amounts will be added. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
@@ -898,17 +1014,60 @@ | |
*/ | |
@Override | |
public Temporal subtractFrom(Temporal temporal) { | |
- long instantSecs = temporal.getLong(INSTANT_SECONDS); | |
- long instantNanos = temporal.getLong(NANO_OF_SECOND); | |
- instantSecs = Math.subtractExact(instantSecs, seconds); | |
- instantNanos = Math.subtractExact(instantNanos, nanos); | |
- instantSecs = Math.addExact(instantSecs, Math.floorDiv(instantNanos, NANOS_PER_SECOND)); | |
- instantNanos = Math.floorMod(instantNanos, NANOS_PER_SECOND); | |
- return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos); | |
+ if (seconds != 0) { | |
+ temporal = temporal.minus(seconds, SECONDS); | |
+ } | |
+ if (nanos != 0) { | |
+ temporal = temporal.minus(nanos, NANOS); | |
+ } | |
+ return temporal; | |
} | |
//----------------------------------------------------------------------- | |
/** | |
+ * Gets the number of minutes in this duration. | |
+ * <p> | |
+ * This returns the total number of minutes in the duration by dividing the | |
+ * number of seconds by 86400. | |
+ * This is based on the standard definition of a day as 24 hours. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @return the number of minutes in the duration, may be negative | |
+ */ | |
+ public long toDays() { | |
+ return seconds / SECONDS_PER_DAY; | |
+ } | |
+ | |
+ /** | |
+ * Gets the number of minutes in this duration. | |
+ * <p> | |
+ * This returns the total number of minutes in the duration by dividing the | |
+ * number of seconds by 3600. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @return the number of minutes in the duration, may be negative | |
+ */ | |
+ public long toHours() { | |
+ return seconds / SECONDS_PER_HOUR; | |
+ } | |
+ | |
+ /** | |
+ * Gets the number of minutes in this duration. | |
+ * <p> | |
+ * This returns the total number of minutes in the duration by dividing the | |
+ * number of seconds by 60. | |
+ * <p> | |
+ * This instance is immutable and unaffected by this method call. | |
+ * | |
+ * @return the number of minutes in the duration, may be negative | |
+ */ | |
+ public long toMinutes() { | |
+ return seconds / SECONDS_PER_MINUTE; | |
+ } | |
+ | |
+ /** | |
* Converts this duration to the total length in milliseconds. | |
* <p> | |
* If this duration is too large to fit in a {@code long} milliseconds, then an | |
@@ -961,30 +1120,6 @@ | |
return nanos - otherDuration.nanos; | |
} | |
- /** | |
- * Checks if this duration is greater than the specified {@code Duration}. | |
- * <p> | |
- * The comparison is based on the total length of the durations. | |
- * | |
- * @param otherDuration the other duration to compare to, not null | |
- * @return true if this duration is greater than the specified duration | |
- */ | |
- public boolean isGreaterThan(Duration otherDuration) { | |
- return compareTo(otherDuration) > 0; | |
- } | |
- | |
- /** | |
- * Checks if this duration is less than the specified {@code Duration}. | |
- * <p> | |
- * The comparison is based on the total length of the durations. | |
- * | |
- * @param otherDuration the other duration to compare to, not null | |
- * @return true if this duration is less than the specified duration | |
- */ | |
- public boolean isLessThan(Duration otherDuration) { | |
- return compareTo(otherDuration) < 0; | |
- } | |
- | |
//----------------------------------------------------------------------- | |
/** | |
* Checks if this duration is equal to the specified {@code Duration}. | |
diff --git a/src/share/classes/java/time/Period.java b/src/share/classes/java/time/Period.java | |
--- a/src/share/classes/java/time/Period.java | |
+++ b/src/share/classes/java/time/Period.java | |
@@ -61,70 +61,79 @@ | |
*/ | |
package java.time; | |
-import static java.time.LocalTime.NANOS_PER_DAY; | |
-import static java.time.LocalTime.NANOS_PER_HOUR; | |
-import static java.time.LocalTime.NANOS_PER_MINUTE; | |
-import static java.time.LocalTime.NANOS_PER_SECOND; | |
-import static java.time.temporal.ChronoField.DAY_OF_MONTH; | |
import static java.time.temporal.ChronoField.EPOCH_MONTH; | |
import static java.time.temporal.ChronoField.MONTH_OF_YEAR; | |
-import static java.time.temporal.ChronoField.NANO_OF_DAY; | |
-import static java.time.temporal.ChronoField.YEAR; | |
import static java.time.temporal.ChronoUnit.DAYS; | |
import static java.time.temporal.ChronoUnit.MONTHS; | |
-import static java.time.temporal.ChronoUnit.NANOS; | |
import static java.time.temporal.ChronoUnit.YEARS; | |
+import java.io.DataInput; | |
+import java.io.DataOutput; | |
+import java.io.IOException; | |
+import java.io.InvalidObjectException; | |
+import java.io.ObjectStreamException; | |
import java.io.Serializable; | |
import java.time.chrono.Chronology; | |
import java.time.format.DateTimeParseException; | |
-import java.time.temporal.ChronoField; | |
import java.time.temporal.ChronoUnit; | |
import java.time.temporal.Temporal; | |
-import java.time.temporal.TemporalAccessor; | |
import java.time.temporal.TemporalAmount; | |
import java.time.temporal.TemporalUnit; | |
import java.time.temporal.ValueRange; | |
-import java.util.ArrayList; | |
+import java.util.Arrays; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.Objects; | |
+import java.util.regex.Matcher; | |
+import java.util.regex.Pattern; | |
/** | |
- * A period of time, measured using the most common units, such as '3 Months, 4 Days and 7 Hours'. | |
+ * A date-based amount of time, such as '2 years, 3 months and 4 days'. | |
* <p> | |
- * A {@code Period} represents an amount of time measured in terms of the most commonly used units: | |
- * <p><ul> | |
- * <li>{@link ChronoUnit#YEARS YEARS}</li> | |
- * <li>{@link ChronoUnit#MONTHS MONTHS}</li> | |
- * <li>{@link ChronoUnit#DAYS DAYS}</li> | |
- * <li>time units with an {@linkplain TemporalUnit#isDurationEstimated() exact duration}</li> | |
- * </ul><p> | |
- * The period may be used with any calendar system with the exception of methods with an "ISO" suffix. | |
- * The meaning of a "year" or a "month" is only applied when the object is added to a date. | |
+ * This class models a quantity or amount of time in terms of years, months and days. | |
+ * See {@link Duration} for the time-based equivalent to this class. | |
+ * <p> | |
+ * Durations and period differ in their treatment of daylight savings time | |
+ * when added to {@link ZonedDateTime}. A {@code Duration} will add an exact | |
+ * number of seconds, thus a duration of one day is always exactly 24 hours. | |
+ * By contrast, a {@code Period} will add a conceptual day, trying to maintain | |
+ * the local time. | |
+ * <p> | |
+ * For example, consider adding a period of one day and a duration of one day to | |
+ * 18:00 on the evening before a daylight savings gap. The {@code Period} will add | |
+ * the conceptual day and result in a {@code ZonedDateTime} at 18:00 the following day. | |
+ * By contrast, the {@code Duration} will add exactly 24 hours, resulting in a | |
+ * {@code ZonedDateTime} at 19:00 the following day (assuming a one hour DST gap). | |
+ * <p> | |
+ * The supported units of a period are {@link ChronoUnit#YEARS YEARS}, | |
+ * {@link ChronoUnit#MONTHS MONTHS} and {@link ChronoUnit#DAYS DAYS}. | |
+ * All three fields are always present, but may be set to zero. | |
+ * <p> | |
+ * The period may be used with any calendar system. | |
+ * The meaning of a "year" or "month" is only applied when the object is added to a date. | |
* <p> | |
* The period is modeled as a directed amount of time, meaning that individual parts of the | |
* period may be negative. | |
+ * <p> | |
+ * The months and years fields may be {@linkplain #normalized() normalized}. | |
+ * The normalization assumes a 12 month year, so is not appropriate for all calendar systems. | |
* | |
* <h3>Specification for implementors</h3> | |
* This class is immutable and thread-safe. | |
- * The maximum number of hours that can be stored is about 2.5 million, limited by storing | |
- * a single {@code long} nanoseconds for all time units internally. | |
* | |
* @since 1.8 | |
*/ | |
public final class Period | |
implements TemporalAmount, Serializable { | |
- // maximum hours is 2,562,047 | |
/** | |
* A constant for a period of zero. | |
*/ | |
- public static final Period ZERO = new Period(0, 0, 0, 0); | |
+ public static final Period ZERO = new Period(0, 0, 0); | |
/** | |
* Serialization version. | |
*/ | |
- private static final long serialVersionUID = -8290556941213247973L; | |
+ private static final long serialVersionUID = -3587258372562876L; | |
/** | |
* The number of years. | |
@@ -138,321 +147,158 @@ | |
* The number of days. | |
*/ | |
private final int days; | |
- /** | |
- * The number of nanoseconds. | |
- */ | |
- private final long nanos; | |
/** | |
- * The static final set of ChronoUnits supported by Period. | |
+ * The pattern for parsing. | |
*/ | |
- private final static List<TemporalUnit> SUPPORTED_UNITS; | |
- | |
- static { | |
- ArrayList<TemporalUnit> tmp = new ArrayList<>(7); | |
- tmp.add(ChronoUnit.YEARS); | |
- tmp.add(ChronoUnit.MONTHS); | |
- tmp.add(ChronoUnit.DAYS); | |
- tmp.add(ChronoUnit.HOURS); | |
- tmp.add(ChronoUnit.MINUTES); | |
- tmp.add(ChronoUnit.SECONDS); | |
- tmp.add(ChronoUnit.NANOS); | |
- SUPPORTED_UNITS = Collections.unmodifiableList(tmp); | |
- } | |
+ private final static Pattern PATTERN = | |
+ Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)Y)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)D)?", Pattern.CASE_INSENSITIVE); | |
+ /** | |
+ * The set of supported units. | |
+ */ | |
+ private final static List<TemporalUnit> SUPPORTED_UNITS = | |
+ Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS)); | |
//----------------------------------------------------------------------- | |
/** | |
* Obtains an instance of {@code Period} from a number of years. | |
* <p> | |
* The resulting period will have the specified years. | |
- * The months, days and time fields will be zero. | |
+ * The months and days units will be zero. | |
* | |
* @param years the number of years, positive or negative | |
- * @return a {@code Period}, not null | |
+ * @return the period of years, not null | |
*/ | |
public static Period ofYears(int years) { | |
- return create(years, 0, 0, 0); | |
+ return create(years, 0, 0); | |
} | |
/** | |
* Obtains an instance of {@code Period} from a number of months. | |
* <p> | |
* The resulting period will have the specified months. | |
- * The years, days and time fields will be zero. | |
+ * The years and days units will be zero. | |
* | |
* @param months the number of months, positive or negative | |
- * @return a {@code Period}, not null | |
+ * @return the period of months, not null | |
*/ | |
public static Period ofMonths(int months) { | |
- return create(0, months, 0, 0); | |
+ return create(0, months, 0); | |
} | |
/** | |
* Obtains an instance of {@code Period} from a number of days. | |
* <p> | |
* The resulting period will have the specified days. | |
- * The years, months and time fields will be zero. | |
+ * The years and months units will be zero. | |
* | |
* @param days the number of days, positive or negative | |
- * @return a {@code Period}, not null | |
+ * @return the period of days, not null | |
*/ | |
public static Period ofDays(int days) { | |
- return create(0, 0, days, 0); | |
- } | |
- | |
- /** | |
- * Obtains an instance of {@code Period} from a number of hours. | |
- * <p> | |
- * The resulting period will have the specified hours. | |
- * The years, months and days fields will be zero. | |
- * <p> | |
- * Within a period, the time fields are always normalized, thus | |
- * the hours are held in the time field measured in nanoseconds | |
- * | |
- * @param hours the number of hours, positive or negative | |
- * @return a {@code Period}, not null | |
- * @throws ArithmeticException if a numeric overflow occurs | |
- */ | |
- public static Period ofHours(int hours) { | |
- return ofTime(hours, 0, 0, 0); | |
- } | |
- | |
- /** | |
- * Obtains an instance of {@code Period} from a number of minutes. | |
- * <p> | |
- * The resulting period will have the specified minutes. | |
- * The years, months and days fields will be zero. | |
- * <p> | |
- * Within a period, the time fields are always normalized, thus | |
- * the minutes are held in the time field measured in nanoseconds | |
- * | |
- * @param minutes the number of minutes, positive or negative | |
- * @return a {@code Period}, not null | |
- * @throws ArithmeticException if a numeric overflow occurs | |
- */ | |
- public static Period ofMinutes(int minutes) { | |
- return ofTime(0, minutes, 0, 0); | |
- } | |
- | |
- /** | |
- * Obtains an instance of {@code Period} from a number of seconds. | |
- * <p> | |
- * The resulting period will have the specified seconds. | |
- * The years, months and days fields will be zero. | |
- * <p> | |
- * Within a period, the time fields are always normalized, thus | |
- * the seconds are held in the time field measured in nanoseconds | |
- * | |
- * @param seconds the number of seconds, positive or negative | |
- * @return a {@code Period}, not null | |
- */ | |
- public static Period ofSeconds(int seconds) { | |
- return ofTime(0, 0, seconds, 0); | |
+ return create(0, 0, days); | |
} | |
//----------------------------------------------------------------------- | |
/** | |
- * Obtains a {@code Period} from date-based and time-based fields. | |
- * <p> | |
- * This creates an instance based on years, months, days, hours, minutes, seconds and nanoseconds. | |
- * Within a period, the time fields are always normalized. | |
- * | |
- * @param years the amount of years, may be negative | |
- * @param months the amount of months, may be negative | |
- * @param days the amount of days, may be negative | |
- * @param hours the amount of hours, may be negative | |
- * @param minutes the amount of minutes, may be negative | |
- * @param seconds the amount of seconds, may be negative | |
- * @param nanos the amount of nanos, may be negative | |
- * @return the period, not null | |
- */ | |
- public static Period of(int years, int months, int days, int hours, int minutes, int seconds, long nanos) { | |
- if ((years | months | days | hours | minutes | seconds | nanos) == 0) { | |
- return ZERO; | |
- } | |
- long totSecs = Math.addExact(hours * 3600L, minutes * 60L) + seconds; | |
- long totNanos = Math.addExact(Math.multiplyExact(totSecs, 1_000_000_000L), nanos); | |
- return create(years, months, days, totNanos); | |
- } | |
- | |
- /** | |
- * Obtains a {@code Period} from date-based fields. | |
+ * Obtains a {@code Period} from the years, months and days units. | |
* <p> | |
* This creates an instance based on years, months and days. | |
* | |
* @param years the amount of years, may be negative | |
* @param months the amount of months, may be negative | |
* @param days the amount of days, may be negative | |
- * @return the period, not null | |
+ * @return the period of years, months and days, not null | |
*/ | |
- public static Period ofDate(int years, int months, int days) { | |
- return of(years, months, days, 0, 0, 0, 0); | |
+ public static Period of(int years, int months, int days) { | |
+ return create(years, months, days); | |
} | |
- /** | |
- * Obtains a {@code Period} from time-based fields. | |
- * <p> | |
- * This creates an instance based on hours, minutes, seconds and nanoseconds. | |
- * Within a period, the time fields are always normalized. | |
- * | |
- * @param hours the amount of hours, may be negative | |
- * @param minutes the amount of minutes, may be negative | |
- * @param seconds the amount of seconds, may be negative | |
- * @param nanos the amount of nanos, may be negative | |
- * @return the period, not null | |
- * @throws ArithmeticException if a numeric overflow occurs | |
- */ | |
- public static Period ofTime(int hours, int minutes, int seconds, long nanos) { | |
- return of(0, 0, 0, hours, minutes, seconds, nanos); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- /** | |
- * Obtains an instance of {@code Period} from a period in the specified unit. | |
- * <p> | |
- * The parameters represent the two parts of a phrase like '6 Days'. For example: | |
- * <pre> | |
- * Period.of(3, SECONDS); | |
- * Period.of(5, YEARS); | |
- * </pre> | |
- * The specified unit must be one of the supported units from {@link ChronoUnit}, | |
- * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an | |
- * {@linkplain TemporalUnit#isDurationEstimated() exact duration}. | |
- * Other units throw an exception. | |
- * | |
- * @param amount the amount of the period, measured in terms of the unit, positive or negative | |
- * @param unit the unit that the period is measured in, must have an exact duration, not null | |
- * @return the period, not null | |
- * @throws DateTimeException if the period unit is invalid | |
- * @throws ArithmeticException if a numeric overflow occurs | |
- */ | |
- public static Period of(long amount, TemporalUnit unit) { | |
- return ZERO.plus(amount, unit); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- /** | |
- * Obtains a {@code Period} from a {@code Duration}. | |
- * <p> | |
- * This converts the duration to a period. | |
- * Within a period, the time fields are always normalized. | |
- * The years, months and days fields will be zero. | |
- * <p> | |
- * To populate the days field, call {@link #normalizedHoursToDays()} on the created period. | |
- * | |
- * @param duration the duration to convert, not null | |
- * @return the period, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public static Period of(Duration duration) { | |
- Objects.requireNonNull(duration, "duration"); | |
- if (duration.isZero()) { | |
- return ZERO; | |
- } | |
- return new Period(0, 0, 0, duration.toNanos()); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- @Override | |
- public long get(TemporalUnit unit) { | |
- if (unit == ChronoUnit.YEARS) { | |
- return getYears(); | |
- } else if (unit == ChronoUnit.MONTHS) { | |
- return getMonths(); | |
- } else if (unit == ChronoUnit.DAYS) { | |
- return getDays(); | |
- } else if (unit == ChronoUnit.HOURS) { | |
- return getHours(); | |
- } else if (unit == ChronoUnit.MINUTES) { | |
- return getMinutes(); | |
- } else if (unit == ChronoUnit.SECONDS) { | |
- return getSeconds(); | |
- } else if (unit == ChronoUnit.NANOS) { | |
- return getNanos(); | |
- } else { | |
- throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
- } | |
- } | |
- | |
- /** | |
- * Gets the set of ChronoUnits supported by {@code Period}. | |
- * @return a {@code List<TemporalUnit>} containing | |
- * {@link java.time.temporal.ChronoUnit#YEARS YEARS}, | |
- * {@link java.time.temporal.ChronoUnit#MONTHS MONTHS}, | |
- * {@link java.time.temporal.ChronoUnit#DAYS DAYS}, | |
- * {@link java.time.temporal.ChronoUnit#HOURS HOURS}, | |
- * {@link java.time.temporal.ChronoUnit#MINUTES MINUTES}, | |
- * {@link java.time.temporal.ChronoUnit#SECONDS SECONDS} | |
- * and {@link java.time.temporal.ChronoUnit#NANOS NANOS}. | |
- */ | |
- @Override | |
- public List<TemporalUnit> getUnits() { | |
- return SUPPORTED_UNITS; | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- /** | |
- * Returns a {@code Period} consisting of the number of years, months, days, | |
- * hours, minutes, seconds, and nanoseconds between two {@code TemporalAccessor} instances. | |
- * <p> | |
- * The start date is included, but the end date is not. Only whole years count. | |
- * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days. | |
- * <p> | |
- * This method examines the {@link ChronoField fields} {@code YEAR}, {@code MONTH_OF_YEAR}, | |
- * {@code DAY_OF_MONTH} and {@code NANO_OF_DAY} | |
- * The difference between each of the fields is calculated independently from the others. | |
- * At least one of the four fields must be present. | |
- * <p> | |
- * The four units are typically retained without normalization. | |
- * However, years and months are normalized if the range of months is fixed, as it is with ISO. | |
- * <p> | |
- * The result of this method can be a negative period if the end is before the start. | |
- * The negative sign can be different in each of the four major units. | |
- * | |
- * @param start the start date, inclusive, not null | |
- * @param end the end date, exclusive, not null | |
- * @return the period between the date-times, not null | |
- * @throws DateTimeException if the two date-times do have similar available fields | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public static Period between(TemporalAccessor start, TemporalAccessor end) { | |
- if (Chronology.from(start).equals(Chronology.from(end)) == false) { | |
- throw new DateTimeException("Unable to calculate period as date-times have different chronologies"); | |
- } | |
- int years = 0; | |
- int months = 0; | |
- int days = 0; | |
- long nanos = 0; | |
- boolean valid = false; | |
- if (start.isSupported(YEAR)) { | |
- years = Math.toIntExact(Math.subtractExact(end.getLong(YEAR), start.getLong(YEAR))); | |
- valid = true; | |
- } | |
- if (start.isSupported(MONTH_OF_YEAR)) { | |
- months = Math.toIntExact(Math.subtractExact(end.getLong(MONTH_OF_YEAR), start.getLong(MONTH_OF_YEAR))); | |
- ValueRange startRange = Chronology.from(start).range(MONTH_OF_YEAR); | |
- ValueRange endRange = Chronology.from(end).range(MONTH_OF_YEAR); | |
- if (startRange.isFixed() && startRange.isIntValue() && startRange.equals(endRange)) { | |
- int monthCount = (int) (startRange.getMaximum() - startRange.getMinimum() + 1); | |
- long totMonths = ((long) months) + years * monthCount; | |
- months = (int) (totMonths % monthCount); | |
- years = Math.toIntExact(totMonths / monthCount); | |
- } | |
- valid = true; | |
- } | |
- if (start.isSupported(DAY_OF_MONTH)) { | |
- days = Math.toIntExact(Math.subtractExact(end.getLong(DAY_OF_MONTH), start.getLong(DAY_OF_MONTH))); | |
- valid = true; | |
- } | |
- if (start.isSupported(NANO_OF_DAY)) { | |
- nanos = Math.subtractExact(end.getLong(NANO_OF_DAY), start.getLong(NANO_OF_DAY)); | |
- valid = true; | |
- } | |
- if (valid == false) { | |
- throw new DateTimeException("Unable to calculate period as date-times do not have any valid fields"); | |
- } | |
- return create(years, months, days, nanos); | |
- } | |
+// //----------------------------------------------------------------------- | |
+// /** | |
+// * Obtains an instance of {@code Period} from a period in the specified unit. | |
+// * <p> | |
+// * The parameters represent the two parts of a phrase like '6 Days'. For example: | |
+// * <pre> | |
+// * Period.of(3, DAYS); | |
+// * Period.of(5, YEARS); | |
+// * </pre> | |
+// * The specified unit must be one of the supported units from {@link ChronoUnit} - | |
+// * {@code YEARS}, {@code MONTHS} or {@code DAYS}. | |
+// * | |
+// * @param amount the amount of the period, measured in terms of the unit, positive or negative | |
+// * @param unit the unit that the period is measured in, must have an exact duration, not null | |
+// * @return the period, not null | |
+// * @throws DateTimeException if the period unit is invalid | |
+// * @throws ArithmeticException if a numeric overflow occurs | |
+// */ | |
+// public static Period of(long amount, TemporalUnit unit) { | |
+// return ZERO.plus(amount, unit); | |
+// } | |
+// | |
+// //----------------------------------------------------------------------- | |
+// /** | |
+// * Returns a {@code Period} consisting of the number of years, months, days, | |
+// * hours, minutes, seconds, and nanoseconds between two {@code TemporalAccessor} instances. | |
+// * <p> | |
+// * The start date is included, but the end date is not. Only whole years count. | |
+// * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days. | |
+// * <p> | |
+// * This method examines the {@link ChronoField fields} {@code YEAR}, {@code MONTH_OF_YEAR}, | |
+// * {@code DAY_OF_MONTH} and {@code NANO_OF_DAY} | |
+// * The difference between each of the fields is calculated independently from the others. | |
+// * At least one of the four fields must be present. | |
+// * <p> | |
+// * The four units are typically retained without normalization. | |
+// * However, years and months are normalized if the range of months is fixed, as it is with ISO. | |
+// * <p> | |
+// * The result of this method can be a negative period if the end is before the start. | |
+// * The negative sign can be different in each of the four major units. | |
+// * | |
+// * @param start the start date, inclusive, not null | |
+// * @param end the end date, exclusive, not null | |
+// * @return the period between the date-times, not null | |
+// * @throws DateTimeException if the two date-times do have similar available fields | |
+// * @throws ArithmeticException if numeric overflow occurs | |
+// */ | |
+// public static Period between(TemporalAccessor start, TemporalAccessor end) { | |
+// if (Chronology.from(start).equals(Chronology.from(end)) == false) { | |
+// throw new DateTimeException("Unable to calculate period as date-times have different chronologies"); | |
+// } | |
+// int years = 0; | |
+// int months = 0; | |
+// int days = 0; | |
+// long nanos = 0; | |
+// boolean valid = false; | |
+// if (start.isSupported(YEAR)) { | |
+// years = Math.toIntExact(Math.subtractExact(end.getLong(YEAR), start.getLong(YEAR))); | |
+// valid = true; | |
+// } | |
+// if (start.isSupported(MONTH_OF_YEAR)) { | |
+// months = Math.toIntExact(Math.subtractExact(end.getLong(MONTH_OF_YEAR), start.getLong(MONTH_OF_YEAR))); | |
+// ValueRange startRange = Chronology.from(start).range(MONTH_OF_YEAR); | |
+// ValueRange endRange = Chronology.from(end).range(MONTH_OF_YEAR); | |
+// if (startRange.isFixed() && startRange.isIntValue() && startRange.equals(endRange)) { | |
+// int monthCount = (int) (startRange.getMaximum() - startRange.getMinimum() + 1); | |
+// long totMonths = ((long) months) + years * monthCount; | |
+// months = (int) (totMonths % monthCount); | |
+// years = Math.toIntExact(totMonths / monthCount); | |
+// } | |
+// valid = true; | |
+// } | |
+// if (start.isSupported(DAY_OF_MONTH)) { | |
+// days = Math.toIntExact(Math.subtractExact(end.getLong(DAY_OF_MONTH), start.getLong(DAY_OF_MONTH))); | |
+// valid = true; | |
+// } | |
+// if (start.isSupported(NANO_OF_DAY)) { | |
+// nanos = Math.subtractExact(end.getLong(NANO_OF_DAY), start.getLong(NANO_OF_DAY)); | |
+// valid = true; | |
+// } | |
+// if (valid == false) { | |
+// throw new DateTimeException("Unable to calculate period as date-times do not have any valid fields"); | |
+// } | |
+// return create(years, months, days, nanos); | |
+// } | |
//----------------------------------------------------------------------- | |
/** | |
@@ -474,7 +320,7 @@ | |
* @return the period between the dates, not null | |
* @throws ArithmeticException if numeric overflow occurs | |
*/ | |
- public static Period betweenIso(LocalDate startDate, LocalDate endDate) { | |
+ public static Period between(LocalDate startDate, LocalDate endDate) { | |
long startMonth = startDate.getLong(EPOCH_MONTH); | |
long endMonth = endDate.getLong(EPOCH_MONTH); | |
long totalMonths = endMonth - startMonth; // safe | |
@@ -489,56 +335,63 @@ | |
} | |
long years = totalMonths / 12; // safe | |
int months = (int) (totalMonths % 12); // safe | |
- return ofDate(Math.toIntExact(years), months, days); | |
+ return create(Math.toIntExact(years), months, days); | |
} | |
//----------------------------------------------------------------------- | |
/** | |
- * Obtains a {@code Period} consisting of the number of hours, minutes, | |
- * seconds and nanoseconds between two times. | |
- * <p> | |
- * The start time is included, but the end time is not. | |
- * The period is calculated from the difference between the nano-of-day values | |
- * of the two times. For example, from {@code 13:45:00} to {@code 14:50:30.123456789} | |
- * is {@code P1H5M30.123456789S}. | |
- * <p> | |
- * The result of this method can be a negative period if the end is before the start. | |
- * | |
- * @param startTime the start time, inclusive, not null | |
- * @param endTime the end time, exclusive, not null | |
- * @return the period between the times, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public static Period betweenIso(LocalTime startTime, LocalTime endTime) { | |
- return create(0, 0, 0, endTime.toNanoOfDay() - startTime.toNanoOfDay()); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- /** | |
- * Obtains a {@code Period} from a text string such as {@code PnYnMnDTnHnMn.nS}. | |
+ * Obtains a {@code Period} from a text string such as {@code PnYnMnD}. | |
* <p> | |
* This will parse the string produced by {@code toString()} which is | |
- * a subset of the ISO-8601 period format {@code PnYnMnDTnHnMn.nS}. | |
+ * based on the ISO-8601 period format {@code PnYnMnD}. | |
* <p> | |
- * The string consists of a series of numbers with a suffix identifying their meaning. | |
- * The values, and suffixes, must be in the sequence year, month, day, hour, minute, second. | |
- * Any of the number/suffix pairs may be omitted providing at least one is present. | |
- * If the period is zero, the value is normally represented as {@code PT0S}. | |
- * The numbers must consist of ASCII digits. | |
- * Any of the numbers may be negative. Negative zero is not accepted. | |
- * The number of nanoseconds is expressed as an optional fraction of the seconds. | |
- * There must be at least one digit before any decimal point. | |
- * There must be between 1 and 9 inclusive digits after any decimal point. | |
- * The letters will all be accepted in upper or lower case. | |
- * The decimal point may be either a dot or a comma. | |
+ * The string starts with an optional sign, denoted by the ASCII negative | |
+ * or positive symbol. If negative, the whole period is negated. | |
+ * The ASCII letter "P" is next in upper or lower case. | |
+ * There are then three sections, each consisting of a number and a suffix. | |
+ * At least one of the three sections must be present. | |
+ * The sections have suffixes in ASCII of "Y", "M" and "D" for | |
+ * years, months and days, accepted in upper or lower case. | |
+ * The suffixes must occur in order. | |
+ * The number part of each section must consist of ASCII digits. | |
+ * The number may be prefixed by the ASCII negative or positive symbol. | |
+ * The number must parse to an {@ocde int}. | |
* | |
* @param text the text to parse, not null | |
* @return the parsed period, not null | |
* @throws DateTimeParseException if the text cannot be parsed to a period | |
*/ | |
- public static Period parse(final CharSequence text) { | |
+ public static Period parse(CharSequence text) { | |
Objects.requireNonNull(text, "text"); | |
- return new PeriodParser(text).parse(); | |
+ Matcher matcher = PATTERN.matcher(text); | |
+ if (matcher.matches()) { | |
+ int negate = ("-".equals(matcher.group(1)) ? -1 : 1); | |
+ String yearMatch = matcher.group(2); | |
+ String monthMatch = matcher.group(3); | |
+ String dayMatch = matcher.group(4); | |
+ if (yearMatch != null || monthMatch != null || dayMatch != null) { | |
+ try { | |
+ return create(parseNumber(text, yearMatch, negate), | |
+ parseNumber(text, monthMatch, negate), | |
+ parseNumber(text, dayMatch, negate)); | |
+ } catch (NumberFormatException ex) { | |
+ throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Period", text, 0).initCause(ex); | |
+ } | |
+ } | |
+ } | |
+ throw new DateTimeParseException("Text cannot be parsed to a Period", text, 0); | |
+ } | |
+ | |
+ private static int parseNumber(CharSequence text, String str, int negate) { | |
+ if (str == null) { | |
+ return 0; | |
+ } | |
+ int val = Integer.parseInt(str); | |
+ try { | |
+ return Math.multiplyExact(val, negate); | |
+ } catch (ArithmeticException ex) { | |
+ throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Period", text, 0).initCause(ex); | |
+ } | |
} | |
//----------------------------------------------------------------------- | |
@@ -548,13 +401,12 @@ | |
* @param years the amount | |
* @param months the amount | |
* @param days the amount | |
- * @param nanos the amount | |
*/ | |
- private static Period create(int years, int months, int days, long nanos) { | |
- if ((years | months | days | nanos) == 0) { | |
+ private static Period create(int years, int months, int days) { | |
+ if ((years | months | days) == 0) { | |
return ZERO; | |
} | |
- return new Period(years, months, days, nanos); | |
+ return new Period(years, months, days); | |
} | |
/** | |
@@ -563,30 +415,61 @@ | |
* @param years the amount | |
* @param months the amount | |
* @param days the amount | |
- * @param nanos the amount | |
*/ | |
- private Period(int years, int months, int days, long nanos) { | |
+ private Period(int years, int months, int days) { | |
this.years = years; | |
this.months = months; | |
this.days = days; | |
- this.nanos = nanos; | |
- } | |
- | |
- /** | |
- * Resolves singletons. | |
- * | |
- * @return the resolved instance | |
- */ | |
- private Object readResolve() { | |
- if ((years | months | days | nanos) == 0) { | |
- return ZERO; | |
- } | |
- return this; | |
} | |
//----------------------------------------------------------------------- | |
/** | |
- * Checks if this period is zero-length. | |
+ * Gets the value of the requested unit. | |
+ * <p> | |
+ * This returns a value for each of the three supported units, | |
+ * {@link ChronoUnit#YEARS YEARS}, {@link ChronoUnit#MONTHS MONTHS} and | |
+ * {@link ChronoUnit#DAYS DAYS}. | |
+ * All other units throw an exception. | |
+ * | |
+ * @param unit the {@code TemporalUnit} for which to return the value | |
+ * @return the long value of the unit | |
+ * @throws DateTimeException if the unit is not supported | |
+ */ | |
+ @Override | |
+ public long get(TemporalUnit unit) { | |
+ if (unit == ChronoUnit.YEARS) { | |
+ return getYears(); | |
+ } else if (unit == ChronoUnit.MONTHS) { | |
+ return getMonths(); | |
+ } else if (unit == ChronoUnit.DAYS) { | |
+ return getDays(); | |
+ } else { | |
+ throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Gets the set of units supported by this period. | |
+ * <p> | |
+ * The supported units are {@link ChronoUnit#YEARS YEARS}, | |
+ * {@link ChronoUnit#MONTHS MONTHS} and {@link ChronoUnit#DAYS DAYS}. | |
+ * They are returned in the order years, months, days. | |
+ * <p> | |
+ * This set can be used in conjunction with {@link #get(TemporalUnit)} | |
+ * to access the entire state of the period. | |
+ * | |
+ * @return a list containing the years, months and days units, not null | |
+ */ | |
+ @Override | |
+ public List<TemporalUnit> getUnits() { | |
+ return SUPPORTED_UNITS; | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ /** | |
+ * Checks if all three units of this period are zero. | |
+ * <p> | |
+ * A zero period has the value zero for the years, months and days units. | |
* | |
* @return true if this period is zero-length | |
*/ | |
@@ -595,22 +478,27 @@ | |
} | |
/** | |
- * Checks if this period is fully positive, excluding zero. | |
+ * Checks if any of the three units of this period are negative. | |
* <p> | |
- * This checks whether all the amounts in the period are positive, | |
- * defined as greater than zero. | |
+ * This checks whether the years, months or days units are less than zero. | |
* | |
- * @return true if this period is fully positive excluding zero | |
+ * @return true if any unit of this period is negative | |
*/ | |
- public boolean isPositive() { | |
- return ((years | months | days | nanos) > 0); | |
+ public boolean isNegative() { | |
+ return years < 0 || months < 0 || days < 0; | |
} | |
//----------------------------------------------------------------------- | |
/** | |
* Gets the amount of years of this period. | |
+ * <p> | |
+ * This returns the years unit. | |
+ * <p> | |
+ * The months unit is not normalized with the years unit. | |
+ * This means that a period of "15 months" is different to a period | |
+ * of "1 year and 3 months". | |
* | |
- * @return the amount of years of this period | |
+ * @return the amount of years of this period, may be negative | |
*/ | |
public int getYears() { | |
return years; | |
@@ -618,8 +506,14 @@ | |
/** | |
* Gets the amount of months of this period. | |
+ * <p> | |
+ * This returns the months unit. | |
+ * <p> | |
+ * The months unit is not normalized with the years unit. | |
+ * This means that a period of "15 months" is different to a period | |
+ * of "1 year and 3 months". | |
* | |
- * @return the amount of months of this period | |
+ * @return the amount of months of this period, may be negative | |
*/ | |
public int getMonths() { | |
return months; | |
@@ -627,158 +521,76 @@ | |
/** | |
* Gets the amount of days of this period. | |
+ * <p> | |
+ * This returns the days unit. | |
* | |
- * @return the amount of days of this period | |
+ * @return the amount of days of this period, may be negative | |
*/ | |
public int getDays() { | |
return days; | |
} | |
- /** | |
- * Gets the amount of hours of this period. | |
- * <p> | |
- * Within a period, the time fields are always normalized. | |
- * | |
- * @return the amount of hours of this period | |
- */ | |
- public int getHours() { | |
- return (int) (nanos / NANOS_PER_HOUR); | |
- } | |
- | |
- /** | |
- * Gets the amount of minutes within an hour of this period. | |
- * <p> | |
- * Within a period, the time fields are always normalized. | |
- * | |
- * @return the amount of minutes within an hour of this period | |
- */ | |
- public int getMinutes() { | |
- return (int) ((nanos / NANOS_PER_MINUTE) % 60); | |
- } | |
- | |
- /** | |
- * Gets the amount of seconds within a minute of this period. | |
- * <p> | |
- * Within a period, the time fields are always normalized. | |
- * | |
- * @return the amount of seconds within a minute of this period | |
- */ | |
- public int getSeconds() { | |
- return (int) ((nanos / NANOS_PER_SECOND) % 60); | |
- } | |
- | |
- /** | |
- * Gets the amount of nanoseconds within a second of this period. | |
- * <p> | |
- * Within a period, the time fields are always normalized. | |
- * | |
- * @return the amount of nanoseconds within a second of this period | |
- */ | |
- public int getNanos() { | |
- return (int) (nanos % NANOS_PER_SECOND); // safe from overflow | |
- } | |
- | |
- /** | |
- * Gets the total amount of the time units of this period, measured in nanoseconds. | |
- * <p> | |
- * Within a period, the time fields are always normalized. | |
- * | |
- * @return the total amount of time unit nanoseconds of this period | |
- */ | |
- public long getTimeNanos() { | |
- return nanos; | |
- } | |
- | |
//----------------------------------------------------------------------- | |
/** | |
* Returns a copy of this period with the specified amount of years. | |
* <p> | |
- * This method will only affect the years field. | |
- * All other units are unaffected. | |
+ * This sets the amount of the years unit in a copy of this period. | |
+ * The months and days units are unaffected. | |
+ * <p> | |
+ * The months unit is not normalized with the years unit. | |
+ * This means that a period of "15 months" is different to a period | |
+ * of "1 year and 3 months". | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
- * @param years the years to represent | |
+ * @param years the years to represent, may be negative | |
* @return a {@code Period} based on this period with the requested years, not null | |
*/ | |
public Period withYears(int years) { | |
if (years == this.years) { | |
return this; | |
} | |
- return create(years, months, days, nanos); | |
+ return create(years, months, days); | |
} | |
/** | |
* Returns a copy of this period with the specified amount of months. | |
* <p> | |
- * This method will only affect the months field. | |
- * All other units are unaffected. | |
+ * This sets the amount of the months unit in a copy of this period. | |
+ * The years and days units are unaffected. | |
+ * <p> | |
+ * The months unit is not normalized with the years unit. | |
+ * This means that a period of "15 months" is different to a period | |
+ * of "1 year and 3 months". | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
- * @param months the months to represent | |
+ * @param months the months to represent, may be negative | |
* @return a {@code Period} based on this period with the requested months, not null | |
*/ | |
public Period withMonths(int months) { | |
if (months == this.months) { | |
return this; | |
} | |
- return create(years, months, days, nanos); | |
+ return create(years, months, days); | |
} | |
/** | |
* Returns a copy of this period with the specified amount of days. | |
* <p> | |
- * This method will only affect the days field. | |
- * All other units are unaffected. | |
+ * This sets the amount of the days unit in a copy of this period. | |
+ * The years and months units are unaffected. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
- * @param days the days to represent | |
+ * @param days the days to represent, may be negative | |
* @return a {@code Period} based on this period with the requested days, not null | |
*/ | |
public Period withDays(int days) { | |
if (days == this.days) { | |
return this; | |
} | |
- return create(years, months, days, nanos); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified total amount of time units | |
- * expressed in nanoseconds. | |
- * <p> | |
- * Within a period, the time fields are always normalized. | |
- * This method will affect all the time units - hours, minutes, seconds and nanos. | |
- * The date units are unaffected. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param nanos the nanoseconds to represent | |
- * @return a {@code Period} based on this period with the requested nanoseconds, not null | |
- */ | |
- public Period withTimeNanos(long nanos) { | |
- if (nanos == this.nanos) { | |
- return this; | |
- } | |
- return create(years, months, days, nanos); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified duration replacing the time units. | |
- * <p> | |
- * Within a period, the time fields are always normalized and equivalent to a duration. | |
- * Calling this method will return a new period with the time fields replaced. | |
- * This method will affect all the time units - hours, minutes, seconds and nanos. | |
- * The date units are unaffected. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param duration the duration to represent, not null | |
- * @return a {@code Period} based on this period with the time fields set to the specified duration, not null | |
- */ | |
- public Period withTime(Duration duration) { | |
- return withTimeNanos(duration.toNanos()); | |
+ return create(years, months, days); | |
} | |
//----------------------------------------------------------------------- | |
@@ -788,6 +600,9 @@ | |
* This operates separately on the years, months, days and the normalized time. | |
* There is no further normalization beyond the normalized time. | |
* <p> | |
+ * For example, "1 year, 6 months and 3 days" plus "2 years, 2 months and 2 days" | |
+ * returns "3 years, 8 months and 5 days". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param amountToAdd the period to add, not null | |
@@ -798,56 +613,59 @@ | |
return create( | |
Math.addExact(years, amountToAdd.years), | |
Math.addExact(months, amountToAdd.months), | |
- Math.addExact(days, amountToAdd.days), | |
- Math.addExact(nanos, amountToAdd.nanos)); | |
+ Math.addExact(days, amountToAdd.days)); | |
} | |
- /** | |
- * Returns a copy of this period with the specified period added. | |
- * <p> | |
- * The specified unit must be one of the supported units from {@link ChronoUnit}, | |
- * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an | |
- * {@linkplain TemporalUnit#isDurationEstimated() exact duration}. | |
- * Other units throw an exception. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param amountToAdd the amountToAdd to add, positive or negative | |
- * @param unit the unit that the amountToAdd is expressed in, not null | |
- * @return a {@code Period} based on this period with the requested amountToAdd added, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period plus(long amountToAdd, TemporalUnit unit) { | |
- Objects.requireNonNull(unit, "unit"); | |
- if (unit instanceof ChronoUnit) { | |
- if (unit == YEARS || unit == MONTHS || unit == DAYS || unit.isDurationEstimated() == false) { | |
- if (amountToAdd == 0) { | |
- return this; | |
- } | |
- switch((ChronoUnit) unit) { | |
- case NANOS: return plusNanos(amountToAdd); | |
- case MICROS: return plusNanos(Math.multiplyExact(amountToAdd, 1000L)); | |
- case MILLIS: return plusNanos(Math.multiplyExact(amountToAdd, 1000_000L)); | |
- case SECONDS: return plusSeconds(amountToAdd); | |
- case MINUTES: return plusMinutes(amountToAdd); | |
- case HOURS: return plusHours(amountToAdd); | |
- case HALF_DAYS: return plusNanos(Math.multiplyExact(amountToAdd, 12 * NANOS_PER_HOUR)); | |
- case DAYS: return plusDays(amountToAdd); | |
- case MONTHS: return plusMonths(amountToAdd); | |
- case YEARS: return plusYears(amountToAdd); | |
- default: throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
- } | |
- } | |
- } | |
- if (unit.isDurationEstimated()) { | |
- throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
- } | |
- return plusNanos(Duration.of(amountToAdd, unit).toNanos()); | |
- } | |
+// /** | |
+// * Returns a copy of this period with the specified period added. | |
+// * <p> | |
+// * The specified unit must be one of the supported units from {@link ChronoUnit}, | |
+// * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an | |
+// * {@linkplain TemporalUnit#isDurationEstimated() exact duration}. | |
+// * Other units throw an exception. | |
+// * <p> | |
+// * This instance is immutable and unaffected by this method call. | |
+// * | |
+// * @param amountToAdd the amountToAdd to add, positive or negative | |
+// * @param unit the unit that the amountToAdd is expressed in, not null | |
+// * @return a {@code Period} based on this period with the requested amountToAdd added, not null | |
+// * @throws ArithmeticException if numeric overflow occurs | |
+// */ | |
+// public Period plus(long amountToAdd, TemporalUnit unit) { | |
+// Objects.requireNonNull(unit, "unit"); | |
+// if (unit instanceof ChronoUnit) { | |
+// if (unit == YEARS || unit == MONTHS || unit == DAYS || unit.isDurationEstimated() == false) { | |
+// if (amountToAdd == 0) { | |
+// return this; | |
+// } | |
+// switch((ChronoUnit) unit) { | |
+// case NANOS: return plusNanos(amountToAdd); | |
+// case MICROS: return plusNanos(Math.multiplyExact(amountToAdd, 1000L)); | |
+// case MILLIS: return plusNanos(Math.multiplyExact(amountToAdd, 1000_000L)); | |
+// case SECONDS: return plusSeconds(amountToAdd); | |
+// case MINUTES: return plusMinutes(amountToAdd); | |
+// case HOURS: return plusHours(amountToAdd); | |
+// case HALF_DAYS: return plusNanos(Math.multiplyExact(amountToAdd, 12 * NANOS_PER_HOUR)); | |
+// case DAYS: return plusDays(amountToAdd); | |
+// case MONTHS: return plusMonths(amountToAdd); | |
+// case YEARS: return plusYears(amountToAdd); | |
+// default: throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
+// } | |
+// } | |
+// } | |
+// if (unit.isDurationEstimated()) { | |
+// throw new DateTimeException("Unsupported unit: " + unit.getName()); | |
+// } | |
+// return plusNanos(Duration.of(amountToAdd, unit).toNanos()); | |
+// } | |
/** | |
* Returns a copy of this period with the specified years added. | |
* <p> | |
+ * This adds the amount to the years unit in a copy of this period. | |
+ * The months and days units are unaffected. | |
+ * For example, "1 year, 6 months and 3 days" plus 2 years returns "3 years, 6 months and 3 days". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param yearsToAdd the years to add, positive or negative | |
@@ -858,12 +676,16 @@ | |
if (yearsToAdd == 0) { | |
return this; | |
} | |
- return create(Math.toIntExact(Math.addExact(years, yearsToAdd)), months, days, nanos); | |
+ return create(Math.toIntExact(Math.addExact(years, yearsToAdd)), months, days); | |
} | |
/** | |
* Returns a copy of this period with the specified months added. | |
* <p> | |
+ * This adds the amount to the months unit in a copy of this period. | |
+ * The years and days units are unaffected. | |
+ * For example, "1 year, 6 months and 3 days" plus 2 months returns "1 year, 8 months and 3 days". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param monthsToAdd the months to add, positive or negative | |
@@ -874,12 +696,16 @@ | |
if (monthsToAdd == 0) { | |
return this; | |
} | |
- return create(years, Math.toIntExact(Math.addExact(months, monthsToAdd)), days, nanos); | |
+ return create(years, Math.toIntExact(Math.addExact(months, monthsToAdd)), days); | |
} | |
/** | |
* Returns a copy of this period with the specified days added. | |
* <p> | |
+ * This adds the amount to the days unit in a copy of this period. | |
+ * The years and months units are unaffected. | |
+ * For example, "1 year, 6 months and 3 days" plus 2 days returns "1 year, 6 months and 5 days". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param daysToAdd the days to add, positive or negative | |
@@ -890,71 +716,7 @@ | |
if (daysToAdd == 0) { | |
return this; | |
} | |
- return create(years, months, Math.toIntExact(Math.addExact(days, daysToAdd)), nanos); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified hours added. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param hoursToAdd the hours to add, positive or negative | |
- * @return a {@code Period} based on this period with the specified hours added, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period plusHours(long hoursToAdd) { | |
- if (hoursToAdd == 0) { | |
- return this; | |
- } | |
- return plusNanos(Math.multiplyExact(hoursToAdd, NANOS_PER_HOUR)); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified minutes added. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param minutesToAdd the minutes to add, positive or negative | |
- * @return a {@code Period} based on this period with the specified minutes added, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period plusMinutes(long minutesToAdd) { | |
- if (minutesToAdd == 0) { | |
- return this; | |
- } | |
- return plusNanos(Math.multiplyExact(minutesToAdd, NANOS_PER_MINUTE)); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified seconds added. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param secondsToAdd the seconds to add, positive or negative | |
- * @return a {@code Period} based on this period with the specified seconds added, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period plusSeconds(long secondsToAdd) { | |
- if (secondsToAdd == 0) { | |
- return this; | |
- } | |
- return plusNanos(Math.multiplyExact(secondsToAdd, NANOS_PER_SECOND)); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified nanoseconds added. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param nanosToAdd the nanoseconds to add, positive or negative | |
- * @return a {@code Period} based on this period with the specified nanoseconds added, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period plusNanos(long nanosToAdd) { | |
- if (nanosToAdd == 0) { | |
- return this; | |
- } | |
- return create(years, months, days, Math.addExact(nanos, nanosToAdd)); | |
+ return create(years, months, Math.toIntExact(Math.addExact(days, daysToAdd))); | |
} | |
//----------------------------------------------------------------------- | |
@@ -964,6 +726,9 @@ | |
* This operates separately on the years, months, days and the normalized time. | |
* There is no further normalization beyond the normalized time. | |
* <p> | |
+ * For example, "1 year, 6 months and 3 days" minus "2 years, 2 months and 2 days" | |
+ * returns "-1 years, 4 months and 1 day". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param amountToSubtract the period to subtract, not null | |
@@ -974,32 +739,35 @@ | |
return create( | |
Math.subtractExact(years, amountToSubtract.years), | |
Math.subtractExact(months, amountToSubtract.months), | |
- Math.subtractExact(days, amountToSubtract.days), | |
- Math.subtractExact(nanos, amountToSubtract.nanos)); | |
+ Math.subtractExact(days, amountToSubtract.days)); | |
} | |
- /** | |
- * Returns a copy of this period with the specified period subtracted. | |
- * <p> | |
- * The specified unit must be one of the supported units from {@link ChronoUnit}, | |
- * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an | |
- * {@linkplain TemporalUnit#isDurationEstimated() exact duration}. | |
- * Other units throw an exception. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param amountToSubtract the amountToSubtract to subtract, positive or negative | |
- * @param unit the unit that the amountToSubtract is expressed in, not null | |
- * @return a {@code Period} based on this period with the requested amountToSubtract subtracted, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period minus(long amountToSubtract, TemporalUnit unit) { | |
- return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); | |
- } | |
+// /** | |
+// * Returns a copy of this period with the specified period subtracted. | |
+// * <p> | |
+// * The specified unit must be one of the supported units from {@link ChronoUnit}, | |
+// * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an | |
+// * {@linkplain TemporalUnit#isDurationEstimated() exact duration}. | |
+// * Other units throw an exception. | |
+// * <p> | |
+// * This instance is immutable and unaffected by this method call. | |
+// * | |
+// * @param amountToSubtract the amountToSubtract to subtract, positive or negative | |
+// * @param unit the unit that the amountToSubtract is expressed in, not null | |
+// * @return a {@code Period} based on this period with the requested amountToSubtract subtracted, not null | |
+// * @throws ArithmeticException if numeric overflow occurs | |
+// */ | |
+// public Period minus(long amountToSubtract, TemporalUnit unit) { | |
+// return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); | |
+// } | |
/** | |
* Returns a copy of this period with the specified years subtracted. | |
* <p> | |
+ * This subtracts the amount from the years unit in a copy of this period. | |
+ * The months and days units are unaffected. | |
+ * For example, "1 year, 6 months and 3 days" minus 2 years returns "-1 years, 6 months and 3 days". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param yearsToSubtract the years to subtract, positive or negative | |
@@ -1013,6 +781,10 @@ | |
/** | |
* Returns a copy of this period with the specified months subtracted. | |
* <p> | |
+ * This subtracts the amount from the months unit in a copy of this period. | |
+ * The years and days units are unaffected. | |
+ * For example, "1 year, 6 months and 3 days" minus 2 months returns "1 year, 4 months and 3 days". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param monthsToSubtract the years to subtract, positive or negative | |
@@ -1026,6 +798,10 @@ | |
/** | |
* Returns a copy of this period with the specified days subtracted. | |
* <p> | |
+ * This subtracts the amount from the days unit in a copy of this period. | |
+ * The years and months units are unaffected. | |
+ * For example, "1 year, 6 months and 3 days" minus 2 days returns "1 year, 6 months and 1 day". | |
+ * <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @param daysToSubtract the months to subtract, positive or negative | |
@@ -1036,65 +812,16 @@ | |
return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract)); | |
} | |
- /** | |
- * Returns a copy of this period with the specified hours subtracted. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param hoursToSubtract the days to subtract, positive or negative | |
- * @return a {@code Period} based on this period with the specified hours subtracted, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period minusHours(long hoursToSubtract) { | |
- return (hoursToSubtract == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hoursToSubtract)); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified minutes subtracted. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param minutesToSubtract the hours to subtract, positive or negative | |
- * @return a {@code Period} based on this period with the specified minutes subtracted, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period minusMinutes(long minutesToSubtract) { | |
- return (minutesToSubtract == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutesToSubtract)); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified seconds subtracted. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param secondsToSubtract the years to subtract, positive or negative | |
- * @return a {@code Period} based on this period with the specified seconds subtracted, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period minusSeconds(long secondsToSubtract) { | |
- return (secondsToSubtract == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-secondsToSubtract)); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the specified nanoseconds subtracted. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @param nanosToSubtract the nanoseconds to subtract, positive or negative | |
- * @return a {@code Period} based on this period with the specified nanoseconds subtracted, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period minusNanos(long nanosToSubtract) { | |
- return (nanosToSubtract == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-nanosToSubtract)); | |
- } | |
- | |
//----------------------------------------------------------------------- | |
/** | |
* Returns a new instance with each element in this period multiplied | |
* by the specified scalar. | |
* <p> | |
- * This simply multiplies each field, years, months, days and normalized time, | |
- * by the scalar. No normalization is performed. | |
+ * This returns a period with each of the years, months and days units | |
+ * individually multiplied. | |
+ * For example, a period of "2 years, -3 months and 4 days" multiplied by | |
+ * 3 will return "6 years, -9 months and 12 days". | |
+ * No normalization is performed. | |
* | |
* @param scalar the scalar to multiply by, not null | |
* @return a {@code Period} based on this period with the amounts multiplied by the scalar, not null | |
@@ -1107,15 +834,21 @@ | |
return create( | |
Math.multiplyExact(years, scalar), | |
Math.multiplyExact(months, scalar), | |
- Math.multiplyExact(days, scalar), | |
- Math.multiplyExact(nanos, scalar)); | |
+ Math.multiplyExact(days, scalar)); | |
} | |
/** | |
* Returns a new instance with each amount in this period negated. | |
+ * <p> | |
+ * This returns a period with each of the years, months and days units | |
+ * individually negated. | |
+ * For example, a period of "2 years, -3 months and 4 days" will be | |
+ * negated to "-2 years, 3 months and -4 days". | |
+ * No normalization is performed. | |
* | |
* @return a {@code Period} based on this period with the amounts negated, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
+ * @throws ArithmeticException if numeric overflow occurs, which only happens if | |
+ * one of the units has the value {@code Long.MIN_VALUE} | |
*/ | |
public Period negated() { | |
return multipliedBy(-1); | |
@@ -1123,137 +856,49 @@ | |
//----------------------------------------------------------------------- | |
/** | |
- * Returns a copy of this period with the days and hours normalized using a 24 hour day. | |
+ * Returns a copy of this period with the years and months normalized | |
+ * using a 12 month year. | |
* <p> | |
- * This normalizes the days and hours units, leaving years and months unchanged. | |
- * The hours unit is adjusted to have an absolute value less than 23, | |
- * with the days unit being adjusted to compensate. | |
- * For example, a period of {@code P1DT27H} will be normalized to {@code P2DT3H}. | |
- * <p> | |
- * The sign of the days and hours units will be the same after normalization. | |
- * For example, a period of {@code P1DT-51H} will be normalized to {@code P-1DT-3H}. | |
- * Since all time units are always normalized, if the hours units changes sign then | |
- * other time units will also be affected. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @return a {@code Period} based on this period with excess hours normalized to days, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period normalizedHoursToDays() { | |
- // logic uses if statements to normalize signs to avoid unnecessary overflows | |
- long totalDays = (nanos / NANOS_PER_DAY) + days; // no overflow | |
- long splitNanos = nanos % NANOS_PER_DAY; | |
- if (totalDays > 0 && splitNanos < 0) { | |
- splitNanos += NANOS_PER_DAY; | |
- totalDays--; | |
- } else if (totalDays < 0 && splitNanos > 0) { | |
- splitNanos -= NANOS_PER_DAY; | |
- totalDays++; | |
- } | |
- if (totalDays == days && splitNanos == nanos) { | |
- return this; | |
- } | |
- return create(years, months, Math.toIntExact(totalDays), splitNanos); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with any days converted to hours using a 24 hour day. | |
- * <p> | |
- * The days unit is reduced to zero, with the hours unit increased by 24 times the | |
- * days unit to compensate. Other units are unaffected. | |
- * For example, a period of {@code P2DT4H} will be normalized to {@code PT52H}. | |
- * <p> | |
- * This can be used to calculate the total number of hours in a period, including | |
- * days but not months or years: | |
- * <pre> | |
- * int totalHours = period.normalizedDaysToHours().getHours(); | |
- * </pre> | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @return a {@code Period} based on this period with days normalized to hours, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
- */ | |
- public Period normalizedDaysToHours() { | |
- if (days == 0) { | |
- return this; | |
- } | |
- return create(years, months, 0, Math.addExact(Math.multiplyExact(days, NANOS_PER_DAY), nanos)); | |
- } | |
- | |
- /** | |
- * Returns a copy of this period with the years and months normalized using a 12 month year. | |
- * <p> | |
- * This normalizes the years and months units, leaving other units unchanged. | |
+ * This normalizes the years and months units, leaving the days unit unchanged. | |
* The months unit is adjusted to have an absolute value less than 11, | |
- * with the years unit being adjusted to compensate. | |
- * For example, a period of {@code P1Y15M} will be normalized to {@code P2Y3M}. | |
+ * with the years unit being adjusted to compensate. For example, a period of | |
+ * "1 Year and 15 months" will be normalized to "2 years and 3 months". | |
* <p> | |
* The sign of the years and months units will be the same after normalization. | |
- * For example, a period of {@code P1Y-25M} will be normalized to {@code P-1Y-1M}. | |
+ * For example, a period of "1 year and -25 months" will be normalized to | |
+ * "-1 year and -1 month". | |
* <p> | |
- * This normalization uses a 12 month year it is not valid for all calendar systems. | |
+ * This normalization uses a 12 month year which is not valid for all calendar systems. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
* @return a {@code Period} based on this period with excess months normalized to years, not null | |
* @throws ArithmeticException if numeric overflow occurs | |
*/ | |
- public Period normalizedMonthsToYears() { | |
- long totalMonths = years * 12L + months; // no overflow | |
+ public Period normalized() { | |
+ long totalMonths = toTotalMonths(); | |
long splitYears = totalMonths / 12; | |
int splitMonths = (int) (totalMonths % 12); // no overflow | |
if (splitYears == years && splitMonths == months) { | |
return this; | |
} | |
- return create(Math.toIntExact(splitYears), splitMonths, days, nanos); | |
+ return create(Math.toIntExact(splitYears), splitMonths, days); | |
} | |
/** | |
- * Returns a copy of this period with any years converted to months using a 12 month year. | |
+ * Gets the total number of months in this period using a 12 month year. | |
* <p> | |
- * The years unit is reduced to zero, with the months unit increased by 12 times the | |
- * years unit to compensate. Other units are unaffected. | |
- * For example, a period of {@code P1Y15M} will be normalized to {@code P27M}. | |
+ * This returns the total number of months in the period by multiplying the | |
+ * number of years by 12 and adding the number of months. | |
* <p> | |
- * This can be used to calculate the total number of months in a period: | |
- * <pre> | |
- * int totalMonths = period.normalizedYearsToMonths().getMonths(); | |
- * </pre> | |
- * <p> | |
- * This normalization uses a 12 month year it is not valid for all calendar systems. | |
+ * This uses a 12 month year which is not valid for all calendar systems. | |
* <p> | |
* This instance is immutable and unaffected by this method call. | |
* | |
- * @return a {@code Period} based on this period with years normalized to months, not null | |
- * @throws ArithmeticException if numeric overflow occurs | |
+ * @return the total number of months in the period, may be negative | |
*/ | |
- public Period normalizedYearsToMonths() { | |
- if (years == 0) { | |
- return this; | |
- } | |
- long totalMonths = years * 12L + months; // no overflow | |
- return create(0, Math.toIntExact(totalMonths), days, nanos); | |
- } | |
- | |
- //------------------------------------------------------------------------- | |
- /** | |
- * Converts this period to one that only has date units. | |
- * <p> | |
- * The resulting period will have the same years, months and days as this period | |
- * but the time units will all be zero. No normalization occurs in the calculation. | |
- * For example, a period of {@code P1Y3MT12H} will be converted to {@code P1Y3M}. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
- * | |
- * @return a {@code Period} based on this period with the time units set to zero, not null | |
- */ | |
- public Period toDateOnly() { | |
- if (nanos == 0) { | |
- return this; | |
- } | |
- return create(years, months, days, 0); | |
+ public long toTotalMonths() { | |
+ return years * 12L + months; // no overflow | |
} | |
//------------------------------------------------------------------------- | |
@@ -1271,7 +916,7 @@ | |
* dateTime = dateTime.plus(thisPeriod); | |
* </pre> | |
* <p> | |
- * The calculation will add the years, then months, then days, then nanos. | |
+ * The calculation will add the years, then months, then days. | |
* Only non-zero amounts will be added. | |
* If the date-time has a calendar system with a fixed number of months in a | |
* year, then the years and months will be combined before being added. | |
@@ -1287,10 +932,9 @@ | |
public Temporal addTo(Temporal temporal) { | |
Objects.requireNonNull(temporal, "temporal"); | |
if ((years | months) != 0) { | |
- ValueRange startRange = Chronology.from(temporal).range(MONTH_OF_YEAR); | |
- if (startRange.isFixed() && startRange.isIntValue()) { | |
- long monthCount = startRange.getMaximum() - startRange.getMinimum() + 1; | |
- temporal = temporal.plus(years * monthCount + months, MONTHS); | |
+ long monthRange = monthRange(temporal); | |
+ if (monthRange >= 0) { | |
+ temporal = temporal.plus(years * monthRange + months, MONTHS); | |
} else { | |
if (years != 0) { | |
temporal = temporal.plus(years, YEARS); | |
@@ -1303,9 +947,6 @@ | |
if (days != 0) { | |
temporal = temporal.plus(days, DAYS); | |
} | |
- if (nanos != 0) { | |
- temporal = temporal.plus(nanos, NANOS); | |
- } | |
return temporal; | |
} | |
@@ -1323,7 +964,7 @@ | |
* dateTime = dateTime.minus(thisPeriod); | |
* </pre> | |
* <p> | |
- * The calculation will subtract the years, then months, then days, then nanos. | |
+ * The calculation will subtract the years, then months, then days. | |
* Only non-zero amounts will be subtracted. | |
* If the date-time has a calendar system with a fixed number of months in a | |
* year, then the years and months will be combined before being subtracted. | |
@@ -1339,10 +980,9 @@ | |
public Temporal subtractFrom(Temporal temporal) { | |
Objects.requireNonNull(temporal, "temporal"); | |
if ((years | months) != 0) { | |
- ValueRange startRange = Chronology.from(temporal).range(MONTH_OF_YEAR); | |
- if (startRange.isFixed() && startRange.isIntValue()) { | |
- long monthCount = startRange.getMaximum() - startRange.getMinimum() + 1; | |
- temporal = temporal.minus(years * monthCount + months, MONTHS); | |
+ long monthRange = monthRange(temporal); | |
+ if (monthRange >= 0) { | |
+ temporal = temporal.minus(years * monthRange + months, MONTHS); | |
} else { | |
if (years != 0) { | |
temporal = temporal.minus(years, YEARS); | |
@@ -1355,48 +995,21 @@ | |
if (days != 0) { | |
temporal = temporal.minus(days, DAYS); | |
} | |
- if (nanos != 0) { | |
- temporal = temporal.minus(nanos, NANOS); | |
- } | |
return temporal; | |
} | |
- //----------------------------------------------------------------------- | |
/** | |
- * Converts this period to one that only has time units. | |
- * <p> | |
- * The resulting period will have the same time units as this period | |
- * but the date units will all be zero. No normalization occurs in the calculation. | |
- * For example, a period of {@code P1Y3MT12H} will be converted to {@code PT12H}. | |
- * <p> | |
- * This instance is immutable and unaffected by this method call. | |
+ * Calculates the range of months based on the temporal. | |
* | |
- * @return a {@code Period} based on this period with the date units set to zero, not null | |
+ * @param temporal the temporal, not null | |
+ * @return the month range, negative if not fixed range | |
*/ | |
- public Period toTimeOnly() { | |
- if ((years | months | days) == 0) { | |
- return this; | |
+ private long monthRange(Temporal temporal) { | |
+ ValueRange startRange = Chronology.from(temporal).range(MONTH_OF_YEAR); | |
+ if (startRange.isFixed() && startRange.isIntValue()) { | |
+ return startRange.getMaximum() - startRange.getMinimum() + 1; | |
} | |
- return create(0, 0, 0, nanos); | |
- } | |
- | |
- //------------------------------------------------------------------------- | |
- /** | |
- * Calculates the duration of this period. | |
- * <p> | |
- * The calculation uses the hours, minutes, seconds and nanoseconds fields. | |
- * If years, months or days are present an exception is thrown. | |
- * See {@link #toTimeOnly()} for a way to remove the date units and | |
- * {@link #normalizedDaysToHours()} for a way to convert days to hours. | |
- * | |
- * @return a {@code Duration} equivalent to this period, not null | |
- * @throws DateTimeException if the period cannot be converted as it contains years, months or days | |
- */ | |
- public Duration toDuration() { | |
- if ((years | months | days) != 0) { | |
- throw new DateTimeException("Unable to convert period to duration as years/months/days are present: " + this); | |
- } | |
- return Duration.ofNanos(nanos); | |
+ return -1; | |
} | |
//----------------------------------------------------------------------- | |
@@ -1404,7 +1017,9 @@ | |
* Checks if this period is equal to another period. | |
* <p> | |
* The comparison is based on the amounts held in the period. | |
- * To be equal, the years, months, days and normalized time fields must be equal. | |
+ * To be equal, the years, months and days units must be individually equal. | |
+ * Note that this means that a period of "15 Months" is not equal to a period | |
+ * of "1 Year and 3 Months". | |
* | |
* @param obj the object to check, null returns false | |
* @return true if this is equal to the other period | |
@@ -1416,8 +1031,9 @@ | |
} | |
if (obj instanceof Period) { | |
Period other = (Period) obj; | |
- return years == other.years && months == other.months && | |
- days == other.days && nanos == other.nanos; | |
+ return years == other.years && | |
+ months == other.months && | |
+ days == other.days; | |
} | |
return false; | |
} | |
@@ -1429,25 +1045,22 @@ | |
*/ | |
@Override | |
public int hashCode() { | |
- // ordered such that overflow from one field doesn't immediately affect the next field | |
- return ((years << 27) | (years >>> 5)) ^ | |
- ((days << 21) | (days >>> 11)) ^ | |
- ((months << 17) | (months >>> 15)) ^ | |
- ((int) (nanos ^ (nanos >>> 32))); | |
+ return years + Integer.rotateLeft(months, 8) + Integer.rotateLeft(days, 16); | |
} | |
//----------------------------------------------------------------------- | |
/** | |
- * Outputs this period as a {@code String}, such as {@code P6Y3M1DT12H}. | |
+ * Outputs this period as a {@code String}, such as {@code P6Y3M1D}. | |
* <p> | |
* The output will be in the ISO-8601 period format. | |
+ * A zero period will be represented as zero days, 'P0D'. | |
* | |
* @return a string representation of this period, not null | |
*/ | |
@Override | |
public String toString() { | |
if (this == ZERO) { | |
- return "PT0S"; | |
+ return "P0D"; | |
} else { | |
StringBuilder buf = new StringBuilder(); | |
buf.append('P'); | |
@@ -1460,38 +1073,47 @@ | |
if (days != 0) { | |
buf.append(days).append('D'); | |
} | |
- if (nanos != 0) { | |
- buf.append('T'); | |
- if (getHours() != 0) { | |
- buf.append(getHours()).append('H'); | |
- } | |
- if (getMinutes() != 0) { | |
- buf.append(getMinutes()).append('M'); | |
- } | |
- int secondPart = getSeconds(); | |
- int nanoPart = getNanos(); | |
- int secsNanosOr = secondPart | nanoPart; | |
- if (secsNanosOr != 0) { // if either non-zero | |
- if ((secsNanosOr & Integer.MIN_VALUE) != 0) { // if either less than zero | |
- buf.append('-'); | |
- secondPart = Math.abs(secondPart); | |
- nanoPart = Math.abs(nanoPart); | |
- } | |
- buf.append(secondPart); | |
- if (nanoPart != 0) { | |
- int dotPos = buf.length(); | |
- nanoPart += 1000_000_000; | |
- while (nanoPart % 10 == 0) { | |
- nanoPart /= 10; | |
- } | |
- buf.append(nanoPart); | |
- buf.setCharAt(dotPos, '.'); | |
- } | |
- buf.append('S'); | |
- } | |
- } | |
return buf.toString(); | |
} | |
} | |
+ //----------------------------------------------------------------------- | |
+ /** | |
+ * Writes the object using a | |
+ * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>. | |
+ * <pre> | |
+ * out.writeByte(14); // identifies this as a Period | |
+ * out.writeInt(years); | |
+ * out.writeInt(months); | |
+ * out.writeInt(seconds); | |
+ * </pre> | |
+ * | |
+ * @return the instance of {@code Ser}, not null | |
+ */ | |
+ private Object writeReplace() { | |
+ return new Ser(Ser.PERIOD_TYPE, this); | |
+ } | |
+ | |
+ /** | |
+ * Defend against malicious streams. | |
+ * @return never | |
+ * @throws java.io.InvalidObjectException always | |
+ */ | |
+ private Object readResolve() throws ObjectStreamException { | |
+ throw new InvalidObjectException("Deserialization via serialization delegate"); | |
+ } | |
+ | |
+ void writeExternal(DataOutput out) throws IOException { | |
+ out.writeInt(years); | |
+ out.writeInt(months); | |
+ out.writeInt(days); | |
+ } | |
+ | |
+ static Period readExternal(DataInput in) throws IOException { | |
+ int years = in.readInt(); | |
+ int months = in.readInt(); | |
+ int days = in.readInt(); | |
+ return Period.of(years, months, days); | |
+ } | |
+ | |
} | |
diff --git a/src/share/classes/java/time/Ser.java b/src/share/classes/java/time/Ser.java | |
--- a/src/share/classes/java/time/Ser.java | |
+++ b/src/share/classes/java/time/Ser.java | |
@@ -106,6 +106,7 @@ | |
static final byte YEAR_TYPE = 11; | |
static final byte YEAR_MONTH_TYPE = 12; | |
static final byte MONTH_DAY_TYPE = 13; | |
+ static final byte PERIOD_TYPE = 14; | |
/** The type being serialized. */ | |
private byte type; | |
@@ -182,6 +183,9 @@ | |
case MONTH_DAY_TYPE: | |
((MonthDay) object).writeExternal(out); | |
break; | |
+ case PERIOD_TYPE: | |
+ ((Period) object).writeExternal(out); | |
+ break; | |
default: | |
throw new InvalidClassException("Unknown serialized type"); | |
} | |
@@ -218,6 +222,7 @@ | |
case YEAR_TYPE: return Year.readExternal(in); | |
case YEAR_MONTH_TYPE: return YearMonth.readExternal(in); | |
case MONTH_DAY_TYPE: return MonthDay.readExternal(in); | |
+ case PERIOD_TYPE: return Period.readExternal(in); | |
default: | |
throw new StreamCorruptedException("Unknown serialized type"); | |
} | |
diff --git a/test/java/time/tck/java/time/TCKDuration.java b/test/java/time/tck/java/time/TCKDuration.java | |
--- a/test/java/time/tck/java/time/TCKDuration.java | |
+++ b/test/java/time/tck/java/time/TCKDuration.java | |
@@ -623,7 +623,7 @@ | |
//----------------------------------------------------------------------- | |
// isZero(), isPositive(), isPositiveOrZero(), isNegative(), isNegativeOrZero() | |
//----------------------------------------------------------------------- | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_isZero() { | |
assertEquals(Duration.ofNanos(0).isZero(), true); | |
assertEquals(Duration.ofSeconds(0).isZero(), true); | |
@@ -635,19 +635,7 @@ | |
assertEquals(Duration.ofSeconds(-1, -1).isZero(), false); | |
} | |
- @Test(groups={"tck"}) | |
- public void test_isPositive() { | |
- assertEquals(Duration.ofNanos(0).isPositive(), false); | |
- assertEquals(Duration.ofSeconds(0).isPositive(), false); | |
- assertEquals(Duration.ofNanos(1).isPositive(), true); | |
- assertEquals(Duration.ofSeconds(1).isPositive(), true); | |
- assertEquals(Duration.ofSeconds(1, 1).isPositive(), true); | |
- assertEquals(Duration.ofNanos(-1).isPositive(), false); | |
- assertEquals(Duration.ofSeconds(-1).isPositive(), false); | |
- assertEquals(Duration.ofSeconds(-1, -1).isPositive(), false); | |
- } | |
- | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_isNegative() { | |
assertEquals(Duration.ofNanos(0).isNegative(), false); | |
assertEquals(Duration.ofSeconds(0).isNegative(), false); | |
@@ -1992,18 +1980,12 @@ | |
Duration b = durations[j]; | |
if (i < j) { | |
assertEquals(a.compareTo(b)< 0, true, a + " <=> " + b); | |
- assertEquals(a.isLessThan(b), true, a + " <=> " + b); | |
- assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); | |
assertEquals(a.equals(b), false, a + " <=> " + b); | |
} else if (i > j) { | |
assertEquals(a.compareTo(b) > 0, true, a + " <=> " + b); | |
- assertEquals(a.isLessThan(b), false, a + " <=> " + b); | |
- assertEquals(a.isGreaterThan(b), true, a + " <=> " + b); | |
assertEquals(a.equals(b), false, a + " <=> " + b); | |
} else { | |
assertEquals(a.compareTo(b), 0, a + " <=> " + b); | |
- assertEquals(a.isLessThan(b), false, a + " <=> " + b); | |
- assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); | |
assertEquals(a.equals(b), true, a + " <=> " + b); | |
} | |
} | |
@@ -2016,18 +1998,6 @@ | |
a.compareTo(null); | |
} | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_isLessThan_ObjectNull() { | |
- Duration a = Duration.ofSeconds(0L, 0); | |
- a.isLessThan(null); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_isGreaterThan_ObjectNull() { | |
- Duration a = Duration.ofSeconds(0L, 0); | |
- a.isGreaterThan(null); | |
- } | |
- | |
@Test(expectedExceptions=ClassCastException.class, groups={"tck"}) | |
@SuppressWarnings({ "unchecked", "rawtypes" }) | |
public void compareToNonDuration() { | |
diff --git a/test/java/time/tck/java/time/TCKInstant.java b/test/java/time/tck/java/time/TCKInstant.java | |
--- a/test/java/time/tck/java/time/TCKInstant.java | |
+++ b/test/java/time/tck/java/time/TCKInstant.java | |
@@ -84,7 +84,6 @@ | |
import java.time.Instant; | |
import java.time.LocalDateTime; | |
import java.time.OffsetDateTime; | |
-import java.time.Period; | |
import java.time.ZoneOffset; | |
import java.time.ZonedDateTime; | |
import java.time.format.DateTimeParseException; | |
@@ -536,6 +535,49 @@ | |
} | |
//----------------------------------------------------------------------- | |
+ // plus(TemporalAmount) | |
+ //----------------------------------------------------------------------- | |
+ @DataProvider(name="plusTemporalAmount") | |
+ Object[][] data_plusTemporalAmount() { | |
+ return new Object[][] { | |
+ {DAYS, MockSimplePeriod.of(1, DAYS), 86401, 0}, | |
+ {HOURS, MockSimplePeriod.of(2, HOURS), 7201, 0}, | |
+ {MINUTES, MockSimplePeriod.of(4, MINUTES), 241, 0}, | |
+ {SECONDS, MockSimplePeriod.of(5, SECONDS), 6, 0}, | |
+ {NANOS, MockSimplePeriod.of(6, NANOS), 1, 6}, | |
+ {DAYS, MockSimplePeriod.of(10, DAYS), 864001, 0}, | |
+ {HOURS, MockSimplePeriod.of(11, HOURS), 39601, 0}, | |
+ {MINUTES, MockSimplePeriod.of(12, MINUTES), 721, 0}, | |
+ {SECONDS, MockSimplePeriod.of(13, SECONDS), 14, 0}, | |
+ {NANOS, MockSimplePeriod.of(14, NANOS), 1, 14}, | |
+ {SECONDS, Duration.ofSeconds(20, 40), 21, 40}, | |
+ {NANOS, Duration.ofSeconds(30, 300), 31, 300}, | |
+ }; | |
+ } | |
+ | |
+ @Test(dataProvider="plusTemporalAmount") | |
+ public void test_plusTemporalAmount(TemporalUnit unit, TemporalAmount amount, int seconds, int nanos) { | |
+ Instant inst = Instant.ofEpochMilli(1000); | |
+ Instant actual = inst.plus(amount); | |
+ Instant expected = Instant.ofEpochSecond(seconds, nanos); | |
+ assertEquals(actual, expected, "plus(TemporalAmount) failed"); | |
+ } | |
+ | |
+ @DataProvider(name="badTemporalAmount") | |
+ Object[][] data_badPlusTemporalAmount() { | |
+ return new Object[][] { | |
+ {MockSimplePeriod.of(2, YEARS)}, | |
+ {MockSimplePeriod.of(2, MONTHS)}, | |
+ }; | |
+ } | |
+ | |
+ @Test(dataProvider="badTemporalAmount",expectedExceptions=DateTimeException.class) | |
+ public void test_badPlusTemporalAmount(TemporalAmount amount) { | |
+ Instant inst = Instant.ofEpochMilli(1000); | |
+ inst.plus(amount); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
@DataProvider(name="Plus") | |
Object[][] provider_plus() { | |
return new Object[][] { | |
@@ -1613,62 +1655,6 @@ | |
} | |
//----------------------------------------------------------------------- | |
- // plus(TemporalAmount) | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="plusTemporalAmount") | |
- Object[][] data_plusTemporalAmount() { | |
- return new Object[][] { | |
- {DAYS, Period.of(1, DAYS), 86401, 0}, | |
- {HOURS, Period.of(2, HOURS), 7201, 0}, | |
- {MINUTES, Period.of(4, MINUTES), 241, 0}, | |
- {SECONDS, Period.of(5, SECONDS), 6, 0}, | |
- {NANOS, Period.of(6, NANOS), 1, 6}, | |
- {DAYS, Period.of(10, DAYS), 864001, 0}, | |
- {HOURS, Period.of(11, HOURS), 39601, 0}, | |
- {MINUTES, Period.of(12, MINUTES), 721, 0}, | |
- {SECONDS, Period.of(13, SECONDS), 14, 0}, | |
- {NANOS, Period.of(14, NANOS), 1, 14}, | |
- {SECONDS, Duration.ofSeconds(20, 40), 21, 40}, | |
- {NANOS, Duration.ofSeconds(30, 300), 31, 300}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="plusTemporalAmount") | |
- public void test_plusTemporalAmount(TemporalUnit unit, TemporalAmount amount, int seconds, int nanos) { | |
- Instant inst = Instant.ofEpochMilli(1000); | |
- Instant actual = inst.plus(amount); | |
- Instant expected = Instant.ofEpochSecond(seconds, nanos); | |
- assertEquals(actual, expected, "plus(TemporalAmount) failed"); | |
- } | |
- | |
- @DataProvider(name="badTemporalAmount") | |
- Object[][] data_badPlusTemporalAmount() { | |
- return new Object[][] { | |
- {Period.of(2, YEARS)}, | |
- {Period.of(2, MONTHS)}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="badTemporalAmount",expectedExceptions=DateTimeException.class) | |
- public void test_badPlusTemporalAmount(TemporalAmount amount) { | |
- Instant inst = Instant.ofEpochMilli(1000); | |
- inst.plus(amount); | |
- } | |
- | |
- @Test(dataProvider="plusTemporalAmount") | |
- public void test_completeAndUnique(TemporalUnit theUnit, TemporalAmount amount, int seconds, int nanos) { | |
- Temporal inst = Instant.ofEpochMilli(1000); | |
- Temporal expected = inst.plus(amount); | |
- Temporal accum = inst; | |
- for (TemporalUnit unit: amount.getUnits()) { | |
- long delta = amount.get(unit); | |
- if (delta != 0) { | |
- accum = accum.plus(delta, unit); | |
- } | |
- } | |
- assertEquals(accum, expected, "adding individual units different than adding whole amoutn"); | |
- } | |
- //----------------------------------------------------------------------- | |
// compareTo() | |
//----------------------------------------------------------------------- | |
@Test | |
diff --git a/test/java/time/tck/java/time/TCKLocalDateTime.java b/test/java/time/tck/java/time/TCKLocalDateTime.java | |
--- a/test/java/time/tck/java/time/TCKLocalDateTime.java | |
+++ b/test/java/time/tck/java/time/TCKLocalDateTime.java | |
@@ -88,8 +88,10 @@ | |
import static java.time.temporal.ChronoField.YEAR; | |
import static java.time.temporal.ChronoField.YEAR_OF_ERA; | |
import static java.time.temporal.ChronoUnit.DAYS; | |
+import static java.time.temporal.ChronoUnit.MONTHS; | |
import static java.time.temporal.ChronoUnit.NANOS; | |
import static java.time.temporal.ChronoUnit.SECONDS; | |
+import static java.time.temporal.ChronoUnit.YEARS; | |
import static org.testng.Assert.assertEquals; | |
import static org.testng.Assert.assertFalse; | |
import static org.testng.Assert.assertSame; | |
@@ -106,7 +108,6 @@ | |
import java.time.LocalTime; | |
import java.time.Month; | |
import java.time.OffsetDateTime; | |
-import java.time.Period; | |
import java.time.Year; | |
import java.time.ZoneId; | |
import java.time.ZoneOffset; | |
@@ -133,7 +134,6 @@ | |
import org.testng.annotations.BeforeMethod; | |
import org.testng.annotations.DataProvider; | |
import org.testng.annotations.Test; | |
-import test.java.time.MockSimplePeriod; | |
/** | |
* Test LocalDateTime. | |
@@ -1286,54 +1286,39 @@ | |
} | |
//----------------------------------------------------------------------- | |
- // plus(adjuster) | |
+ // plus(TemporalAmount) | |
//----------------------------------------------------------------------- | |
- @Test(groups={"tck"}) | |
- public void test_plus_adjuster() { | |
- Period p = Period.ofTime(0, 0, 62, 3); | |
- LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plus(p); | |
- assertEquals(t, LocalDateTime.of(2007, 7, 15, 12, 31, 42, 987654324)); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_plus_adjuster_null() { | |
- TEST_2007_07_15_12_30_40_987654321.plus((TemporalAmount) null); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // plus(Period) | |
- //----------------------------------------------------------------------- | |
- @Test(groups={"tck"}) | |
- public void test_plus_Period_positiveMonths() { | |
- MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); | |
+ @Test | |
+ public void test_plus_TemporalAmount_positiveMonths() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(7, MONTHS); | |
LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plus(period); | |
assertEquals(t, LocalDateTime.of(2008, 2, 15, 12, 30, 40, 987654321)); | |
} | |
- @Test(groups={"tck"}) | |
- public void test_plus_Period_negativeDays() { | |
- MockSimplePeriod period = MockSimplePeriod.of(-25, ChronoUnit.DAYS); | |
+ @Test | |
+ public void test_plus_TemporalAmount_negativeDays() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(-25, DAYS); | |
LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plus(period); | |
assertEquals(t, LocalDateTime.of(2007, 6, 20, 12, 30, 40, 987654321)); | |
} | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_plus_Period_null() { | |
- TEST_2007_07_15_12_30_40_987654321.plus((MockSimplePeriod) null); | |
- } | |
- | |
- @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) | |
- public void test_plus_Period_invalidTooLarge() { | |
- MockSimplePeriod period = MockSimplePeriod.of(1, ChronoUnit.YEARS); | |
+ @Test(expectedExceptions=DateTimeException.class) | |
+ public void test_plus_TemporalAmount_invalidTooLarge() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(1, YEARS); | |
LocalDateTime.of(Year.MAX_VALUE, 1, 1, 0, 0).plus(period); | |
} | |
- @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) | |
- public void test_plus_Period_invalidTooSmall() { | |
- MockSimplePeriod period = MockSimplePeriod.of(-1, ChronoUnit.YEARS); | |
+ @Test(expectedExceptions=DateTimeException.class) | |
+ public void test_plus_TemporalAmount_invalidTooSmall() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(-1, YEARS); | |
LocalDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0).plus(period); | |
} | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void test_plus_TemporalAmount_null() { | |
+ TEST_2007_07_15_12_30_40_987654321.plus((TemporalAmount) null); | |
+ } | |
+ | |
//----------------------------------------------------------------------- | |
// plus(long,TemporalUnit) | |
//----------------------------------------------------------------------- | |
@@ -1990,54 +1975,39 @@ | |
} | |
//----------------------------------------------------------------------- | |
- // minus(adjuster) | |
+ // minus(TemporalAmount) | |
//----------------------------------------------------------------------- | |
- @Test(groups={"tck"}) | |
- public void test_minus_adjuster() { | |
- Period p = Period.ofTime(0, 0, 62, 3); | |
- LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minus(p); | |
- assertEquals(t, LocalDateTime.of(2007, 7, 15, 12, 29, 38, 987654318)); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_minus_adjuster_null() { | |
- TEST_2007_07_15_12_30_40_987654321.minus((TemporalAmount) null); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minus(Period) | |
- //----------------------------------------------------------------------- | |
- @Test(groups={"tck"}) | |
- public void test_minus_Period_positiveMonths() { | |
- MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); | |
+ @Test | |
+ public void test_minus_TemporalAmount_positiveMonths() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(7, MONTHS); | |
LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minus(period); | |
assertEquals(t, LocalDateTime.of(2006, 12, 15, 12, 30, 40, 987654321)); | |
} | |
- @Test(groups={"tck"}) | |
- public void test_minus_Period_negativeDays() { | |
- MockSimplePeriod period = MockSimplePeriod.of(-25, ChronoUnit.DAYS); | |
+ @Test | |
+ public void test_minus_TemporalAmount_negativeDays() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(-25, DAYS); | |
LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minus(period); | |
assertEquals(t, LocalDateTime.of(2007, 8, 9, 12, 30, 40, 987654321)); | |
} | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_minus_Period_null() { | |
- TEST_2007_07_15_12_30_40_987654321.minus((MockSimplePeriod) null); | |
- } | |
- | |
- @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) | |
- public void test_minus_Period_invalidTooLarge() { | |
- MockSimplePeriod period = MockSimplePeriod.of(-1, ChronoUnit.YEARS); | |
+ @Test(expectedExceptions=DateTimeException.class) | |
+ public void test_minus_TemporalAmount_invalidTooLarge() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(-1, YEARS); | |
LocalDateTime.of(Year.MAX_VALUE, 1, 1, 0, 0).minus(period); | |
} | |
- @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) | |
- public void test_minus_Period_invalidTooSmall() { | |
- MockSimplePeriod period = MockSimplePeriod.of(1, ChronoUnit.YEARS); | |
+ @Test(expectedExceptions=DateTimeException.class) | |
+ public void test_minus_TemporalAmount_invalidTooSmall() { | |
+ MockSimplePeriod period = MockSimplePeriod.of(1, YEARS); | |
LocalDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0).minus(period); | |
} | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void test_minus_TemporalAmount_null() { | |
+ TEST_2007_07_15_12_30_40_987654321.minus((TemporalAmount) null); | |
+ } | |
+ | |
//----------------------------------------------------------------------- | |
// minus(long,TemporalUnit) | |
//----------------------------------------------------------------------- | |
diff --git a/test/java/time/tck/java/time/TCKLocalTime.java b/test/java/time/tck/java/time/TCKLocalTime.java | |
--- a/test/java/time/tck/java/time/TCKLocalTime.java | |
+++ b/test/java/time/tck/java/time/TCKLocalTime.java | |
@@ -125,7 +125,6 @@ | |
import org.testng.annotations.BeforeMethod; | |
import org.testng.annotations.DataProvider; | |
import org.testng.annotations.Test; | |
-import test.java.time.MockSimplePeriod; | |
/** | |
* Test LocalTime. | |
@@ -1032,41 +1031,41 @@ | |
//----------------------------------------------------------------------- | |
// plus(TemporalAmount) | |
//----------------------------------------------------------------------- | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_plus_TemporalAmount_positiveHours() { | |
TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.HOURS); | |
LocalTime t = TEST_12_30_40_987654321.plus(period); | |
assertEquals(t, LocalTime.of(19, 30, 40, 987654321)); | |
} | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_plus_TemporalAmount_negativeMinutes() { | |
TemporalAmount period = MockSimplePeriod.of(-25, ChronoUnit.MINUTES); | |
LocalTime t = TEST_12_30_40_987654321.plus(period); | |
assertEquals(t, LocalTime.of(12, 5, 40, 987654321)); | |
} | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_plus_TemporalAmount_zero() { | |
TemporalAmount period = Period.ZERO; | |
LocalTime t = TEST_12_30_40_987654321.plus(period); | |
assertEquals(t, TEST_12_30_40_987654321); | |
} | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_plus_TemporalAmount_wrap() { | |
- TemporalAmount p = Period.ofHours(1); | |
+ TemporalAmount p = MockSimplePeriod.of(1, HOURS); | |
LocalTime t = LocalTime.of(23, 30).plus(p); | |
assertEquals(t, LocalTime.of(0, 30)); | |
} | |
- @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) | |
+ @Test(expectedExceptions=DateTimeException.class) | |
public void test_plus_TemporalAmount_dateNotAllowed() { | |
TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); | |
TEST_12_30_40_987654321.plus(period); | |
} | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
+ @Test(expectedExceptions=NullPointerException.class) | |
public void test_plus_TemporalAmount_null() { | |
TEST_12_30_40_987654321.plus((TemporalAmount) null); | |
} | |
@@ -1466,55 +1465,41 @@ | |
//----------------------------------------------------------------------- | |
// minus(TemporalAmount) | |
//----------------------------------------------------------------------- | |
- @Test(groups={"tck"}) | |
- public void test_minus_TemporalAmount() { | |
- TemporalAmount p = Period.ofTime(0, 0, 62, 3); | |
- LocalTime t = TEST_12_30_40_987654321.minus(p); | |
- assertEquals(t, LocalTime.of(12, 29, 38, 987654318)); | |
- } | |
- | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_minus_TemporalAmount_positiveHours() { | |
TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.HOURS); | |
LocalTime t = TEST_12_30_40_987654321.minus(period); | |
assertEquals(t, LocalTime.of(5, 30, 40, 987654321)); | |
} | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_minus_TemporalAmount_negativeMinutes() { | |
TemporalAmount period = MockSimplePeriod.of(-25, ChronoUnit.MINUTES); | |
LocalTime t = TEST_12_30_40_987654321.minus(period); | |
assertEquals(t, LocalTime.of(12, 55, 40, 987654321)); | |
} | |
- @Test(groups={"tck"}) | |
- public void test_minus_TemporalAmount_big1() { | |
- TemporalAmount p = Period.ofTime(0, 0, 0, Long.MAX_VALUE); | |
- LocalTime t = TEST_12_30_40_987654321.minus(p); | |
- assertEquals(t, TEST_12_30_40_987654321.minusNanos(Long.MAX_VALUE)); | |
- } | |
- | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_minus_TemporalAmount_zero() { | |
- TemporalAmount p = Period.ZERO; | |
- LocalTime t = TEST_12_30_40_987654321.minus(p); | |
+ TemporalAmount period = Period.ZERO; | |
+ LocalTime t = TEST_12_30_40_987654321.minus(period); | |
assertEquals(t, TEST_12_30_40_987654321); | |
} | |
- @Test(groups={"tck"}) | |
+ @Test | |
public void test_minus_TemporalAmount_wrap() { | |
- TemporalAmount p = Period.ofHours(1); | |
+ TemporalAmount p = MockSimplePeriod.of(1, HOURS); | |
LocalTime t = LocalTime.of(0, 30).minus(p); | |
assertEquals(t, LocalTime.of(23, 30)); | |
} | |
- @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) | |
+ @Test(expectedExceptions=DateTimeException.class) | |
public void test_minus_TemporalAmount_dateNotAllowed() { | |
TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); | |
TEST_12_30_40_987654321.minus(period); | |
} | |
- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
+ @Test(expectedExceptions=NullPointerException.class) | |
public void test_minus_TemporalAmount_null() { | |
TEST_12_30_40_987654321.minus((TemporalAmount) null); | |
} | |
diff --git a/test/java/time/tck/java/time/TCKPeriod.java b/test/java/time/tck/java/time/TCKPeriod.java | |
--- a/test/java/time/tck/java/time/TCKPeriod.java | |
+++ b/test/java/time/tck/java/time/TCKPeriod.java | |
@@ -59,25 +59,16 @@ | |
*/ | |
package tck.java.time; | |
-import static java.time.temporal.ChronoUnit.DAYS; | |
-import static java.time.temporal.ChronoUnit.HALF_DAYS; | |
-import static java.time.temporal.ChronoUnit.HOURS; | |
-import static java.time.temporal.ChronoUnit.MICROS; | |
-import static java.time.temporal.ChronoUnit.MILLIS; | |
-import static java.time.temporal.ChronoUnit.MINUTES; | |
-import static java.time.temporal.ChronoUnit.MONTHS; | |
-import static java.time.temporal.ChronoUnit.NANOS; | |
-import static java.time.temporal.ChronoUnit.SECONDS; | |
-import static java.time.temporal.ChronoUnit.YEARS; | |
import static org.testng.Assert.assertEquals; | |
-import static org.testng.Assert.assertTrue; | |
-import java.time.Duration; | |
+import java.time.DateTimeException; | |
+import java.time.LocalDate; | |
import java.time.Period; | |
-import java.time.DateTimeException; | |
+import java.time.format.DateTimeParseException; | |
import java.time.temporal.ChronoUnit; | |
import java.time.temporal.TemporalUnit; | |
import java.util.List; | |
+import java.util.Locale; | |
import org.testng.annotations.DataProvider; | |
import org.testng.annotations.Test; | |
@@ -89,418 +80,522 @@ | |
public class TCKPeriod extends AbstractTCKTest { | |
//----------------------------------------------------------------------- | |
- // of(int7) | |
- //----------------------------------------------------------------------- | |
@Test | |
- public void factory_of_7ints() { | |
- assertPeriod(Period.of(1, 2, 3, 4, 5, 6, 0), 1, 2, 3, 4, 5, 6, 0); | |
- assertPeriod(Period.of(0, 2, 3, 4, 5, 6, 0), 0, 2, 3, 4, 5, 6, 0); | |
- assertPeriod(Period.of(1, 0, 0, 0, 0, 0, 0), 1, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(0, 0, 0, 0, 0, 0, 0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, -2, -3, -4, -5, -6, 0), -1, -2, -3, -4, -5, -6, 0); | |
+ public void test_serialization() throws Exception { | |
+ assertSerializable(Period.ZERO); | |
+ assertSerializable(Period.ofDays(1)); | |
+ assertSerializable(Period.of(1, 2, 3)); | |
} | |
//----------------------------------------------------------------------- | |
- // ofDate(int3) | |
+ // ofYears(int) | |
//----------------------------------------------------------------------- | |
@Test | |
- public void factory_ofDate_ints() { | |
- assertPeriod(Period.ofDate(1, 2, 3), 1, 2, 3, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDate(0, 2, 3), 0, 2, 3, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDate(1, 0, 0), 1, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDate(0, 0, 0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDate(-1, -2, -3), -1, -2, -3, 0, 0, 0, 0); | |
+ public void factory_ofYears_int() { | |
+ assertPeriod(Period.ofYears(0), 0, 0, 0); | |
+ assertPeriod(Period.ofYears(1), 1, 0, 0); | |
+ assertPeriod(Period.ofYears(234), 234, 0, 0); | |
+ assertPeriod(Period.ofYears(-100), -100, 0, 0); | |
+ assertPeriod(Period.ofYears(Integer.MAX_VALUE), Integer.MAX_VALUE, 0, 0); | |
+ assertPeriod(Period.ofYears(Integer.MIN_VALUE), Integer.MIN_VALUE, 0, 0); | |
} | |
//----------------------------------------------------------------------- | |
- // ofTime(int4) | |
+ // ofMonths(int) | |
//----------------------------------------------------------------------- | |
@Test | |
- public void factory_ofTime_4ints() { | |
- assertPeriod(Period.ofTime(1, 2, 3, 4), 0, 0, 0, 1, 2, 3, 4); | |
- assertPeriod(Period.ofTime(0, 2, 3, 4), 0, 0, 0, 0, 2, 3, 4); | |
- assertPeriod(Period.ofTime(1, 0, 0, 0), 0, 0, 0, 1, 0, 0, 0); | |
- assertPeriod(Period.ofTime(0, 0, 0, 0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofTime(-1, -2, -3, -4), 0, 0, 0, -1, -2, -3, -4); | |
+ public void factory_ofMonths_int() { | |
+ assertPeriod(Period.ofMonths(0), 0, 0, 0); | |
+ assertPeriod(Period.ofMonths(1), 0, 1, 0); | |
+ assertPeriod(Period.ofMonths(234), 0, 234, 0); | |
+ assertPeriod(Period.ofMonths(-100), 0, -100, 0); | |
+ assertPeriod(Period.ofMonths(Integer.MAX_VALUE), 0, Integer.MAX_VALUE, 0); | |
+ assertPeriod(Period.ofMonths(Integer.MIN_VALUE), 0, Integer.MIN_VALUE, 0); | |
} | |
//----------------------------------------------------------------------- | |
- // of(long,TemporalUnit) | |
+ // ofDays(int) | |
//----------------------------------------------------------------------- | |
@Test | |
- public void factory_of_longUnit() { | |
- assertEquals(Period.of(1, YEARS), Period.of(1, YEARS)); | |
- assertEquals(Period.of(2, MONTHS), Period.of(2, MONTHS)); | |
- assertEquals(Period.of(3, DAYS), Period.of(3, DAYS)); | |
+ public void factory_ofDay_int() { | |
+ assertPeriod(Period.ofDays(0), 0, 0, 0); | |
+ assertPeriod(Period.ofDays(1), 0, 0, 1); | |
+ assertPeriod(Period.ofDays(234), 0, 0, 234); | |
+ assertPeriod(Period.ofDays(-100), 0, 0, -100); | |
+ assertPeriod(Period.ofDays(Integer.MAX_VALUE), 0, 0, Integer.MAX_VALUE); | |
+ assertPeriod(Period.ofDays(Integer.MIN_VALUE), 0, 0, Integer.MIN_VALUE); | |
+ } | |
- assertEquals(Period.of(1, HALF_DAYS), Period.of(12, HOURS)); | |
- assertEquals(Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS), Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS)); | |
- assertEquals(Period.of(-1, MINUTES), Period.of(-1, MINUTES)); | |
- assertEquals(Period.of(-2, SECONDS), Period.of(-2, SECONDS)); | |
- assertEquals(Period.of(Integer.MIN_VALUE, NANOS), Period.of(Integer.MIN_VALUE, NANOS)); | |
- assertEquals(Period.of(2, MILLIS), Period.of(2000000, NANOS)); | |
- assertEquals(Period.of(2, MICROS), Period.of(2000, NANOS)); | |
+ //----------------------------------------------------------------------- | |
+ // of(int3) | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void factory_of_ints() { | |
+ assertPeriod(Period.of(1, 2, 3), 1, 2, 3); | |
+ assertPeriod(Period.of(0, 2, 3), 0, 2, 3); | |
+ assertPeriod(Period.of(1, 0, 0), 1, 0, 0); | |
+ assertPeriod(Period.of(0, 0, 0), 0, 0, 0); | |
+ assertPeriod(Period.of(-1, -2, -3), -1, -2, -3); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // parse(String) | |
+ //----------------------------------------------------------------------- | |
+ @DataProvider(name="parseSuccess") | |
+ Object[][] data_factory_parseSuccess() { | |
+ return new Object[][] { | |
+ {"P1Y", Period.ofYears(1)}, | |
+ {"P12Y", Period.ofYears(12)}, | |
+ {"P987654321Y", Period.ofYears(987654321)}, | |
+ {"P+1Y", Period.ofYears(1)}, | |
+ {"P+12Y", Period.ofYears(12)}, | |
+ {"P+987654321Y", Period.ofYears(987654321)}, | |
+ {"P+0Y", Period.ofYears(0)}, | |
+ {"P0Y", Period.ofYears(0)}, | |
+ {"P-0Y", Period.ofYears(0)}, | |
+ {"P-25Y", Period.ofYears(-25)}, | |
+ {"P-987654321Y", Period.ofYears(-987654321)}, | |
+ {"P" + Integer.MAX_VALUE + "Y", Period.ofYears(Integer.MAX_VALUE)}, | |
+ {"P" + Integer.MIN_VALUE + "Y", Period.ofYears(Integer.MIN_VALUE)}, | |
+ | |
+ {"P1M", Period.ofMonths(1)}, | |
+ {"P12M", Period.ofMonths(12)}, | |
+ {"P987654321M", Period.ofMonths(987654321)}, | |
+ {"P+1M", Period.ofMonths(1)}, | |
+ {"P+12M", Period.ofMonths(12)}, | |
+ {"P+987654321M", Period.ofMonths(987654321)}, | |
+ {"P+0M", Period.ofMonths(0)}, | |
+ {"P0M", Period.ofMonths(0)}, | |
+ {"P-0M", Period.ofMonths(0)}, | |
+ {"P-25M", Period.ofMonths(-25)}, | |
+ {"P-987654321M", Period.ofMonths(-987654321)}, | |
+ {"P" + Integer.MAX_VALUE + "M", Period.ofMonths(Integer.MAX_VALUE)}, | |
+ {"P" + Integer.MIN_VALUE + "M", Period.ofMonths(Integer.MIN_VALUE)}, | |
+ | |
+ {"P1D", Period.ofDays(1)}, | |
+ {"P12D", Period.ofDays(12)}, | |
+ {"P987654321D", Period.ofDays(987654321)}, | |
+ {"P+1D", Period.ofDays(1)}, | |
+ {"P+12D", Period.ofDays(12)}, | |
+ {"P+987654321D", Period.ofDays(987654321)}, | |
+ {"P+0D", Period.ofDays(0)}, | |
+ {"P0D", Period.ofDays(0)}, | |
+ {"P-0D", Period.ofDays(0)}, | |
+ {"P-25D", Period.ofDays(-25)}, | |
+ {"P-987654321D", Period.ofDays(-987654321)}, | |
+ {"P" + Integer.MAX_VALUE + "D", Period.ofDays(Integer.MAX_VALUE)}, | |
+ {"P" + Integer.MIN_VALUE + "D", Period.ofDays(Integer.MIN_VALUE)}, | |
+ | |
+ {"P0Y0M0D", Period.of(0, 0, 0)}, | |
+ {"P2Y0M0D", Period.of(2, 0, 0)}, | |
+ {"P0Y3M0D", Period.of(0, 3, 0)}, | |
+ {"P0Y0M4D", Period.of(0, 0, 4)}, | |
+ {"P2Y3M25D", Period.of(2, 3, 25)}, | |
+ {"P-2Y3M25D", Period.of(-2, 3, 25)}, | |
+ {"P2Y-3M25D", Period.of(2, -3, 25)}, | |
+ {"P2Y3M-25D", Period.of(2, 3, -25)}, | |
+ {"P-2Y-3M-25D", Period.of(-2, -3, -25)}, | |
+ }; | |
+ } | |
+ | |
+ @Test(dataProvider="parseSuccess") | |
+ public void factory_parse(String text, Period expected) { | |
+ Period p = Period.parse(text); | |
+ assertEquals(p, expected); | |
+ } | |
+ | |
+ @Test(dataProvider="parseSuccess") | |
+ public void factory_parse_plus(String text, Period expected) { | |
+ Period p = Period.parse("+" + text); | |
+ assertEquals(p, expected); | |
+ } | |
+ | |
+ @Test(dataProvider="parseSuccess") | |
+ public void factory_parse_minus(String text, Period expected) { | |
+ Period p = null; | |
+ try { | |
+ p = Period.parse("-" + text); | |
+ } catch (DateTimeParseException ex) { | |
+ assertEquals(expected.getYears() == Integer.MIN_VALUE || | |
+ expected.getMonths() == Integer.MIN_VALUE || | |
+ expected.getDays() == Integer.MIN_VALUE, true); | |
+ return; | |
+ } | |
+ // not inside try/catch or it breaks test | |
+ assertEquals(p, expected.negated()); | |
+ } | |
+ | |
+ @Test(dataProvider="parseSuccess") | |
+ public void factory_parse_lowerCase(String text, Period expected) { | |
+ Period p = Period.parse(text.toLowerCase(Locale.ENGLISH)); | |
+ assertEquals(p, expected); | |
+ } | |
+ | |
+ @DataProvider(name="parseFailure") | |
+ Object[][] data_parseFailure() { | |
+ return new Object[][] { | |
+ {""}, | |
+ {"PTD"}, | |
+ {"AT0D"}, | |
+ {"PA0D"}, | |
+ {"PT0A"}, | |
+ | |
+ {"PT+D"}, | |
+ {"PT-D"}, | |
+ {"PT.D"}, | |
+ {"PTAD"}, | |
+ | |
+ {"PT+0D"}, | |
+ {"PT-0D"}, | |
+ {"PT+1D"}, | |
+ {"PT-.D"}, | |
+ | |
+ {"P1Y1MT1D"}, | |
+ {"P1YMD"}, | |
+ {"P1Y2Y"}, | |
+ {"PT1M+3S"}, | |
+ | |
+ {"PT1S1"}, | |
+ {"PT1S."}, | |
+ {"PT1SA"}, | |
+ {"PT1M1"}, | |
+ {"PT1M."}, | |
+ {"PT1MA"}, | |
+ | |
+ {"P"+ (((long) Integer.MAX_VALUE) + 1) + "Y"}, | |
+ {"P"+ (((long) Integer.MAX_VALUE) + 1) + "M"}, | |
+ {"P"+ (((long) Integer.MAX_VALUE) + 1) + "D"}, | |
+ {"P"+ (((long) Integer.MIN_VALUE) - 1) + "Y"}, | |
+ {"P"+ (((long) Integer.MIN_VALUE) - 1) + "M"}, | |
+ {"P"+ (((long) Integer.MIN_VALUE) - 1) + "D"}, | |
+ | |
+ {"Rubbish"}, | |
+ }; | |
+ } | |
+ | |
+ @Test(dataProvider="parseFailure", expectedExceptions=DateTimeParseException.class) | |
+ public void factory_parseFailures(String text) { | |
+ try { | |
+ Period.parse(text); | |
+ } catch (DateTimeParseException ex) { | |
+ assertEquals(ex.getParsedString(), text); | |
+ throw ex; | |
+ } | |
+ } | |
+ | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void factory_parse_null() { | |
+ Period.parse(null); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // between(LocalDate,LocalDate) | |
+ //----------------------------------------------------------------------- | |
+ @DataProvider(name="between") | |
+ Object[][] data_between() { | |
+ return new Object[][] { | |
+ {2010, 1, 1, 2010, 1, 1, 0, 0, 0}, | |
+ {2010, 1, 1, 2010, 1, 2, 0, 0, 1}, | |
+ {2010, 1, 1, 2010, 1, 31, 0, 0, 30}, | |
+ {2010, 1, 1, 2010, 2, 1, 0, 1, 0}, | |
+ {2010, 1, 1, 2010, 2, 28, 0, 1, 27}, | |
+ {2010, 1, 1, 2010, 3, 1, 0, 2, 0}, | |
+ {2010, 1, 1, 2010, 12, 31, 0, 11, 30}, | |
+ {2010, 1, 1, 2011, 1, 1, 1, 0, 0}, | |
+ {2010, 1, 1, 2011, 12, 31, 1, 11, 30}, | |
+ {2010, 1, 1, 2012, 1, 1, 2, 0, 0}, | |
+ | |
+ {2010, 1, 10, 2010, 1, 1, 0, 0, -9}, | |
+ {2010, 1, 10, 2010, 1, 2, 0, 0, -8}, | |
+ {2010, 1, 10, 2010, 1, 9, 0, 0, -1}, | |
+ {2010, 1, 10, 2010, 1, 10, 0, 0, 0}, | |
+ {2010, 1, 10, 2010, 1, 11, 0, 0, 1}, | |
+ {2010, 1, 10, 2010, 1, 31, 0, 0, 21}, | |
+ {2010, 1, 10, 2010, 2, 1, 0, 0, 22}, | |
+ {2010, 1, 10, 2010, 2, 9, 0, 0, 30}, | |
+ {2010, 1, 10, 2010, 2, 10, 0, 1, 0}, | |
+ {2010, 1, 10, 2010, 2, 28, 0, 1, 18}, | |
+ {2010, 1, 10, 2010, 3, 1, 0, 1, 19}, | |
+ {2010, 1, 10, 2010, 3, 9, 0, 1, 27}, | |
+ {2010, 1, 10, 2010, 3, 10, 0, 2, 0}, | |
+ {2010, 1, 10, 2010, 12, 31, 0, 11, 21}, | |
+ {2010, 1, 10, 2011, 1, 1, 0, 11, 22}, | |
+ {2010, 1, 10, 2011, 1, 9, 0, 11, 30}, | |
+ {2010, 1, 10, 2011, 1, 10, 1, 0, 0}, | |
+ | |
+ {2010, 3, 30, 2011, 5, 1, 1, 1, 1}, | |
+ {2010, 4, 30, 2011, 5, 1, 1, 0, 1}, | |
+ | |
+ {2010, 2, 28, 2012, 2, 27, 1, 11, 30}, | |
+ {2010, 2, 28, 2012, 2, 28, 2, 0, 0}, | |
+ {2010, 2, 28, 2012, 2, 29, 2, 0, 1}, | |
+ | |
+ {2012, 2, 28, 2014, 2, 27, 1, 11, 30}, | |
+ {2012, 2, 28, 2014, 2, 28, 2, 0, 0}, | |
+ {2012, 2, 28, 2014, 3, 1, 2, 0, 1}, | |
+ | |
+ {2012, 2, 29, 2014, 2, 28, 1, 11, 30}, | |
+ {2012, 2, 29, 2014, 3, 1, 2, 0, 1}, | |
+ {2012, 2, 29, 2014, 3, 2, 2, 0, 2}, | |
+ | |
+ {2012, 2, 29, 2016, 2, 28, 3, 11, 30}, | |
+ {2012, 2, 29, 2016, 2, 29, 4, 0, 0}, | |
+ {2012, 2, 29, 2016, 3, 1, 4, 0, 1}, | |
+ | |
+ {2010, 1, 1, 2009, 12, 31, 0, 0, -1}, | |
+ {2010, 1, 1, 2009, 12, 30, 0, 0, -2}, | |
+ {2010, 1, 1, 2009, 12, 2, 0, 0, -30}, | |
+ {2010, 1, 1, 2009, 12, 1, 0, -1, 0}, | |
+ {2010, 1, 1, 2009, 11, 30, 0, -1, -1}, | |
+ {2010, 1, 1, 2009, 11, 2, 0, -1, -29}, | |
+ {2010, 1, 1, 2009, 11, 1, 0, -2, 0}, | |
+ {2010, 1, 1, 2009, 1, 2, 0, -11, -30}, | |
+ {2010, 1, 1, 2009, 1, 1, -1, 0, 0}, | |
+ | |
+ {2010, 1, 15, 2010, 1, 15, 0, 0, 0}, | |
+ {2010, 1, 15, 2010, 1, 14, 0, 0, -1}, | |
+ {2010, 1, 15, 2010, 1, 1, 0, 0, -14}, | |
+ {2010, 1, 15, 2009, 12, 31, 0, 0, -15}, | |
+ {2010, 1, 15, 2009, 12, 16, 0, 0, -30}, | |
+ {2010, 1, 15, 2009, 12, 15, 0, -1, 0}, | |
+ {2010, 1, 15, 2009, 12, 14, 0, -1, -1}, | |
+ | |
+ {2010, 2, 28, 2009, 3, 1, 0, -11, -27}, | |
+ {2010, 2, 28, 2009, 2, 28, -1, 0, 0}, | |
+ {2010, 2, 28, 2009, 2, 27, -1, 0, -1}, | |
+ | |
+ {2010, 2, 28, 2008, 2, 29, -1, -11, -28}, | |
+ {2010, 2, 28, 2008, 2, 28, -2, 0, 0}, | |
+ {2010, 2, 28, 2008, 2, 27, -2, 0, -1}, | |
+ | |
+ {2012, 2, 29, 2009, 3, 1, -2, -11, -28}, | |
+ {2012, 2, 29, 2009, 2, 28, -3, 0, -1}, | |
+ {2012, 2, 29, 2009, 2, 27, -3, 0, -2}, | |
+ | |
+ {2012, 2, 29, 2008, 3, 1, -3, -11, -28}, | |
+ {2012, 2, 29, 2008, 2, 29, -4, 0, 0}, | |
+ {2012, 2, 29, 2008, 2, 28, -4, 0, -1}, | |
+ }; | |
+ } | |
+ | |
+ @Test(dataProvider="between") | |
+ public void factory_between_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) { | |
+ LocalDate start = LocalDate.of(y1, m1, d1); | |
+ LocalDate end = LocalDate.of(y2, m2, d2); | |
+ Period test = Period.between(start, end); | |
+ assertPeriod(test, ye, me, de); | |
+ //assertEquals(start.plus(test), end); | |
+ } | |
+ | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void factory_between_LocalDate_nullFirst() { | |
+ Period.between((LocalDate) null, LocalDate.of(2010, 1, 1)); | |
+ } | |
+ | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void factory_between_LocalDate_nullSecond() { | |
+ Period.between(LocalDate.of(2010, 1, 1), (LocalDate) null); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // isZero() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_isZero() { | |
+ assertEquals(Period.of(0, 0, 0).isZero(), true); | |
+ assertEquals(Period.of(1, 2, 3).isZero(), false); | |
+ assertEquals(Period.of(1, 0, 0).isZero(), false); | |
+ assertEquals(Period.of(0, 2, 0).isZero(), false); | |
+ assertEquals(Period.of(0, 0, 3).isZero(), false); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // isNegative() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_isPositive() { | |
+ assertEquals(Period.of(0, 0, 0).isNegative(), false); | |
+ assertEquals(Period.of(1, 2, 3).isNegative(), false); | |
+ assertEquals(Period.of(1, 0, 0).isNegative(), false); | |
+ assertEquals(Period.of(0, 2, 0).isNegative(), false); | |
+ assertEquals(Period.of(0, 0, 3).isNegative(), false); | |
+ | |
+ assertEquals(Period.of(-1, -2, -3).isNegative(), true); | |
+ assertEquals(Period.of(-1, -2, 3).isNegative(), true); | |
+ assertEquals(Period.of(1, -2, -3).isNegative(), true); | |
+ assertEquals(Period.of(-1, 2, -3).isNegative(), true); | |
+ assertEquals(Period.of(-1, 2, 3).isNegative(), true); | |
+ assertEquals(Period.of(1, -2, 3).isNegative(), true); | |
+ assertEquals(Period.of(1, 2, -3).isNegative(), true); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // withYears() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_withYears() { | |
+ assertPeriod(Period.of(1, 2, 3).withYears(1), 1, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).withYears(10), 10, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).withYears(-10), -10, 2, 3); | |
+ assertPeriod(Period.of(-1, -2, -3).withYears(10), 10, -2, -3); | |
+ assertPeriod(Period.of(1, 2, 3).withYears(0), 0, 2, 3); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // withMonths() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_withMonths() { | |
+ assertPeriod(Period.of(1, 2, 3).withMonths(2), 1, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).withMonths(10), 1, 10, 3); | |
+ assertPeriod(Period.of(1, 2, 3).withMonths(-10), 1, -10, 3); | |
+ assertPeriod(Period.of(-1, -2, -3).withMonths(10), -1, 10, -3); | |
+ assertPeriod(Period.of(1, 2, 3).withMonths(0), 1, 0, 3); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // withDays() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_withDays() { | |
+ assertPeriod(Period.of(1, 2, 3).withDays(3), 1, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).withDays(10), 1, 2, 10); | |
+ assertPeriod(Period.of(1, 2, 3).withDays(-10), 1, 2, -10); | |
+ assertPeriod(Period.of(-1, -2, -3).withDays(10), -1, -2, 10); | |
+ assertPeriod(Period.of(1, 2, 3).withDays(0), 1, 2, 0); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // plusYears() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_plusYears() { | |
+ assertPeriod(Period.of(1, 2, 3).plusYears(0), 1, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).plusYears(10), 11, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).plusYears(-10), -9, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).plusYears(-1), 0, 2, 3); | |
+ } | |
+ | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_plusYears_overflowTooBig() { | |
+ Period test = Period.ofYears(Integer.MAX_VALUE); | |
+ test.plusYears(1); | |
+ } | |
+ | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_plusYears_overflowTooSmall() { | |
+ Period test = Period.ofYears(Integer.MIN_VALUE); | |
+ test.plusYears(-1); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // plusMonths() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_plusMonths() { | |
+ assertPeriod(Period.of(1, 2, 3).plusMonths(0), 1, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).plusMonths(10), 1, 12, 3); | |
+ assertPeriod(Period.of(1, 2, 3).plusMonths(-10), 1, -8, 3); | |
+ assertPeriod(Period.of(1, 2, 3).plusMonths(-2), 1, 0, 3); | |
+ } | |
+ | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_plusMonths_overflowTooBig() { | |
+ Period test = Period.ofMonths(Integer.MAX_VALUE); | |
+ test.plusMonths(1); | |
+ } | |
+ | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_plusMonths_overflowTooSmall() { | |
+ Period test = Period.ofMonths(Integer.MIN_VALUE); | |
+ test.plusMonths(-1); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // plusDays() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_plusDays() { | |
+ assertPeriod(Period.of(1, 2, 3).plusDays(0), 1, 2, 3); | |
+ assertPeriod(Period.of(1, 2, 3).plusDays(10), 1, 2, 13); | |
+ assertPeriod(Period.of(1, 2, 3).plusDays(-10), 1, 2, -7); | |
+ assertPeriod(Period.of(1, 2, 3).plusDays(-3), 1, 2, 0); | |
+ } | |
+ | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_plusDays_overflowTooBig() { | |
+ Period test = Period.ofDays(Integer.MAX_VALUE); | |
+ test.plusDays(1); | |
+ } | |
+ | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_plusDays_overflowTooSmall() { | |
+ Period test = Period.ofDays(Integer.MIN_VALUE); | |
+ test.plusDays(-1); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // multipliedBy() | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
+ public void test_multipliedBy() { | |
+ Period test = Period.of(1, 2, 3); | |
+ assertPeriod(test.multipliedBy(0), 0, 0, 0); | |
+ assertPeriod(test.multipliedBy(1), 1, 2, 3); | |
+ assertPeriod(test.multipliedBy(2), 2, 4, 6); | |
+ assertPeriod(test.multipliedBy(-3), -3, -6, -9); | |
} | |
@Test | |
- public void factory_of_longUnit_years() { | |
- assertPeriod(Period.of(1, YEARS), 1, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(0, YEARS), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, YEARS), -1, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MAX_VALUE, YEARS), Integer.MAX_VALUE, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MIN_VALUE, YEARS), Integer.MIN_VALUE, 0, 0, 0, 0, 0, 0); | |
+ public void test_multipliedBy_zeroBase() { | |
+ assertPeriod(Period.ZERO.multipliedBy(2), 0, 0, 0); | |
} | |
- @Test | |
- public void factory_of_longUnit_months() { | |
- assertPeriod(Period.of(1, MONTHS), 0, 1, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(0, MONTHS), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, MONTHS), 0, -1, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MAX_VALUE, MONTHS), 0, Integer.MAX_VALUE, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MIN_VALUE, MONTHS), 0, Integer.MIN_VALUE, 0, 0, 0, 0, 0); | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_multipliedBy_overflowTooBig() { | |
+ Period test = Period.ofYears(Integer.MAX_VALUE / 2 + 1); | |
+ test.multipliedBy(2); | |
} | |
- @Test | |
- public void factory_of_longUnit_days() { | |
- assertPeriod(Period.of(1, DAYS), 0, 0, 1, 0, 0, 0, 0); | |
- assertPeriod(Period.of(0, DAYS), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, DAYS), 0, 0, -1, 0, 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MAX_VALUE, DAYS), 0, 0, Integer.MAX_VALUE, 0, 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MIN_VALUE, DAYS), 0, 0, Integer.MIN_VALUE, 0, 0, 0, 0); | |
- } | |
- | |
- @Test | |
- public void factory_of_longUnit_hours() { | |
- assertPeriod(Period.of(1, HOURS), 0, 0, 0, 1, 0, 0, 0); | |
- assertPeriod(Period.of(0, HOURS), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, HOURS), 0, 0, 0, -1, 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS), 0, 0, 0, Integer.MAX_VALUE / (3600 * 8), 0, 0, 0); | |
- assertPeriod(Period.of(Integer.MIN_VALUE / (3600 * 8), HOURS), 0, 0, 0, Integer.MIN_VALUE / (3600 * 8), 0, 0, 0); | |
- } | |
- | |
- @Test | |
- public void factory_of_longUnit_minutes() { | |
- assertPeriod(Period.of(1, MINUTES), 0, 0, 0, 0, 1, 0, 0); | |
- assertPeriod(Period.of(0, MINUTES), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, MINUTES), 0, 0, 0, 0, -1, 0, 0); | |
- int val = Integer.MAX_VALUE / (60 * 8); | |
- assertPeriod(Period.of(val, MINUTES), 0, 0, 0, | |
- (int) (val / 60L), | |
- (int) (val % 60), | |
- 0, 0); | |
- val = Integer.MIN_VALUE / (60 * 8); | |
- assertPeriod(Period.of(val, MINUTES), 0, 0, 0, | |
- (int) (val / 60L), | |
- (int) (val % 60), | |
- 0, 0); | |
- } | |
- | |
- @Test | |
- public void factory_of_longUnit_seconds() { | |
- assertPeriod(Period.of(1, SECONDS), 0, 0, 0, 0, 0, 1, 0); | |
- assertPeriod(Period.of(0, SECONDS), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, SECONDS), 0, 0, 0, 0, 0, -1, 0); | |
- assertPeriod(Period.of(Integer.MAX_VALUE, SECONDS), 0, 0, 0, | |
- (int) (Integer.MAX_VALUE / 3600L), | |
- (int) ((Integer.MAX_VALUE / 60L) % 60), | |
- (int) (Integer.MAX_VALUE % 60), | |
- 0); | |
- assertPeriod(Period.of(Integer.MIN_VALUE, SECONDS), 0, 0, 0, | |
- (int) (Integer.MIN_VALUE / 3600L), | |
- (int) ((Integer.MIN_VALUE / 60L) % 60), | |
- (int) (Integer.MIN_VALUE % 60), | |
- 0); | |
- } | |
- | |
- @Test | |
- public void factory_nanos() { | |
- assertPeriod(Period.of(1, NANOS), 0, 0, 0, 0, 0, 0, 1); | |
- assertPeriod(Period.of(0, NANOS), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.of(-1, NANOS), 0, 0, 0, 0, 0, 0, -1); | |
- assertPeriod(Period.of(Long.MAX_VALUE, NANOS), 0, 0, 0, | |
- (int) (Long.MAX_VALUE / 3600_000_000_000L), | |
- (int) ((Long.MAX_VALUE / 60_000_000_000L) % 60), | |
- (int) ((Long.MAX_VALUE / 1_000_000_000L) % 60), | |
- Long.MAX_VALUE % 1_000_000_000L); | |
- assertPeriod(Period.of(Long.MIN_VALUE, NANOS), 0, 0, 0, | |
- (int) (Long.MIN_VALUE / 3600_000_000_000L), | |
- (int) ((Long.MIN_VALUE / 60_000_000_000L) % 60), | |
- (int) ((Long.MIN_VALUE / 1_000_000_000L) % 60), | |
- Long.MIN_VALUE % 1_000_000_000L); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void factory_of_longUnit_null() { | |
- Period.of(1, null); | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_multipliedBy_overflowTooSmall() { | |
+ Period test = Period.ofYears(Integer.MIN_VALUE / 2 - 1); | |
+ test.multipliedBy(2); | |
} | |
//----------------------------------------------------------------------- | |
+ // negated() | |
+ //----------------------------------------------------------------------- | |
@Test | |
- public void factory_ofYears() { | |
- assertPeriod(Period.ofYears(1), 1, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofYears(0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofYears(-1), -1, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofYears(Integer.MAX_VALUE), Integer.MAX_VALUE, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofYears(Integer.MIN_VALUE), Integer.MIN_VALUE, 0, 0, 0, 0, 0, 0); | |
+ public void test_negated() { | |
+ assertPeriod(Period.of(0, 0, 0).negated(), 0 ,0, 0); | |
+ assertPeriod(Period.of(1, 2, 3).negated(), -1, -2, -3); | |
+ assertPeriod(Period.of(-1, -2, -3).negated(), 1, 2, 3); | |
+ assertPeriod(Period.of(-1, 2, -3).negated(), 1, -2, 3); | |
+ assertPeriod(Period.of(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).negated(), | |
+ -Integer.MAX_VALUE, -Integer.MAX_VALUE, -Integer.MAX_VALUE); | |
} | |
- @Test | |
- public void factory_ofMonths() { | |
- assertPeriod(Period.ofMonths(1), 0, 1, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofMonths(0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofMonths(-1), 0, -1, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofMonths(Integer.MAX_VALUE), 0, Integer.MAX_VALUE, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofMonths(Integer.MIN_VALUE), 0, Integer.MIN_VALUE, 0, 0, 0, 0, 0); | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_negated_overflow_years() { | |
+ Period.ofYears(Integer.MIN_VALUE).negated(); | |
} | |
- @Test | |
- public void factory_ofDays() { | |
- assertPeriod(Period.ofDays(1), 0, 0, 1, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDays(0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDays(-1), 0, 0, -1, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDays(Integer.MAX_VALUE), 0, 0, Integer.MAX_VALUE, 0, 0, 0, 0); | |
- assertPeriod(Period.ofDays(Integer.MIN_VALUE), 0, 0, Integer.MIN_VALUE, 0, 0, 0, 0); | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_negated_overflow_months() { | |
+ Period.ofMonths(Integer.MIN_VALUE).negated(); | |
} | |
- @Test | |
- public void factory_ofHours() { | |
- assertPeriod(Period.ofHours(1), 0, 0, 0, 1, 0, 0, 0); | |
- assertPeriod(Period.ofHours(0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofHours(-1), 0, 0, 0, -1, 0, 0, 0); | |
- assertPeriod(Period.ofHours(Integer.MAX_VALUE / (3600 * 8)), 0, 0, 0, Integer.MAX_VALUE / (3600 * 8), 0, 0, 0); | |
- assertPeriod(Period.ofHours(Integer.MIN_VALUE / (3600 * 8)), 0, 0, 0, Integer.MIN_VALUE / (3600 * 8), 0, 0, 0); | |
- } | |
- | |
- @Test | |
- public void factory_ofMinutes() { | |
- assertPeriod(Period.ofMinutes(1), 0, 0, 0, 0, 1, 0, 0); | |
- assertPeriod(Period.ofMinutes(0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofMinutes(-1), 0, 0, 0, 0, -1, 0, 0); | |
- int val = Integer.MAX_VALUE / (60 * 8); | |
- assertPeriod(Period.ofMinutes(val), 0, 0, 0, | |
- (int) (val / 60L), | |
- (int) (val % 60), | |
- 0, 0); | |
- val = Integer.MIN_VALUE / (60 * 8); | |
- assertPeriod(Period.ofMinutes(val), 0, 0, 0, | |
- (int) (val / 60L), | |
- (int) (val % 60), | |
- 0, 0); | |
- } | |
- | |
- @Test | |
- public void factory_ofSeconds() { | |
- assertPeriod(Period.ofSeconds(1), 0, 0, 0, 0, 0, 1, 0); | |
- assertPeriod(Period.ofSeconds(0), 0, 0, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.ofSeconds(-1), 0, 0, 0, 0, 0, -1, 0); | |
- assertPeriod(Period.ofSeconds(Integer.MAX_VALUE), 0, 0, 0, | |
- (int) (Integer.MAX_VALUE / 3600L), | |
- (int) ((Integer.MAX_VALUE / 60L) % 60), | |
- (int) (Integer.MAX_VALUE % 60), | |
- 0); | |
- assertPeriod(Period.ofSeconds(Integer.MIN_VALUE), 0, 0, 0, | |
- (int) (Integer.MIN_VALUE / 3600L), | |
- (int) ((Integer.MIN_VALUE / 60L) % 60), | |
- (int) (Integer.MIN_VALUE % 60), | |
- 0); | |
+ @Test(expectedExceptions=ArithmeticException.class) | |
+ public void test_negated_overflow_days() { | |
+ Period.ofDays(Integer.MIN_VALUE).negated(); | |
} | |
//----------------------------------------------------------------------- | |
- // of(Duration) | |
+ // normalized() | |
//----------------------------------------------------------------------- | |
- @Test | |
- public void factory_duration() { | |
- assertPeriod(Period.of(Duration.ofSeconds(2, 3)), 0, 0, 0, 0, 0, 2, 3); | |
- assertPeriod(Period.of(Duration.ofSeconds(59, 3)), 0, 0, 0, 0, 0, 59, 3); | |
- assertPeriod(Period.of(Duration.ofSeconds(60, 3)), 0, 0, 0, 0, 1, 0, 3); | |
- assertPeriod(Period.of(Duration.ofSeconds(61, 3)), 0, 0, 0, 0, 1, 1, 3); | |
- assertPeriod(Period.of(Duration.ofSeconds(3599, 3)), 0, 0, 0, 0, 59, 59, 3); | |
- assertPeriod(Period.of(Duration.ofSeconds(3600, 3)), 0, 0, 0, 1, 0, 0, 3); | |
- } | |
- | |
- @Test | |
- public void factory_duration_negative() { | |
- assertPeriod(Period.of(Duration.ofSeconds(-2, 3)), 0, 0, 0, 0, 0, -1, -999999997); | |
- assertPeriod(Period.of(Duration.ofSeconds(-59, 3)), 0, 0, 0, 0, 0, -58, -999999997); | |
- assertPeriod(Period.of(Duration.ofSeconds(-60, 3)), 0, 0, 0, 0, 0, -59, -999999997); | |
- assertPeriod(Period.of(Duration.ofSeconds(-60, -3)), 0, 0, 0, 0, -1, 0, -3); | |
- | |
- assertPeriod(Period.of(Duration.ofSeconds(2, -3)), 0, 0, 0, 0, 0, 1, 999999997); | |
- } | |
- | |
- @Test | |
- public void factory_duration_big() { | |
- Duration dur = Duration.ofSeconds(Integer.MAX_VALUE, 3); | |
- long secs = Integer.MAX_VALUE; | |
- assertPeriod(Period.of(dur), 0, 0, 0, (int) (secs / 3600), (int) ((secs % 3600) / 60), (int) (secs % 60), 3); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void factory_duration_null() { | |
- Period.of((Duration) null); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // withTime(Duration) | |
- //----------------------------------------------------------------------- | |
- @Test | |
- public void test_withTime_duration() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.withTime(Duration.ofSeconds(10)), 1, 2, 3, 0, 0, 10, 0); | |
- } | |
- | |
- @Test | |
- public void test_withTime_duration_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.withTime(Duration.ofNanos(((4 * 60 + 5) * 60 + 6) * 1_000_000_000L + 7)), test); | |
- } | |
- | |
- @Test | |
- public void test_withTime_duration_toZero() { | |
- Period test = Period.of(1, NANOS); | |
- assertEquals(test.withTime(Duration.ZERO), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // normalizedHoursToDays() | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="normalizedHoursToDays") | |
- Object[][] data_normalizedHoursToDays() { | |
- return new Object[][] { | |
- {0, 0, 0, 0}, | |
- {1, 0, 1, 0}, | |
- {-1, 0, -1, 0}, | |
- | |
- {1, 1, 1, 1}, | |
- {1, 23, 1, 23}, | |
- {1, 24, 2, 0}, | |
- {1, 25, 2, 1}, | |
- | |
- {1, -1, 0, 23}, | |
- {1, -23, 0, 1}, | |
- {1, -24, 0, 0}, | |
- {1, -25, 0, -1}, | |
- {1, -47, 0, -23}, | |
- {1, -48, -1, 0}, | |
- {1, -49, -1, -1}, | |
- | |
- {-1, 1, 0, -23}, | |
- {-1, 23, 0, -1}, | |
- {-1, 24, 0, 0}, | |
- {-1, 25, 0, 1}, | |
- {-1, 47, 0, 23}, | |
- {-1, 48, 1, 0}, | |
- {-1, 49, 1, 1}, | |
- | |
- {-1, -1, -1, -1}, | |
- {-1, -23, -1, -23}, | |
- {-1, -24, -2, 0}, | |
- {-1, -25, -2, -1}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="normalizedHoursToDays") | |
- public void test_normalizedHoursToDays(int inputDays, int inputHours, int expectedDays, int expectedHours) { | |
- assertPeriod(Period.of(0, 0, inputDays, inputHours, 0, 0, 0).normalizedHoursToDays(), 0, 0, expectedDays, expectedHours, 0, 0, 0); | |
- } | |
- | |
- @Test(dataProvider="normalizedHoursToDays") | |
- public void test_normalizedHoursToDays_yearsMonthsUnaffected(int inputDays, int inputHours, int expectedDays, int expectedHours) { | |
- assertPeriod(Period.of(12, 6, inputDays, inputHours, 0, 0, 0).normalizedHoursToDays(), 12, 6, expectedDays, expectedHours, 0, 0, 0); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedHoursToDays_min() { | |
- Period base = Period.of(0, 0, Integer.MIN_VALUE, -24, 0, 0, 0); | |
- base.normalizedHoursToDays(); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedHoursToDays_max() { | |
- Period base = Period.of(0, 0, Integer.MAX_VALUE, 24, 0, 0, 0); | |
- base.normalizedHoursToDays(); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // normalizedDaysToHours() | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="normalizedDaysToHours") | |
- Object[][] data_normalizedDaysToHours() { | |
- return new Object[][] { | |
- {0, 0, 0, 0, 0}, | |
- | |
- {1, 0, 0, 24, 0}, | |
- {1, 1, 0, 25, 0}, | |
- {1, 23, 0, 47, 0}, | |
- {1, 24, 0, 48, 0}, | |
- {1, 25, 0, 49, 0}, | |
- {2, 23, 0, 71, 0}, | |
- {2, 24, 0, 72, 0}, | |
- {2, 25, 0, 73, 0}, | |
- | |
- {1, 0, 0, 24, 0}, | |
- {1, -1, 0, 23, 0}, | |
- {1, -23, 0, 1, 0}, | |
- {1, -24, 0, 0, 0}, | |
- {1, -25, 0, -1, 0}, | |
- {2, -23, 0, 25, 0}, | |
- {2, -24, 0, 24, 0}, | |
- {2, -25, 0, 23, 0}, | |
- | |
- {-1, 0, 0, -24, 0}, | |
- {-1, 1, 0, -23, 0}, | |
- {-1, 23, 0, -1, 0}, | |
- {-1, 24, 0, 0, 0}, | |
- {-1, 25, 0, 1, 0}, | |
- {-2, 23, 0, -25, 0}, | |
- {-2, 24, 0, -24, 0}, | |
- {-2, 25, 0, -23, 0}, | |
- | |
- {-1, 0, 0, -24, 0}, | |
- {-1, -1, 0, -25, 0}, | |
- {-1, -23, 0, -47, 0}, | |
- {-1, -24, 0, -48, 0}, | |
- {-1, -25, 0, -49, 0}, | |
- | |
- // minutes | |
- {1, -1, -1, 22, 59}, | |
- {1, -23, -1, 0, 59}, | |
- {1, -24, -1, 0, -1}, | |
- {1, -25, -1, -1, -1}, | |
- {-1, 1, 1, -22, -59}, | |
- {-1, 23, 1, 0, -59}, | |
- {-1, 24, 1, 0, 1}, | |
- {-1, 25, 1, 1, 1}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="normalizedDaysToHours") | |
- public void test_normalizedDaysToHours(int inputDays, int inputHours, int inputMinutes, int expectedHours, int expectedMinutes) { | |
- assertPeriod(Period.of(0, 0, inputDays, inputHours, inputMinutes, 0, 0).normalizedDaysToHours(), 0, 0, 0, expectedHours, expectedMinutes, 0, 0); | |
- } | |
- | |
- @Test(dataProvider="normalizedDaysToHours") | |
- public void test_normalizedDaysToHours_yearsMonthsUnaffected(int inputDays, int inputHours, int inputMinutes, int expectedHours, int expectedMinutes) { | |
- assertPeriod(Period.of(12, 6, inputDays, inputHours, inputMinutes, 0, 0).normalizedDaysToHours(), 12, 6, 0, expectedHours, expectedMinutes, 0, 0); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedDaysToHours_min() { | |
- Period base = Period.of(0, 0, -1_000, -10_000_000, 0, 0, 0); | |
- base.normalizedDaysToHours(); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedDaysToHours_max() { | |
- Period base = Period.of(0, 0, 1_000, 10_000_000, 0, 0, 0); | |
- base.normalizedDaysToHours(); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // normalizedMonthsToYears() | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="normalizedMonthsToYears") | |
- Object[][] data_normalizedMonthsToYears() { | |
+ @DataProvider(name="normalized") | |
+ Object[][] data_normalized() { | |
return new Object[][] { | |
{0, 0, 0, 0}, | |
{1, 0, 1, 0}, | |
@@ -542,160 +637,270 @@ | |
}; | |
} | |
- @Test(dataProvider="normalizedMonthsToYears") | |
- public void test_normalizedMonthsToYears(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { | |
- assertPeriod(Period.ofDate(inputYears, inputMonths, 0).normalizedMonthsToYears(), expectedYears, expectedMonths, 0, 0, 0, 0, 0); | |
+ @Test(dataProvider="normalized") | |
+ public void test_normalized(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { | |
+ assertPeriod(Period.of(inputYears, inputMonths, 0).normalized(), expectedYears, expectedMonths, 0); | |
} | |
- @Test(dataProvider="normalizedMonthsToYears") | |
- public void test_normalizedMonthsToYears_daysTimeUnaffected(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { | |
- assertPeriod(Period.of(inputYears, inputMonths, 5, 12, 30, 0, 0).normalizedMonthsToYears(), expectedYears, expectedMonths, 5, 12, 30, 0, 0); | |
+ @Test(dataProvider="normalized") | |
+ public void test_normalized_daysUnaffected(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { | |
+ assertPeriod(Period.of(inputYears, inputMonths, 5).normalized(), expectedYears, expectedMonths, 5); | |
} | |
@Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedMonthsToYears_min() { | |
- Period base = Period.ofDate(Integer.MIN_VALUE, -12, 0); | |
- base.normalizedMonthsToYears(); | |
+ public void test_normalized_min() { | |
+ Period base = Period.of(Integer.MIN_VALUE, -12, 0); | |
+ base.normalized(); | |
} | |
@Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedMonthsToYears_max() { | |
- Period base = Period.ofDate(Integer.MAX_VALUE, 12, 0); | |
- base.normalizedMonthsToYears(); | |
+ public void test_normalized_max() { | |
+ Period base = Period.of(Integer.MAX_VALUE, 12, 0); | |
+ base.normalized(); | |
} | |
//----------------------------------------------------------------------- | |
- // normalizedYearsToMonths() | |
+ // addTo() | |
//----------------------------------------------------------------------- | |
- @DataProvider(name="normalizedYearsToMonths") | |
- Object[][] data_normalizedYearsToMonths() { | |
+ @DataProvider(name="addTo") | |
+ Object[][] data_addTo() { | |
return new Object[][] { | |
- {0, 0, 0}, | |
- {1, 0, 12}, | |
- {-1, 0, -12}, | |
+ {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, | |
- {1, 1, 13}, | |
- {1, 2, 14}, | |
- {1, 11, 23}, | |
- {1, 12, 24}, | |
- {1, 13, 25}, | |
- {1, 23, 35}, | |
- {1, 24, 36}, | |
- {1, 25, 37}, | |
+ {pymd(1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, | |
+ {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 7, 10)}, | |
+ {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 11)}, | |
- {1, -1, 11}, | |
- {1, -2, 10}, | |
- {1, -11, 1}, | |
- {1, -12, 0}, | |
- {1, -13, -1}, | |
- {1, -23, -11}, | |
- {1, -24, -12}, | |
- {1, -25, -13}, | |
- {1, -35, -23}, | |
- {1, -36, -24}, | |
- {1, -37, -25}, | |
+ {pymd(-1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, | |
+ {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 5, 10)}, | |
+ {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 9)}, | |
- {-1, 1, -11}, | |
- {-1, 11, -1}, | |
- {-1, 12, 0}, | |
- {-1, 13, 1}, | |
- {-1, 23, 11}, | |
- {-1, 24, 12}, | |
- {-1, 25, 13}, | |
+ {pymd(1, 2, 3), date(2012, 6, 27), date(2013, 8, 30)}, | |
+ {pymd(1, 2, 3), date(2012, 6, 28), date(2013, 8, 31)}, | |
+ {pymd(1, 2, 3), date(2012, 6, 29), date(2013, 9, 1)}, | |
+ {pymd(1, 2, 3), date(2012, 6, 30), date(2013, 9, 2)}, | |
+ {pymd(1, 2, 3), date(2012, 7, 1), date(2013, 9, 4)}, | |
- {-1, -1, -13}, | |
- {-1, -11, -23}, | |
- {-1, -12, -24}, | |
- {-1, -13, -25}, | |
+ {pymd(1, 0, 0), date(2011, 2, 28), date(2012, 2, 28)}, | |
+ {pymd(4, 0, 0), date(2011, 2, 28), date(2015, 2, 28)}, | |
+ {pymd(1, 0, 0), date(2012, 2, 29), date(2013, 2, 28)}, | |
+ {pymd(4, 0, 0), date(2012, 2, 29), date(2016, 2, 29)}, | |
+ | |
+ {pymd(1, 1, 0), date(2011, 1, 29), date(2012, 2, 29)}, | |
+ {pymd(1, 2, 0), date(2012, 2, 29), date(2013, 4, 29)}, | |
}; | |
} | |
- @Test(dataProvider="normalizedYearsToMonths") | |
- public void test_normalizedYearsToMonths(int inputYears, int inputMonths, int expectedMonths) { | |
- assertPeriod(Period.ofDate(inputYears, inputMonths, 0).normalizedYearsToMonths(), 0, expectedMonths, 0, 0, 0, 0, 0); | |
+ @Test(dataProvider="addTo") | |
+ public void test_addTo(Period period, LocalDate baseDate, LocalDate expected) { | |
+ assertEquals(period.addTo(baseDate), expected); | |
} | |
- @Test(dataProvider="normalizedYearsToMonths") | |
- public void test_normalizedYearsToMonths_daysTimeUnaffected(int inputYears, int inputMonths, int expectedMonths) { | |
- assertPeriod(Period.of(inputYears, inputMonths, 5, 12, 30, 0, 0).normalizedYearsToMonths(), 0, expectedMonths, 5, 12, 30, 0, 0); | |
+ @Test(dataProvider="addTo") | |
+ public void test_addTo_usingLocalDatePlus(Period period, LocalDate baseDate, LocalDate expected) { | |
+ assertEquals(baseDate.plus(period), expected); | |
} | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedYearsToMonths_min() { | |
- Period base = Period.ofDate(Integer.MIN_VALUE / 12, -12, 0); | |
- base.normalizedYearsToMonths(); | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void test_addTo_nullZero() { | |
+ Period.ZERO.addTo(null); | |
} | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_normalizedYearsToMonths_max() { | |
- Period base = Period.ofDate(Integer.MAX_VALUE / 12, 12, 0); | |
- base.normalizedYearsToMonths(); | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void test_addTo_nullNonZero() { | |
+ Period.ofDays(2).addTo(null); | |
} | |
//----------------------------------------------------------------------- | |
- @Test(groups="{tck}") | |
+ // subtractFrom() | |
+ //----------------------------------------------------------------------- | |
+ @DataProvider(name="subtractFrom") | |
+ Object[][] data_subtractFrom() { | |
+ return new Object[][] { | |
+ {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, | |
+ | |
+ {pymd(1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, | |
+ {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 5, 10)}, | |
+ {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 9)}, | |
+ | |
+ {pymd(-1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, | |
+ {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 7, 10)}, | |
+ {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 11)}, | |
+ | |
+ {pymd(1, 2, 3), date(2012, 8, 30), date(2011, 6, 27)}, | |
+ {pymd(1, 2, 3), date(2012, 8, 31), date(2011, 6, 27)}, | |
+ {pymd(1, 2, 3), date(2012, 9, 1), date(2011, 6, 28)}, | |
+ {pymd(1, 2, 3), date(2012, 9, 2), date(2011, 6, 29)}, | |
+ {pymd(1, 2, 3), date(2012, 9, 3), date(2011, 6, 30)}, | |
+ {pymd(1, 2, 3), date(2012, 9, 4), date(2011, 7, 1)}, | |
+ | |
+ {pymd(1, 0, 0), date(2011, 2, 28), date(2010, 2, 28)}, | |
+ {pymd(4, 0, 0), date(2011, 2, 28), date(2007, 2, 28)}, | |
+ {pymd(1, 0, 0), date(2012, 2, 29), date(2011, 2, 28)}, | |
+ {pymd(4, 0, 0), date(2012, 2, 29), date(2008, 2, 29)}, | |
+ | |
+ {pymd(1, 1, 0), date(2013, 3, 29), date(2012, 2, 29)}, | |
+ {pymd(1, 2, 0), date(2012, 2, 29), date(2010, 12, 29)}, | |
+ }; | |
+ } | |
+ | |
+ @Test(dataProvider="subtractFrom") | |
+ public void test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected) { | |
+ assertEquals(period.subtractFrom(baseDate), expected); | |
+ } | |
+ | |
+ @Test(dataProvider="subtractFrom") | |
+ public void test_subtractFrom_usingLocalDateMinus(Period period, LocalDate baseDate, LocalDate expected) { | |
+ assertEquals(baseDate.minus(period), expected); | |
+ } | |
+ | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void test_subtractFrom_nullZero() { | |
+ Period.ZERO.subtractFrom(null); | |
+ } | |
+ | |
+ @Test(expectedExceptions=NullPointerException.class) | |
+ public void test_subtractFrom_nullNonZero() { | |
+ Period.ofDays(2).subtractFrom(null); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // get units | |
+ //----------------------------------------------------------------------- | |
+ @Test | |
public void test_Period_getUnits() { | |
- Period period = Period.ofDate(2012, 1, 1); | |
+ Period period = Period.of(2012, 1, 1); | |
List<TemporalUnit> units = period.getUnits(); | |
- assertEquals(units.size(), 7, "Period.getUnits should return 7 units"); | |
+ assertEquals(units.size(), 3, "Period.getUnits should return 3 units"); | |
assertEquals(units.get(0), ChronoUnit.YEARS, "Period.getUnits contains ChronoUnit.YEARS"); | |
assertEquals(units.get(1), ChronoUnit.MONTHS, "Period.getUnits contains ChronoUnit.MONTHS"); | |
assertEquals(units.get(2), ChronoUnit.DAYS, "Period.getUnits contains ChronoUnit.DAYS"); | |
- assertEquals(units.get(3), ChronoUnit.HOURS, "Period.getUnits contains ChronoUnit.HOURS"); | |
- assertEquals(units.get(4), ChronoUnit.MINUTES, "Period.getUnits contains ChronoUnit.MINUTES"); | |
- assertEquals(units.get(5), ChronoUnit.SECONDS, "Period.getUnits contains ChronoUnit.SECONDS"); | |
- assertEquals(units.get(6), ChronoUnit.NANOS, "contains ChronoUnit.NANOS"); | |
} | |
@DataProvider(name="GoodTemporalUnit") | |
- Object[][] provider_factory_of_goodTemporalUnit() { | |
+ Object[][] data_goodTemporalUnit() { | |
return new Object[][] { | |
- {0, ChronoUnit.NANOS}, | |
- {0, ChronoUnit.SECONDS}, | |
- {0, ChronoUnit.MINUTES}, | |
- {0, ChronoUnit.HOURS}, | |
- {0, ChronoUnit.DAYS}, | |
- {0, ChronoUnit.MONTHS}, | |
- {0, ChronoUnit.YEARS}, | |
+ {2, ChronoUnit.DAYS}, | |
+ {2, ChronoUnit.MONTHS}, | |
+ {2, ChronoUnit.YEARS}, | |
}; | |
} | |
@Test(dataProvider="GoodTemporalUnit") | |
public void test_good_getUnit(long amount, TemporalUnit unit) { | |
- Period period = Period.of(amount, unit); | |
+ Period period = Period.of(2, 2, 2); | |
long actual = period.get(unit); | |
assertEquals(actual, amount, "Value of unit: " + unit); | |
} | |
@DataProvider(name="BadTemporalUnit") | |
- Object[][] provider_factory_of_badTemporalUnit() { | |
+ Object[][] data_badTemporalUnit() { | |
return new Object[][] { | |
- {0, ChronoUnit.MICROS}, | |
- {0, ChronoUnit.MILLIS}, | |
- {0, ChronoUnit.HALF_DAYS}, | |
- {0, ChronoUnit.DECADES}, | |
- {0, ChronoUnit.CENTURIES}, | |
- {0, ChronoUnit.MILLENNIA}, | |
+ {ChronoUnit.MICROS}, | |
+ {ChronoUnit.MILLIS}, | |
+ {ChronoUnit.HALF_DAYS}, | |
+ {ChronoUnit.DECADES}, | |
+ {ChronoUnit.CENTURIES}, | |
+ {ChronoUnit.MILLENNIA}, | |
}; | |
} | |
@Test(dataProvider="BadTemporalUnit", expectedExceptions=DateTimeException.class) | |
- public void test_bad_getUnit(long amount, TemporalUnit unit) { | |
- Period t = Period.of(amount, unit); | |
- long actual = t.get(unit); | |
+ public void test_bad_getUnit(TemporalUnit unit) { | |
+ Period period = Period.of(2, 2, 2); | |
+ period.get(unit); | |
} | |
//----------------------------------------------------------------------- | |
- private void assertPeriod(Period test, int y, int mo, int d, int h, int mn, int s, long n) { | |
+ // equals() / hashCode() | |
+ //----------------------------------------------------------------------- | |
+ public void test_equals() { | |
+ assertEquals(Period.of(1, 0, 0).equals(Period.ofYears(1)), true); | |
+ assertEquals(Period.of(0, 1, 0).equals(Period.ofMonths(1)), true); | |
+ assertEquals(Period.of(0, 0, 1).equals(Period.ofDays(1)), true); | |
+ assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 3)), true); | |
+ | |
+ assertEquals(Period.ofYears(1).equals(Period.ofYears(1)), true); | |
+ assertEquals(Period.ofYears(1).equals(Period.ofYears(2)), false); | |
+ | |
+ assertEquals(Period.ofMonths(1).equals(Period.ofMonths(1)), true); | |
+ assertEquals(Period.ofMonths(1).equals(Period.ofMonths(2)), false); | |
+ | |
+ assertEquals(Period.ofDays(1).equals(Period.ofDays(1)), true); | |
+ assertEquals(Period.ofDays(1).equals(Period.ofDays(2)), false); | |
+ | |
+ assertEquals(Period.of(1, 2, 3).equals(Period.of(0, 2, 3)), false); | |
+ assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 0, 3)), false); | |
+ assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 0)), false); | |
+ } | |
+ | |
+ public void test_equals_self() { | |
+ Period test = Period.of(1, 2, 3); | |
+ assertEquals(test.equals(test), true); | |
+ } | |
+ | |
+ public void test_equals_null() { | |
+ Period test = Period.of(1, 2, 3); | |
+ assertEquals(test.equals(null), false); | |
+ } | |
+ | |
+ public void test_equals_otherClass() { | |
+ Period test = Period.of(1, 2, 3); | |
+ assertEquals(test.equals(""), false); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ public void test_hashCode() { | |
+ Period test5 = Period.ofDays(5); | |
+ Period test6 = Period.ofDays(6); | |
+ Period test5M = Period.ofMonths(5); | |
+ Period test5Y = Period.ofYears(5); | |
+ assertEquals(test5.hashCode() == test5.hashCode(), true); | |
+ assertEquals(test5.hashCode() == test6.hashCode(), false); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ // toString() | |
+ //----------------------------------------------------------------------- | |
+ @DataProvider(name="toStringAndParse") | |
+ Object[][] data_toString() { | |
+ return new Object[][] { | |
+ {Period.ZERO, "P0D"}, | |
+ {Period.ofDays(0), "P0D"}, | |
+ {Period.ofYears(1), "P1Y"}, | |
+ {Period.ofMonths(1), "P1M"}, | |
+ {Period.ofDays(1), "P1D"}, | |
+ {Period.of(1, 2, 0), "P1Y2M"}, | |
+ {Period.of(0, 2, 3), "P2M3D"}, | |
+ {Period.of(1, 2, 3), "P1Y2M3D"}, | |
+ }; | |
+ } | |
+ | |
+ @Test(dataProvider="toStringAndParse") | |
+ public void test_toString(Period input, String expected) { | |
+ assertEquals(input.toString(), expected); | |
+ } | |
+ | |
+ @Test(dataProvider="toStringAndParse") | |
+ public void test_parse(Period test, String expected) { | |
+ assertEquals(Period.parse(expected), test); | |
+ } | |
+ | |
+ //----------------------------------------------------------------------- | |
+ private void assertPeriod(Period test, int y, int m, int d) { | |
assertEquals(test.getYears(), y, "years"); | |
- assertEquals(test.getMonths(), mo, "months"); | |
+ assertEquals(test.getMonths(), m, "months"); | |
assertEquals(test.getDays(), d, "days"); | |
- assertEquals(test.getHours(), h, "hours"); | |
- assertEquals(test.getMinutes(), mn, "mins"); | |
- assertEquals(test.getSeconds(), s, "secs"); | |
- assertEquals(test.getNanos(), n, "nanos"); | |
- assertEquals(test.getTimeNanos(), (((h * 60L + mn) * 60 + s) * 1_000_000_000L + n), "total nanos"); | |
+ assertEquals(test.toTotalMonths(), y * 12L + m, "totalMonths"); | |
+ } | |
+ | |
+ private static Period pymd(int y, int m, int d) { | |
+ return Period.of(y, m, d); | |
+ } | |
+ | |
+ private static LocalDate date(int y, int m, int d) { | |
+ return LocalDate.of(y, m, d); | |
} | |
} | |
diff --git a/test/java/time/tck/java/time/TCKZonedDateTime.java b/test/java/time/tck/java/time/TCKZonedDateTime.java | |
--- a/test/java/time/tck/java/time/TCKZonedDateTime.java | |
+++ b/test/java/time/tck/java/time/TCKZonedDateTime.java | |
@@ -60,7 +60,6 @@ | |
package tck.java.time; | |
import java.time.*; | |
-import test.java.time.MockSimplePeriod; | |
import static java.time.Month.JANUARY; | |
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; | |
@@ -1412,25 +1411,25 @@ | |
} | |
//----------------------------------------------------------------------- | |
- // plus(adjuster) | |
+ // plus(TemporalAmount) | |
//----------------------------------------------------------------------- | |
@Test(groups={"tck"}, dataProvider="plusDays") | |
- public void test_plus_adjuster_Period_days(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
- assertEquals(base.plus(Period.of(amount, DAYS)), expected); | |
+ public void test_plus_TemporalAmount_Period_days(ZonedDateTime base, int amount, ZonedDateTime expected) { | |
+ assertEquals(base.plus(Period.ofDays(amount)), expected); | |
} | |
@Test(groups={"tck"}, dataProvider="plusTime") | |
- public void test_plus_adjuster_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
- assertEquals(base.plus(Period.of(amount, HOURS)), expected); | |
+ public void test_plus_TemporalAmount_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
+ assertEquals(base.plus(MockSimplePeriod.of(amount, HOURS)), expected); | |
} | |
@Test(groups={"tck"}, dataProvider="plusTime") | |
- public void test_plus_adjuster_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
+ public void test_plus_TemporalAmount_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
assertEquals(base.plus(Duration.ofHours(amount)), expected); | |
} | |
@Test(groups={"tck"}) | |
- public void test_plus_adjuster() { | |
+ public void test_plus_TemporalAmount() { | |
MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); | |
ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); | |
ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2009, 1, 1, 12, 30, 59, 500), ZONE_0100); | |
@@ -1438,7 +1437,7 @@ | |
} | |
@Test(groups={"tck"}) | |
- public void test_plus_adjuster_Duration() { | |
+ public void test_plus_TemporalAmount_Duration() { | |
Duration duration = Duration.ofSeconds(4L * 60 * 60 + 5L * 60 + 6L); | |
ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); | |
ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 16, 36, 5, 500), ZONE_0100); | |
@@ -1446,19 +1445,19 @@ | |
} | |
@Test(groups={"tck"}) | |
- public void test_plus_adjuster_Period_zero() { | |
+ public void test_plus_TemporalAmount_Period_zero() { | |
ZonedDateTime t = TEST_DATE_TIME.plus(MockSimplePeriod.ZERO_DAYS); | |
assertEquals(t, TEST_DATE_TIME); | |
} | |
@Test(groups={"tck"}) | |
- public void test_plus_adjuster_Duration_zero() { | |
+ public void test_plus_TemporalAmount_Duration_zero() { | |
ZonedDateTime t = TEST_DATE_TIME.plus(Duration.ZERO); | |
assertEquals(t, TEST_DATE_TIME); | |
} | |
@Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_plus_adjuster_null() { | |
+ public void test_plus_TemporalAmount_null() { | |
TEST_DATE_TIME.plus((TemporalAmount) null); | |
} | |
@@ -1617,25 +1616,25 @@ | |
} | |
//----------------------------------------------------------------------- | |
- // minus(adjuster) | |
+ // minus(TemporalAmount) | |
//----------------------------------------------------------------------- | |
@Test(groups={"tck"}, dataProvider="plusDays") | |
- public void test_minus_adjuster_Period_days(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
- assertEquals(base.minus(Period.of(-amount, DAYS)), expected); | |
+ public void test_minus_TemporalAmount_Period_days(ZonedDateTime base, int amount, ZonedDateTime expected) { | |
+ assertEquals(base.minus(Period.ofDays(-amount)), expected); | |
} | |
@Test(groups={"tck"}, dataProvider="plusTime") | |
- public void test_minus_adjuster_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
- assertEquals(base.minus(Period.of(-amount, HOURS)), expected); | |
+ public void test_minus_TemporalAmount_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
+ assertEquals(base.minus(MockSimplePeriod.of(-amount, HOURS)), expected); | |
} | |
@Test(groups={"tck"}, dataProvider="plusTime") | |
- public void test_minus_adjuster_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
+ public void test_minus_TemporalAmount_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { | |
assertEquals(base.minus(Duration.ofHours(-amount)), expected); | |
} | |
@Test(groups={"tck"}) | |
- public void test_minus_adjuster() { | |
+ public void test_minus_TemporalAmount() { | |
MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); | |
ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); | |
ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2007, 11, 1, 12, 30, 59, 500), ZONE_0100); | |
@@ -1643,7 +1642,7 @@ | |
} | |
@Test(groups={"tck"}) | |
- public void test_minus_adjuster_Duration() { | |
+ public void test_minus_TemporalAmount_Duration() { | |
Duration duration = Duration.ofSeconds(4L * 60 * 60 + 5L * 60 + 6L); | |
ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); | |
ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 8, 25, 53, 500), ZONE_0100); | |
@@ -1651,19 +1650,19 @@ | |
} | |
@Test(groups={"tck"}) | |
- public void test_minus_adjuster_Period_zero() { | |
+ public void test_minus_TemporalAmount_Period_zero() { | |
ZonedDateTime t = TEST_DATE_TIME.minus(MockSimplePeriod.ZERO_DAYS); | |
assertEquals(t, TEST_DATE_TIME); | |
} | |
@Test(groups={"tck"}) | |
- public void test_minus_adjuster_Duration_zero() { | |
+ public void test_minus_TemporalAmount_Duration_zero() { | |
ZonedDateTime t = TEST_DATE_TIME.minus(Duration.ZERO); | |
assertEquals(t, TEST_DATE_TIME); | |
} | |
@Test(expectedExceptions=NullPointerException.class, groups={"tck"}) | |
- public void test_minus_adjuster_null() { | |
+ public void test_minus_TemporalAmount_null() { | |
TEST_DATE_TIME.minus((TemporalAmount) null); | |
} | |
diff --git a/test/java/time/test/java/time/TestDuration.java b/test/java/time/test/java/time/TestDuration.java | |
--- a/test/java/time/test/java/time/TestDuration.java | |
+++ b/test/java/time/test/java/time/TestDuration.java | |
@@ -218,18 +218,12 @@ | |
Duration b = durations[j]; | |
if (i < j) { | |
assertEquals(a.compareTo(b)< 0, true, a + " <=> " + b); | |
- assertEquals(a.isLessThan(b), true, a + " <=> " + b); | |
- assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); | |
assertEquals(a.equals(b), false, a + " <=> " + b); | |
} else if (i > j) { | |
assertEquals(a.compareTo(b) > 0, true, a + " <=> " + b); | |
- assertEquals(a.isLessThan(b), false, a + " <=> " + b); | |
- assertEquals(a.isGreaterThan(b), true, a + " <=> " + b); | |
assertEquals(a.equals(b), false, a + " <=> " + b); | |
} else { | |
assertEquals(a.compareTo(b), 0, a + " <=> " + b); | |
- assertEquals(a.isLessThan(b), false, a + " <=> " + b); | |
- assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); | |
assertEquals(a.equals(b), true, a + " <=> " + b); | |
} | |
} | |
diff --git a/test/java/time/test/java/time/TestPeriod.java b/test/java/time/test/java/time/TestPeriod.java | |
--- a/test/java/time/test/java/time/TestPeriod.java | |
+++ b/test/java/time/test/java/time/TestPeriod.java | |
@@ -59,37 +59,11 @@ | |
*/ | |
package test.java.time; | |
-import static java.time.temporal.ChronoUnit.DAYS; | |
-import static java.time.temporal.ChronoUnit.HALF_DAYS; | |
-import static java.time.temporal.ChronoUnit.HOURS; | |
-import static java.time.temporal.ChronoUnit.MICROS; | |
-import static java.time.temporal.ChronoUnit.MILLIS; | |
-import static java.time.temporal.ChronoUnit.MINUTES; | |
-import static java.time.temporal.ChronoUnit.MONTHS; | |
-import static java.time.temporal.ChronoUnit.NANOS; | |
-import static java.time.temporal.ChronoUnit.SECONDS; | |
-import static java.time.temporal.ChronoUnit.YEARS; | |
import static org.testng.Assert.assertEquals; | |
import static org.testng.Assert.assertSame; | |
-import static org.testng.Assert.assertTrue; | |
-import java.io.ByteArrayInputStream; | |
-import java.io.ByteArrayOutputStream; | |
-import java.io.ObjectInputStream; | |
-import java.io.ObjectOutputStream; | |
-import java.io.Serializable; | |
+import java.time.Period; | |
-import java.time.DateTimeException; | |
-import java.time.Duration; | |
-import java.time.LocalDate; | |
-import java.time.LocalTime; | |
-import java.time.Month; | |
-import java.time.OffsetTime; | |
-import java.time.Period; | |
-import java.time.YearMonth; | |
-import java.time.ZoneOffset; | |
- | |
-import org.testng.annotations.DataProvider; | |
import org.testng.annotations.Test; | |
/** | |
@@ -98,39 +72,6 @@ | |
@Test | |
public class TestPeriod extends AbstractTest { | |
- //----------------------------------------------------------------------- | |
- // basics | |
- //----------------------------------------------------------------------- | |
- public void test_interfaces() { | |
- assertTrue(Serializable.class.isAssignableFrom(Period.class)); | |
- } | |
- | |
- @DataProvider(name="serialization") | |
- Object[][] data_serialization() { | |
- return new Object[][] { | |
- {Period.ZERO}, | |
- {Period.of(0, DAYS)}, | |
- {Period.of(1, DAYS)}, | |
- {Period.of(1, 2, 3, 4, 5, 6, 0)}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="serialization") | |
- public void test_serialization(Period period) throws Exception { | |
- ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
- ObjectOutputStream oos = new ObjectOutputStream(baos); | |
- oos.writeObject(period); | |
- oos.close(); | |
- | |
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream( | |
- baos.toByteArray())); | |
- if (period.isZero()) { | |
- assertSame(ois.readObject(), period); | |
- } else { | |
- assertEquals(ois.readObject(), period); | |
- } | |
- } | |
- | |
@Test | |
public void test_immutable() { | |
assertImmutable(Period.class); | |
@@ -144,1282 +85,21 @@ | |
assertSame(Period.ofYears(0), Period.ZERO); | |
assertSame(Period.ofMonths(0), Period.ZERO); | |
assertSame(Period.ofDays(0), Period.ZERO); | |
- assertSame(Period.ofHours(0), Period.ZERO); | |
- assertSame(Period.ofMinutes(0), Period.ZERO); | |
- assertSame(Period.ofSeconds(0), Period.ZERO); | |
- assertSame(Period.of(0, 0, 0, 0, 0, 0, 0), Period.ZERO); | |
- assertSame(Period.ofDate(0, 0, 0), Period.ZERO); | |
- assertSame(Period.ofTime(0, 0, 0, 0), Period.ZERO); | |
- assertSame(Period.of(0, YEARS), Period.ZERO); | |
- assertSame(Period.of(0, MONTHS), Period.ZERO); | |
- assertSame(Period.of(0, DAYS), Period.ZERO); | |
- assertSame(Period.of(0, HOURS), Period.ZERO); | |
- assertSame(Period.of(0, MINUTES), Period.ZERO); | |
- assertSame(Period.of(0, SECONDS), Period.ZERO); | |
- assertSame(Period.of(0, NANOS), Period.ZERO); | |
+ assertSame(Period.of(0, 0, 0), Period.ZERO); | |
} | |
//----------------------------------------------------------------------- | |
- // between | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="betweenDates") | |
- Object[][] data_betweenDates() { | |
- return new Object[][] { | |
- {2010, 1, 1, 2010, 1, 1, 0, 0, 0}, | |
- {2010, 1, 1, 2010, 1, 2, 0, 0, 1}, | |
- {2010, 1, 1, 2010, 2, 1, 0, 1, 0}, | |
- {2010, 1, 1, 2010, 2, 2, 0, 1, 1}, | |
- {2010, 1, 1, 2011, 1, 1, 1, 0, 0}, | |
- | |
- {2010, 6, 12, 2010, 1, 1, 0, -5, -11}, | |
- {2010, 6, 12, 2010, 1, 2, 0, -5, -10}, | |
- {2010, 6, 12, 2010, 2, 1, 0, -4, -11}, | |
- {2010, 6, 12, 2010, 9, 24, 0, 3, 12}, | |
- | |
- {2010, 6, 12, 2009, 1, 1, -1, -5, -11}, | |
- {2010, 6, 12, 2009, 1, 2, -1, -5, -10}, | |
- {2010, 6, 12, 2009, 2, 1, -1, -4, -11}, | |
- {2010, 6, 12, 2009, 9, 24, 0, -9, 12}, | |
- | |
- {2010, 6, 12, 2008, 1, 1, -2, -5, -11}, | |
- {2010, 6, 12, 2008, 1, 2, -2, -5, -10}, | |
- {2010, 6, 12, 2008, 2, 1, -2, -4, -11}, | |
- {2010, 6, 12, 2008, 9, 24, -1, -9, 12}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="betweenDates") | |
- public void factory_between_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) { | |
- LocalDate start = LocalDate.of(y1, m1, d1); | |
- LocalDate end = LocalDate.of(y2, m2, d2); | |
- Period test = Period.between(start, end); | |
- assertPeriod(test, ye, me, de, 0, 0, 0, 0); | |
- //assertEquals(start.plus(test), end); | |
- } | |
- | |
- @DataProvider(name="betweenTimes") | |
- Object[][] data_betweenTimes() { | |
- return new Object[][] { | |
- {12, 30, 40, 12, 30, 45, 0, 0, 5}, | |
- {12, 30, 40, 12, 35, 40, 0, 5, 0}, | |
- {12, 30, 40, 13, 30, 40, 1, 0, 0}, | |
- | |
- {12, 30, 40, 12, 30, 35, 0, 0, -5}, | |
- {12, 30, 40, 12, 25, 40, 0, -5, 0}, | |
- {12, 30, 40, 11, 30, 40, -1, 0, 0}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="betweenTimes") | |
- public void factory_between_LocalTime(int h1, int m1, int s1, int h2, int m2, int s2, int he, int me, int se) { | |
- LocalTime start = LocalTime.of(h1, m1, s1); | |
- LocalTime end = LocalTime.of(h2, m2, s2); | |
- Period test = Period.between(start, end); | |
- assertPeriod(test, 0, 0, 0, he, me, se, 0); | |
- } | |
- | |
- @Test(dataProvider="betweenTimes") | |
- public void factory_between_OffsetTime(int h1, int m1, int s1, int h2, int m2, int s2, int he, int me, int se) { | |
- OffsetTime start = OffsetTime.of(LocalTime.of(h1, m1, s1), ZoneOffset.ofHours(1)); | |
- OffsetTime end = OffsetTime.of(LocalTime.of(h2, m2, s2), ZoneOffset.ofHours(1)); | |
- Period test = Period.between(start, end); | |
- assertPeriod(test, 0, 0, 0, he, me, se, 0); | |
- } | |
- | |
- public void factory_between_YearMonth() { | |
- assertPeriod(Period.between(YearMonth.of(2012, 6), YearMonth.of(2013, 7)), 1, 1, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.between(YearMonth.of(2012, 6), YearMonth.of(2013, 3)), 0, 9, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.between(YearMonth.of(2012, 6), YearMonth.of(2011, 7)), 0, -11, 0, 0, 0, 0, 0); | |
- } | |
- | |
- public void factory_between_Month() { | |
- assertPeriod(Period.between(Month.FEBRUARY, Month.MAY), 0, 3, 0, 0, 0, 0, 0); | |
- assertPeriod(Period.between(Month.NOVEMBER, Month.MAY), 0, -6, 0, 0, 0, 0, 0); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // betweenIso | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="betweenIso") | |
- Object[][] data_betweenIso() { | |
- return new Object[][] { | |
- {2010, 1, 1, 2010, 1, 1, 0, 0, 0}, | |
- {2010, 1, 1, 2010, 1, 2, 0, 0, 1}, | |
- {2010, 1, 1, 2010, 1, 31, 0, 0, 30}, | |
- {2010, 1, 1, 2010, 2, 1, 0, 1, 0}, | |
- {2010, 1, 1, 2010, 2, 28, 0, 1, 27}, | |
- {2010, 1, 1, 2010, 3, 1, 0, 2, 0}, | |
- {2010, 1, 1, 2010, 12, 31, 0, 11, 30}, | |
- {2010, 1, 1, 2011, 1, 1, 1, 0, 0}, | |
- {2010, 1, 1, 2011, 12, 31, 1, 11, 30}, | |
- {2010, 1, 1, 2012, 1, 1, 2, 0, 0}, | |
- | |
- {2010, 1, 10, 2010, 1, 1, 0, 0, -9}, | |
- {2010, 1, 10, 2010, 1, 2, 0, 0, -8}, | |
- {2010, 1, 10, 2010, 1, 9, 0, 0, -1}, | |
- {2010, 1, 10, 2010, 1, 10, 0, 0, 0}, | |
- {2010, 1, 10, 2010, 1, 11, 0, 0, 1}, | |
- {2010, 1, 10, 2010, 1, 31, 0, 0, 21}, | |
- {2010, 1, 10, 2010, 2, 1, 0, 0, 22}, | |
- {2010, 1, 10, 2010, 2, 9, 0, 0, 30}, | |
- {2010, 1, 10, 2010, 2, 10, 0, 1, 0}, | |
- {2010, 1, 10, 2010, 2, 28, 0, 1, 18}, | |
- {2010, 1, 10, 2010, 3, 1, 0, 1, 19}, | |
- {2010, 1, 10, 2010, 3, 9, 0, 1, 27}, | |
- {2010, 1, 10, 2010, 3, 10, 0, 2, 0}, | |
- {2010, 1, 10, 2010, 12, 31, 0, 11, 21}, | |
- {2010, 1, 10, 2011, 1, 1, 0, 11, 22}, | |
- {2010, 1, 10, 2011, 1, 9, 0, 11, 30}, | |
- {2010, 1, 10, 2011, 1, 10, 1, 0, 0}, | |
- | |
- {2010, 3, 30, 2011, 5, 1, 1, 1, 1}, | |
- {2010, 4, 30, 2011, 5, 1, 1, 0, 1}, | |
- | |
- {2010, 2, 28, 2012, 2, 27, 1, 11, 30}, | |
- {2010, 2, 28, 2012, 2, 28, 2, 0, 0}, | |
- {2010, 2, 28, 2012, 2, 29, 2, 0, 1}, | |
- | |
- {2012, 2, 28, 2014, 2, 27, 1, 11, 30}, | |
- {2012, 2, 28, 2014, 2, 28, 2, 0, 0}, | |
- {2012, 2, 28, 2014, 3, 1, 2, 0, 1}, | |
- | |
- {2012, 2, 29, 2014, 2, 28, 1, 11, 30}, | |
- {2012, 2, 29, 2014, 3, 1, 2, 0, 1}, | |
- {2012, 2, 29, 2014, 3, 2, 2, 0, 2}, | |
- | |
- {2012, 2, 29, 2016, 2, 28, 3, 11, 30}, | |
- {2012, 2, 29, 2016, 2, 29, 4, 0, 0}, | |
- {2012, 2, 29, 2016, 3, 1, 4, 0, 1}, | |
- | |
- {2010, 1, 1, 2009, 12, 31, 0, 0, -1}, | |
- {2010, 1, 1, 2009, 12, 30, 0, 0, -2}, | |
- {2010, 1, 1, 2009, 12, 2, 0, 0, -30}, | |
- {2010, 1, 1, 2009, 12, 1, 0, -1, 0}, | |
- {2010, 1, 1, 2009, 11, 30, 0, -1, -1}, | |
- {2010, 1, 1, 2009, 11, 2, 0, -1, -29}, | |
- {2010, 1, 1, 2009, 11, 1, 0, -2, 0}, | |
- {2010, 1, 1, 2009, 1, 2, 0, -11, -30}, | |
- {2010, 1, 1, 2009, 1, 1, -1, 0, 0}, | |
- | |
- {2010, 1, 15, 2010, 1, 15, 0, 0, 0}, | |
- {2010, 1, 15, 2010, 1, 14, 0, 0, -1}, | |
- {2010, 1, 15, 2010, 1, 1, 0, 0, -14}, | |
- {2010, 1, 15, 2009, 12, 31, 0, 0, -15}, | |
- {2010, 1, 15, 2009, 12, 16, 0, 0, -30}, | |
- {2010, 1, 15, 2009, 12, 15, 0, -1, 0}, | |
- {2010, 1, 15, 2009, 12, 14, 0, -1, -1}, | |
- | |
- {2010, 2, 28, 2009, 3, 1, 0, -11, -27}, | |
- {2010, 2, 28, 2009, 2, 28, -1, 0, 0}, | |
- {2010, 2, 28, 2009, 2, 27, -1, 0, -1}, | |
- | |
- {2010, 2, 28, 2008, 2, 29, -1, -11, -28}, | |
- {2010, 2, 28, 2008, 2, 28, -2, 0, 0}, | |
- {2010, 2, 28, 2008, 2, 27, -2, 0, -1}, | |
- | |
- {2012, 2, 29, 2009, 3, 1, -2, -11, -28}, | |
- {2012, 2, 29, 2009, 2, 28, -3, 0, -1}, | |
- {2012, 2, 29, 2009, 2, 27, -3, 0, -2}, | |
- | |
- {2012, 2, 29, 2008, 3, 1, -3, -11, -28}, | |
- {2012, 2, 29, 2008, 2, 29, -4, 0, 0}, | |
- {2012, 2, 29, 2008, 2, 28, -4, 0, -1}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="betweenIso") | |
- public void factory_betweenIso_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) { | |
- LocalDate start = LocalDate.of(y1, m1, d1); | |
- LocalDate end = LocalDate.of(y2, m2, d2); | |
- Period test = Period.betweenIso(start, end); | |
- assertPeriod(test, ye, me, de, 0, 0, 0, 0); | |
- //assertEquals(start.plus(test), end); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void factory_betweenIso_LocalDate_nullFirst() { | |
- Period.betweenIso((LocalDate) null, LocalDate.of(2010, 1, 1)); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void factory_betweenIso_LocalDate_nullSecond() { | |
- Period.betweenIso(LocalDate.of(2010, 1, 1), (LocalDate) null); | |
- } | |
- | |
- //------------------------------------------------------------------------- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void factory_betweenIso_LocalTime_nullFirst() { | |
- Period.betweenIso((LocalTime) null, LocalTime.of(12, 30)); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void factory_betweenIso_LocalTime_nullSecond() { | |
- Period.betweenIso(LocalTime.of(12, 30), (LocalTime) null); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // parse() | |
- //----------------------------------------------------------------------- | |
- @Test(dataProvider="toStringAndParse") | |
- public void test_parse(Period test, String expected) { | |
- assertEquals(test, Period.parse(expected)); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void test_parse_nullText() { | |
- Period.parse((String) null); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // isZero() | |
- //----------------------------------------------------------------------- | |
- public void test_isZero() { | |
- assertEquals(Period.of(1, 2, 3, 4, 5, 6, 7).isZero(), false); | |
- assertEquals(Period.of(1, 2, 3, 0, 0, 0, 0).isZero(), false); | |
- assertEquals(Period.of(0, 0, 0, 4, 5, 6, 7).isZero(), false); | |
- assertEquals(Period.of(1, 0, 0, 0, 0, 0, 0).isZero(), false); | |
- assertEquals(Period.of(0, 2, 0, 0, 0, 0, 0).isZero(), false); | |
- assertEquals(Period.of(0, 0, 3, 0, 0, 0, 0).isZero(), false); | |
- assertEquals(Period.of(0, 0, 0, 4, 0, 0, 0).isZero(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, 5, 0, 0).isZero(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 6, 0).isZero(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 0, 7).isZero(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 0, 0).isZero(), true); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // isPositive() | |
- //----------------------------------------------------------------------- | |
- public void test_isPositive() { | |
- assertEquals(Period.of(1, 2, 3, 4, 5, 6, 7).isPositive(), true); | |
- assertEquals(Period.of(1, 2, 3, 0, 0, 0, 0).isPositive(), true); | |
- assertEquals(Period.of(0, 0, 0, 4, 5, 6, 7).isPositive(), true); | |
- assertEquals(Period.of(1, 0, 0, 0, 0, 0, 0).isPositive(), true); | |
- assertEquals(Period.of(0, 2, 0, 0, 0, 0, 0).isPositive(), true); | |
- assertEquals(Period.of(0, 0, 3, 0, 0, 0, 0).isPositive(), true); | |
- assertEquals(Period.of(0, 0, 0, 4, 0, 0, 0).isPositive(), true); | |
- assertEquals(Period.of(0, 0, 0, 0, 5, 0, 0).isPositive(), true); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 6, 0).isPositive(), true); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 0, 7).isPositive(), true); | |
- assertEquals(Period.of(-1, -2, -3, -4, -5, -6, -7).isPositive(), false); | |
- assertEquals(Period.of(-1, -2, 3, 4, -5, -6, -7).isPositive(), false); | |
- assertEquals(Period.of(-1, 0, 0, 0, 0, 0, 0).isPositive(), false); | |
- assertEquals(Period.of(0, -2, 0, 0, 0, 0, 0).isPositive(), false); | |
- assertEquals(Period.of(0, 0, -3, 0, 0, 0, 0).isPositive(), false); | |
- assertEquals(Period.of(0, 0, 0, -4, 0, 0, 0).isPositive(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, -5, 0, 0).isPositive(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, -6, 0).isPositive(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 0, -7).isPositive(), false); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 0, 0).isPositive(), false); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // withYears() | |
- //----------------------------------------------------------------------- | |
- public void test_withYears() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.withYears(10), 10, 2, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_withYears_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.withYears(1), test); | |
- } | |
- | |
- public void test_withYears_toZero() { | |
- Period test = Period.of(1, YEARS); | |
- assertSame(test.withYears(0), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // withMonths() | |
- //----------------------------------------------------------------------- | |
- public void test_withMonths() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.withMonths(10), 1, 10, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_withMonths_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.withMonths(2), test); | |
- } | |
- | |
- public void test_withMonths_toZero() { | |
- Period test = Period.of(1, MONTHS); | |
- assertSame(test.withMonths(0), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // withDays() | |
- //----------------------------------------------------------------------- | |
- public void test_withDays() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.withDays(10), 1, 2, 10, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_withDays_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.withDays(3), test); | |
- } | |
- | |
- public void test_withDays_toZero() { | |
- Period test = Period.of(1, DAYS); | |
- assertSame(test.withDays(0), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // withTimeNanos() | |
- //----------------------------------------------------------------------- | |
- public void test_withTimeNanos() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.withTimeNanos(10), 1, 2, 3, 0, 0, 0, 10); | |
- } | |
- | |
- public void test_withTimeNanos_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.withTimeNanos(((4 * 60 + 5) * 60 + 6) * 1_000_000_000L + 7), test); | |
- } | |
- | |
- public void test_withTimeNanos_toZero() { | |
- Period test = Period.of(1, NANOS); | |
- assertSame(test.withTimeNanos(0), Period.ZERO); | |
- } | |
- | |
- | |
- //----------------------------------------------------------------------- | |
- // plusYears() | |
- //----------------------------------------------------------------------- | |
- public void test_plusYears() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(10, YEARS), 11, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(Period.of(10, YEARS)), 11, 2, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_plusYears_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.plus(0, YEARS), test); | |
- assertPeriod(test.plus(Period.of(0, YEARS)), 1, 2, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_plusYears_toZero() { | |
- Period test = Period.of(-1, YEARS); | |
- assertSame(test.plus(1, YEARS), Period.ZERO); | |
- assertSame(test.plus(Period.of(1, YEARS)), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusYears_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, YEARS); | |
- test.plus(1, YEARS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusYears_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, YEARS); | |
- test.plus(-1, YEARS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // plusMonths() | |
- //----------------------------------------------------------------------- | |
- public void test_plusMonths() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(10, MONTHS), 1, 12, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(Period.of(10, MONTHS)), 1, 12, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_plusMonths_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.plus(0, MONTHS), test); | |
- assertEquals(test.plus(Period.of(0, MONTHS)), test); | |
- } | |
- | |
- public void test_plusMonths_toZero() { | |
- Period test = Period.of(-1, MONTHS); | |
- assertSame(test.plus(1, MONTHS), Period.ZERO); | |
- assertSame(test.plus(Period.of(1, MONTHS)), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusMonths_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, MONTHS); | |
- test.plus(1, MONTHS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusMonths_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, MONTHS); | |
- test.plus(-1, MONTHS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // plusDays() | |
- //----------------------------------------------------------------------- | |
- public void test_plusDays() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(10, DAYS), 1, 2, 13, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_plusDays_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.plus(0, DAYS), test); | |
- } | |
- | |
- public void test_plusDays_toZero() { | |
- Period test = Period.of(-1, DAYS); | |
- assertSame(test.plus(1, DAYS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusDays_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, DAYS); | |
- test.plus(1, DAYS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusDays_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, DAYS); | |
- test.plus(-1, DAYS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // plusHours() | |
- //----------------------------------------------------------------------- | |
- public void test_plusHours() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(10, HOURS), 1, 2, 3, 14, 5, 6, 7); | |
- } | |
- | |
- public void test_plusHours_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.plus(0, HOURS), test); | |
- } | |
- | |
- public void test_plusHours_toZero() { | |
- Period test = Period.of(-1, HOURS); | |
- assertSame(test.plus(1, HOURS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusHours_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, HOURS); | |
- test.plus(1, HOURS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusHours_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, HOURS); | |
- test.plus(-1, HOURS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // plusMinutes() | |
- //----------------------------------------------------------------------- | |
- public void test_plusMinutes() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(10, MINUTES), 1, 2, 3, 4, 15, 6, 7); | |
- } | |
- | |
- public void test_plusMinutes_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.plus(0, MINUTES), test); | |
- } | |
- | |
- public void test_plusMinutes_toZero() { | |
- Period test = Period.of(-1, MINUTES); | |
- assertSame(test.plus(1, MINUTES), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // plusSeconds() | |
- //----------------------------------------------------------------------- | |
- public void test_plusSeconds() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(10, SECONDS), 1, 2, 3, 4, 5, 16, 7); | |
- } | |
- | |
- public void test_plusSeconds_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.plus(0, SECONDS), test); | |
- } | |
- | |
- public void test_plusSeconds_toZero() { | |
- Period test = Period.of(-1, SECONDS); | |
- assertSame(test.plus(1, SECONDS), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // plusNanos() | |
- //----------------------------------------------------------------------- | |
- public void test_plusNanos() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.plus(10, NANOS), 1, 2, 3, 4, 5, 6, 17); | |
- } | |
- | |
- public void test_plusNanos_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.plus(0, NANOS), test); | |
- } | |
- | |
- public void test_plusNanos_toZero() { | |
- Period test = Period.of(-1, NANOS); | |
- assertSame(test.plus(1, NANOS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusNanos_overflowTooBig() { | |
- Period test = Period.of(Long.MAX_VALUE, NANOS); | |
- test.plus(1, NANOS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_plusNanos_overflowTooSmall() { | |
- Period test = Period.of(Long.MIN_VALUE, NANOS); | |
- test.plus(-1, NANOS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusYears() | |
- //----------------------------------------------------------------------- | |
- public void test_minus_Years() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minus(10, YEARS), -9, 2, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_minus_Years_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.minus(0, YEARS), test); | |
- } | |
- | |
- public void test_minus_Years_toZero() { | |
- Period test = Period.of(1, YEARS); | |
- assertSame(test.minus(1, YEARS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Years_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, YEARS); | |
- test.minus(-1, YEARS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Years_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, YEARS); | |
- test.minus(1, YEARS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusYears() | |
- //----------------------------------------------------------------------- | |
- public void test_minusYears() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minusYears(10), -9, 2, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_minusYears_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.minusYears(0), test); | |
- } | |
- | |
- public void test_minusYears_toZero() { | |
- Period test = Period.of(1, YEARS); | |
- assertEquals(test.minusYears(1), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusYears_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, YEARS); | |
- test.minusYears(-1); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusYears_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, YEARS); | |
- test.minusYears(1); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusMonths() | |
- //----------------------------------------------------------------------- | |
- public void test_minus_Months() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minus(10, MONTHS), 1, -8, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_minus_Months_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.minus(0, MONTHS), test); | |
- } | |
- | |
- public void test_minus_Months_toZero() { | |
- Period test = Period.of(1, MONTHS); | |
- assertSame(test.minus(1, MONTHS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Months_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, MONTHS); | |
- test.minus(-1, MONTHS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Months_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, MONTHS); | |
- test.minus(1, MONTHS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusMonths() | |
- //----------------------------------------------------------------------- | |
- public void test_minusMonths() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minusMonths(10), 1, -8, 3, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_minusMonths_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.minusMonths(0), test); | |
- } | |
- | |
- public void test_minusMonths_toZero() { | |
- Period test = Period.of(1, MONTHS); | |
- assertEquals(test.minusMonths(1), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusMonths_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, MONTHS); | |
- test.minusMonths(-1); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusMonths_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, MONTHS); | |
- test.minusMonths(1); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusDays() | |
- //----------------------------------------------------------------------- | |
- public void test_minus_Days() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minus(10, DAYS), 1, 2, -7, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_minus_Days_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.minus(0, DAYS), test); | |
- } | |
- | |
- public void test_minus_Days_toZero() { | |
- Period test = Period.of(1, DAYS); | |
- assertSame(test.minus(1, DAYS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Days_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, DAYS); | |
- test.minus(-1, DAYS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Days_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, DAYS); | |
- test.minus(1, DAYS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusDays() | |
- //----------------------------------------------------------------------- | |
- public void test_minusDays() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minusDays(10), 1, 2, -7, 4, 5, 6, 7); | |
- } | |
- | |
- public void test_minusDays_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.minusDays(0), test); | |
- } | |
- | |
- public void test_minusDays_toZero() { | |
- Period test = Period.of(1, DAYS); | |
- assertEquals(test.minusDays(1), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusDays_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, DAYS); | |
- test.minusDays(-1); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusDays_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, DAYS); | |
- test.minusDays(1); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusHours() | |
- //----------------------------------------------------------------------- | |
- public void test_minus_Hours() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minus(10, HOURS), 1, 2, 3, -5, -54, -53, -999999993); | |
- assertEquals(test.minus(10, HOURS).plus(10, HOURS), test); | |
- } | |
- | |
- public void test_minus_Hours_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.minus(0, HOURS), test); | |
- } | |
- | |
- public void test_minus_Hours_toZero() { | |
- Period test = Period.of(1, HOURS); | |
- assertSame(test.minus(1, HOURS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Hours_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, HOURS); | |
- test.minus(-1, HOURS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Hours_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, HOURS); | |
- test.minus(1, HOURS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusHours() | |
- //----------------------------------------------------------------------- | |
- public void test_minusHours() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minusHours(10), 1, 2, 3, -5, -54, -53, -999999993); | |
- assertEquals(test.minusHours(10).plusHours(10), test); | |
- } | |
- | |
- public void test_minusHours_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.minusHours(0), test); | |
- } | |
- | |
- public void test_minusHours_toZero() { | |
- Period test = Period.of(1, HOURS); | |
- assertEquals(test.minusHours(1), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusHours_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE, HOURS); | |
- test.minusHours(-1); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusHours_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE, HOURS); | |
- test.minusHours(1); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusMinutes() | |
- //----------------------------------------------------------------------- | |
- public void test_minus_Minutes() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minus(10, MINUTES), 1, 2, 3, 3, 55, 6, 7); | |
- assertEquals(test.minus(10, MINUTES).plus(10, MINUTES), test); | |
- } | |
- | |
- public void test_minus_Minutes_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.minus(0, MINUTES), test); | |
- } | |
- | |
- public void test_minus_Minutes_toZero() { | |
- Period test = Period.of(1, MINUTES); | |
- assertSame(test.minus(1, MINUTES), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusMinutes() | |
- //----------------------------------------------------------------------- | |
- public void test_minusMinutes() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minusMinutes(10), 1, 2, 3, 3, 55, 6, 7); | |
- assertEquals(test.minusMinutes(10).plusMinutes(10), test); | |
- } | |
- | |
- public void test_minusMinutes_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.minusMinutes(0), test); | |
- } | |
- | |
- public void test_minusMinutes_toZero() { | |
- Period test = Period.of(1, MINUTES); | |
- assertEquals(test.minusMinutes(1), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusSeconds() | |
- //----------------------------------------------------------------------- | |
- public void test_minus_Seconds() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minus(10, SECONDS), 1, 2, 3, 4, 4, 56, 7); | |
- assertEquals(test.minus(10, SECONDS).plus(10, SECONDS), test); | |
- } | |
- | |
- public void test_minus_Seconds_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.minus(0, SECONDS), test); | |
- } | |
- | |
- public void test_minus_Seconds_toZero() { | |
- Period test = Period.of(1, SECONDS); | |
- assertSame(test.minus(1, SECONDS), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusSeconds() | |
- //----------------------------------------------------------------------- | |
- public void test_minusSeconds() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minusSeconds(10), 1, 2, 3, 4, 4, 56, 7); | |
- assertEquals(test.minusSeconds(10).plusSeconds(10), test); | |
- } | |
- | |
- public void test_minusSeconds_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.minusSeconds(0), test); | |
- } | |
- | |
- public void test_minusSeconds_toZero() { | |
- Period test = Period.of(1, SECONDS); | |
- assertEquals(test.minusSeconds(1), Period.ZERO); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusNanos() | |
- //----------------------------------------------------------------------- | |
- public void test_minus_Nanos() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minus(10, NANOS), 1, 2, 3, 4, 5, 5, 999999997); | |
- } | |
- | |
- public void test_minus_Nanos_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.minus(0, NANOS), test); | |
- } | |
- | |
- public void test_minus_Nanos_toZero() { | |
- Period test = Period.of(1, NANOS); | |
- assertSame(test.minus(1, NANOS), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Nanos_overflowTooBig() { | |
- Period test = Period.of(Long.MAX_VALUE, NANOS); | |
- test.minus(-1, NANOS); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minus_Nanos_overflowTooSmall() { | |
- Period test = Period.of(Long.MIN_VALUE, NANOS); | |
- test.minus(1, NANOS); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // minusNanos() | |
- //----------------------------------------------------------------------- | |
- public void test_minusNanos() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.minusNanos(10), 1, 2, 3, 4, 5, 5, 999999997); | |
- } | |
- | |
- public void test_minusNanos_noChange() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertEquals(test.minusNanos(0), test); | |
- } | |
- | |
- public void test_minusNanos_toZero() { | |
- Period test = Period.of(1, NANOS); | |
- assertEquals(test.minusNanos(1), Period.ZERO); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusNanos_overflowTooBig() { | |
- Period test = Period.of(Long.MAX_VALUE, NANOS); | |
- test.minusNanos(-1); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_minusNanos_overflowTooSmall() { | |
- Period test = Period.of(Long.MIN_VALUE, NANOS); | |
- test.minusNanos(1); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // multipliedBy() | |
- //----------------------------------------------------------------------- | |
- public void test_multipliedBy() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.multipliedBy(2), 2, 4, 6, 8, 10, 12, 14); | |
- assertPeriod(test.multipliedBy(-3), -3, -6, -9, -12, -15, -18, -21); | |
- } | |
- | |
- public void test_multipliedBy_zeroBase() { | |
- assertSame(Period.ZERO.multipliedBy(2), Period.ZERO); | |
- } | |
- | |
- public void test_multipliedBy_zero() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.multipliedBy(0), Period.ZERO); | |
- } | |
- | |
- public void test_multipliedBy_one() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertSame(test.multipliedBy(1), test); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_multipliedBy_overflowTooBig() { | |
- Period test = Period.of(Integer.MAX_VALUE / 2 + 1, YEARS); | |
- test.multipliedBy(2); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_multipliedBy_overflowTooSmall() { | |
- Period test = Period.of(Integer.MIN_VALUE / 2 - 1, YEARS); | |
- test.multipliedBy(2); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // negated() | |
- //----------------------------------------------------------------------- | |
- public void test_negated() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 7); | |
- assertPeriod(test.negated(), -1, -2, -3, -4, -5, -6, -7); | |
- } | |
- | |
- public void test_negated_zero() { | |
- assertSame(Period.ZERO.negated(), Period.ZERO); | |
- } | |
- | |
- public void test_negated_max() { | |
- assertPeriod(Period.of(Integer.MAX_VALUE, YEARS).negated(), -Integer.MAX_VALUE, 0, 0, 0, 0, 0, 0); | |
- } | |
- | |
- @Test(expectedExceptions=ArithmeticException.class) | |
- public void test_negated_overflow() { | |
- Period.of(Integer.MIN_VALUE, YEARS).negated(); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // addTo() | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="addTo") | |
- Object[][] data_addTo() { | |
- return new Object[][] { | |
- {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, | |
- | |
- {pymd(1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, | |
- {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 7, 10)}, | |
- {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 11)}, | |
- | |
- {pymd(-1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, | |
- {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 5, 10)}, | |
- {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 9)}, | |
- | |
- {pymd(1, 2, 3), date(2012, 6, 27), date(2013, 8, 30)}, | |
- {pymd(1, 2, 3), date(2012, 6, 28), date(2013, 8, 31)}, | |
- {pymd(1, 2, 3), date(2012, 6, 29), date(2013, 9, 1)}, | |
- {pymd(1, 2, 3), date(2012, 6, 30), date(2013, 9, 2)}, | |
- {pymd(1, 2, 3), date(2012, 7, 1), date(2013, 9, 4)}, | |
- | |
- {pymd(1, 0, 0), date(2011, 2, 28), date(2012, 2, 28)}, | |
- {pymd(4, 0, 0), date(2011, 2, 28), date(2015, 2, 28)}, | |
- {pymd(1, 0, 0), date(2012, 2, 29), date(2013, 2, 28)}, | |
- {pymd(4, 0, 0), date(2012, 2, 29), date(2016, 2, 29)}, | |
- | |
- {pymd(1, 1, 0), date(2011, 1, 29), date(2012, 2, 29)}, | |
- {pymd(1, 2, 0), date(2012, 2, 29), date(2013, 4, 29)}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="addTo") | |
- public void test_addTo(Period period, LocalDate baseDate, LocalDate expected) { | |
- assertEquals(period.addTo(baseDate), expected); | |
- } | |
- | |
- @Test(dataProvider="addTo") | |
- public void test_addTo_usingLocalDatePlus(Period period, LocalDate baseDate, LocalDate expected) { | |
- assertEquals(baseDate.plus(period), expected); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void test_addTo_nullZero() { | |
- Period.ZERO.addTo(null); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void test_addTo_nullNonZero() { | |
- Period.of(2, DAYS).addTo(null); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // subtractFrom() | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="subtractFrom") | |
- Object[][] data_subtractFrom() { | |
- return new Object[][] { | |
- {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, | |
- | |
- {pymd(1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, | |
- {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 5, 10)}, | |
- {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 9)}, | |
- | |
- {pymd(-1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, | |
- {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 7, 10)}, | |
- {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 11)}, | |
- | |
- {pymd(1, 2, 3), date(2012, 8, 30), date(2011, 6, 27)}, | |
- {pymd(1, 2, 3), date(2012, 8, 31), date(2011, 6, 27)}, | |
- {pymd(1, 2, 3), date(2012, 9, 1), date(2011, 6, 28)}, | |
- {pymd(1, 2, 3), date(2012, 9, 2), date(2011, 6, 29)}, | |
- {pymd(1, 2, 3), date(2012, 9, 3), date(2011, 6, 30)}, | |
- {pymd(1, 2, 3), date(2012, 9, 4), date(2011, 7, 1)}, | |
- | |
- {pymd(1, 0, 0), date(2011, 2, 28), date(2010, 2, 28)}, | |
- {pymd(4, 0, 0), date(2011, 2, 28), date(2007, 2, 28)}, | |
- {pymd(1, 0, 0), date(2012, 2, 29), date(2011, 2, 28)}, | |
- {pymd(4, 0, 0), date(2012, 2, 29), date(2008, 2, 29)}, | |
- | |
- {pymd(1, 1, 0), date(2013, 3, 29), date(2012, 2, 29)}, | |
- {pymd(1, 2, 0), date(2012, 2, 29), date(2010, 12, 29)}, | |
- }; | |
- } | |
- | |
- @Test(dataProvider="subtractFrom") | |
- public void test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected) { | |
- assertEquals(period.subtractFrom(baseDate), expected); | |
- } | |
- | |
- @Test(dataProvider="subtractFrom") | |
- public void test_subtractFrom_usingLocalDateMinus(Period period, LocalDate baseDate, LocalDate expected) { | |
- assertEquals(baseDate.minus(period), expected); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void test_subtractFrom_nullZero() { | |
- Period.ZERO.subtractFrom(null); | |
- } | |
- | |
- @Test(expectedExceptions=NullPointerException.class) | |
- public void test_subtractFrom_nullNonZero() { | |
- Period.of(2, DAYS).subtractFrom(null); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // toDuration() | |
- //----------------------------------------------------------------------- | |
- public void test_toDuration() { | |
- assertEquals(Period.ZERO.toDuration(), Duration.of(0, SECONDS)); | |
- assertEquals(Period.of(0, 0, 0, 4, 5, 6, 7).toDuration(), Duration.ofSeconds((4 * 60 + 5) * 60L + 6, 7)); | |
- } | |
- | |
- public void test_toDuration_calculation() { | |
- assertEquals(Period.of(0, 0, 0, 2, 0, 0, 0).toDuration(), Duration.ofSeconds(2 * 3600)); | |
- assertEquals(Period.of(0, 0, 0, 0, 2, 0, 0).toDuration(), Duration.of(120, SECONDS)); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 2, 0).toDuration(), Duration.of(2, SECONDS)); | |
- | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 3, 1000000000L - 1).toDuration(), Duration.ofSeconds(3, 999999999)); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 3, 1000000000L).toDuration(), Duration.ofSeconds(4, 0)); | |
- } | |
- | |
- public void test_toDuration_negatives() { | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 2, 1).toDuration(), Duration.ofSeconds(2, 1)); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 2, -1).toDuration(), Duration.ofSeconds(1, 999999999)); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, -2, 1).toDuration(), Duration.ofSeconds(-2, 1)); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, -2, -1).toDuration(), Duration.ofSeconds(-3, 999999999)); | |
- } | |
- | |
- @Test(expectedExceptions=DateTimeException.class) | |
- public void test_toDuration_years() { | |
- Period.of(1, 0, 0, 4, 5, 6, 7).toDuration(); | |
- } | |
- | |
- @Test(expectedExceptions=DateTimeException.class) | |
- public void test_toDuration_months() { | |
- Period.of(0, 1, 0, 4, 5, 6, 7).toDuration(); | |
- } | |
- | |
- @Test(expectedExceptions=DateTimeException.class) | |
- public void test_toDuration_days() { | |
- Duration test = Period.of(0, 0, 1, 4, 5, 6, 7).toDuration(); | |
- assertEquals(test, Duration.ofSeconds(101106, 7L)); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // equals() / hashCode() | |
- //----------------------------------------------------------------------- | |
- public void test_equals() { | |
- assertEquals(Period.of(1, 0, 0, 0, 0, 0, 0).equals(Period.of(1, YEARS)), true); | |
- assertEquals(Period.of(0, 1, 0, 0, 0, 0, 0).equals(Period.of(1, MONTHS)), true); | |
- assertEquals(Period.of(0, 0, 1, 0, 0, 0, 0).equals(Period.of(1, DAYS)), true); | |
- assertEquals(Period.of(0, 0, 0, 1, 0, 0, 0).equals(Period.of(1, HOURS)), true); | |
- assertEquals(Period.of(0, 0, 0, 0, 1, 0, 0).equals(Period.of(1, MINUTES)), true); | |
- assertEquals(Period.of(0, 0, 0, 0, 0, 1, 0).equals(Period.of(1, SECONDS)), true); | |
- assertEquals(Period.of(1, 2, 3, 0, 0, 0, 0).equals(Period.ofDate(1, 2, 3)), true); | |
- assertEquals(Period.of(0, 0, 0, 1, 2, 3, 0).equals(Period.ofTime(1, 2, 3, 0)), true); | |
- assertEquals(Period.of(1, 2, 3, 4, 5, 6, 0).equals(Period.of(1, 2, 3, 4, 5, 6, 0)), true); | |
- | |
- assertEquals(Period.of(1, YEARS).equals(Period.of(1, YEARS)), true); | |
- assertEquals(Period.of(1, YEARS).equals(Period.of(2, YEARS)), false); | |
- | |
- assertEquals(Period.of(1, MONTHS).equals(Period.of(1, MONTHS)), true); | |
- assertEquals(Period.of(1, MONTHS).equals(Period.of(2, MONTHS)), false); | |
- | |
- assertEquals(Period.of(1, DAYS).equals(Period.of(1, DAYS)), true); | |
- assertEquals(Period.of(1, DAYS).equals(Period.of(2, DAYS)), false); | |
- | |
- assertEquals(Period.of(1, HOURS).equals(Period.of(1, HOURS)), true); | |
- assertEquals(Period.of(1, HOURS).equals(Period.of(2, HOURS)), false); | |
- | |
- assertEquals(Period.of(1, MINUTES).equals(Period.of(1, MINUTES)), true); | |
- assertEquals(Period.of(1, MINUTES).equals(Period.of(2, MINUTES)), false); | |
- | |
- assertEquals(Period.of(1, SECONDS).equals(Period.of(1, SECONDS)), true); | |
- assertEquals(Period.of(1, SECONDS).equals(Period.of(2, SECONDS)), false); | |
- | |
- assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(1, 2, 3)), true); | |
- assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(0, 2, 3)), false); | |
- assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(1, 0, 3)), false); | |
- assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(1, 2, 0)), false); | |
- | |
- assertEquals(Period.ofTime(1, 2, 3, 0).equals(Period.ofTime(1, 2, 3, 0)), true); | |
- assertEquals(Period.ofTime(1, 2, 3, 0).equals(Period.ofTime(0, 2, 3, 0)), false); | |
- assertEquals(Period.ofTime(1, 2, 3, 0).equals(Period.ofTime(1, 0, 3, 0)), false); | |
- assertEquals(Period.ofTime(1, 2, 3, 0).equals(Period.ofTime(1, 2, 0, 0)), false); | |
- } | |
- | |
- public void test_equals_self() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 0); | |
- assertEquals(test.equals(test), true); | |
- } | |
- | |
- public void test_equals_null() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 0); | |
- assertEquals(test.equals(null), false); | |
- } | |
- | |
- public void test_equals_otherClass() { | |
- Period test = Period.of(1, 2, 3, 4, 5, 6, 0); | |
- assertEquals(test.equals(""), false); | |
- } | |
- | |
+ // hashCode() | |
//----------------------------------------------------------------------- | |
public void test_hashCode() { | |
- Period test5 = Period.of(5, DAYS); | |
- Period test6 = Period.of(6, DAYS); | |
- Period test5M = Period.of(5, MONTHS); | |
- Period test5Y = Period.of(5, YEARS); | |
+ Period test5 = Period.ofDays(5); | |
+ Period test6 = Period.ofDays(6); | |
+ Period test5M = Period.ofMonths(5); | |
+ Period test5Y = Period.ofYears(5); | |
assertEquals(test5.hashCode() == test5.hashCode(), true); | |
assertEquals(test5.hashCode() == test6.hashCode(), false); | |
assertEquals(test5.hashCode() == test5M.hashCode(), false); | |
assertEquals(test5.hashCode() == test5Y.hashCode(), false); | |
} | |
- //----------------------------------------------------------------------- | |
- // toString() | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="toStringAndParse") | |
- Object[][] data_toString() { | |
- return new Object[][] { | |
- {Period.ZERO, "PT0S"}, | |
- {Period.of(0, DAYS), "PT0S"}, | |
- {Period.of(1, YEARS), "P1Y"}, | |
- {Period.of(1, MONTHS), "P1M"}, | |
- {Period.of(1, DAYS), "P1D"}, | |
- {Period.of(1, HOURS), "PT1H"}, | |
- {Period.of(1, MINUTES), "PT1M"}, | |
- {Period.of(1, SECONDS), "PT1S"}, | |
- {Period.of(12, SECONDS), "PT12S"}, | |
- {Period.of(123, SECONDS), "PT2M3S"}, | |
- {Period.of(1234, SECONDS), "PT20M34S"}, | |
- {Period.of(-1, SECONDS), "PT-1S"}, | |
- {Period.of(-12, SECONDS), "PT-12S"}, | |
- {Period.of(-123, SECONDS), "PT-2M-3S"}, | |
- {Period.of(-1234, SECONDS), "PT-20M-34S"}, | |
- {Period.of(1, 2, 3, 4, 5, 6, 0), "P1Y2M3DT4H5M6S"}, | |
- {Period.of(1, 2, 3, 4, 5, 6, 700000000), "P1Y2M3DT4H5M6.7S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, 100000000), "PT0.1S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, -100000000), "PT-0.1S"}, | |
- {Period.of(0, 0, 0, 0, 0, 1, -900000000), "PT0.1S"}, | |
- {Period.of(0, 0, 0, 0, 0, -1, 900000000), "PT-0.1S"}, | |
- {Period.of(0, 0, 0, 0, 0, 1, 100000000), "PT1.1S"}, | |
- {Period.of(0, 0, 0, 0, 0, 1, -100000000), "PT0.9S"}, | |
- {Period.of(0, 0, 0, 0, 0, -1, 100000000), "PT-0.9S"}, | |
- {Period.of(0, 0, 0, 0, 0, -1, -100000000), "PT-1.1S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, 10000000), "PT0.01S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, -10000000), "PT-0.01S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, 1000000), "PT0.001S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, -1000000), "PT-0.001S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, 1000), "PT0.000001S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, -1000), "PT-0.000001S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, 1), "PT0.000000001S"}, | |
- {Period.of(0, 0, 0, 0, 0, 0, -1), "PT-0.000000001S"}, | |
- }; | |
- } | |
- | |
- @Test(groups="tck", dataProvider="toStringAndParse") | |
- public void test_toString(Period input, String expected) { | |
- assertEquals(input.toString(), expected); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- // toTimeOnly() and toDateOnly() | |
- //----------------------------------------------------------------------- | |
- @DataProvider(name="toTimeOnlyAndToDateOnly") | |
- Object[][] data_toTimeOnlyAndToDateOnly() { | |
- return new Object[][] { | |
- {Period.ZERO, Period.ZERO, Period.ZERO}, | |
- {Period.of(1, YEARS), Period.ofDate(1, 0, 0), Period.ZERO}, | |
- {Period.of(2, MONTHS), Period.ofDate(0, 2, 0), Period.ZERO}, | |
- {Period.of(3, DAYS), Period.ofDate(0, 0, 3), Period.ZERO}, | |
- {Period.of(4, HOURS), Period.ZERO, Period.ofTime(4, 0, 0, 0)}, | |
- {Period.of(5, MINUTES), Period.ZERO, Period.ofTime(0, 5, 0, 0)}, | |
- {Period.of(6, SECONDS), Period.ZERO, Period.ofTime(0, 0, 6, 0)}, | |
- {Period.of(7, NANOS), Period.ZERO, Period.ofTime(0, 0, 0, 7)}, | |
- {Period.ofDate(1, 2, 3), Period.of(1, 2, 3, 0, 0, 0, 0), Period.ZERO}, | |
- {Period.ofTime(4, 5, 6, 0), Period.ZERO, Period.of(0, 0, 0, 4, 5, 6, 0)}, | |
- {Period.ofTime(4, 5, 6, 7), Period.ZERO, Period.of(0, 0, 0, 4, 5, 6, 7)}, | |
- {Period.of(1, 2, 3, 4, 5, 6, 0), Period.ofDate(1, 2, 3), Period.ofTime(4, 5, 6, 0)}, | |
- {Period.of(1, 2, 3, 4, 5, 6, 700000000), Period.ofDate(1, 2, 3), Period.ofTime(4, 5, 6, 700000000)}, | |
- }; | |
- } | |
- | |
- @Test(groups="tck", dataProvider="toTimeOnlyAndToDateOnly") | |
- public void test_toTimeOnlyAndToDateOnly(Period input, Period toDateOnlyResult, Period toTimeOnlyResult) { | |
- assertEquals(input.toDateOnly(), toDateOnlyResult); | |
- assertEquals(input.toTimeOnly(), toTimeOnlyResult); | |
- } | |
- | |
- //----------------------------------------------------------------------- | |
- private void assertPeriod(Period test, int y, int mo, int d, int h, int mn, int s, long n) { | |
- assertEquals(test.getYears(), y, "years"); | |
- assertEquals(test.getMonths(), mo, "months"); | |
- assertEquals(test.getDays(), d, "days"); | |
- assertEquals(test.getHours(), h, "hours"); | |
- assertEquals(test.getMinutes(), mn, "mins"); | |
- assertEquals(test.getSeconds(), s, "secs"); | |
- assertEquals(test.getNanos(), n, "nanos"); | |
- assertEquals(test.getTimeNanos(), (((h * 60L + mn) * 60 + s) * 1_000_000_000L + n), "total nanos"); | |
- } | |
- | |
- private static Period pymd(int y, int m, int d) { | |
- return Period.ofDate(y, m, d); | |
- } | |
- | |
- private static LocalDate date(int y, int m, int d) { | |
- return LocalDate.of(y, m, d); | |
- } | |
- | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment