Skip to content

Instantly share code, notes, and snippets.

@jodastephen
Created September 13, 2013 12:05
Show Gist options
  • Save jodastephen/6549818 to your computer and use it in GitHub Desktop.
Save jodastephen/6549818 to your computer and use it in GitHub Desktop.
Patch for #328
# HG changeset patch
# User scolebourne
# Date 1379073847 -3600
# Node ID 46b86421753a3c3c71167d327a2012e50e45bd94
# Parent 0d78450f712812a6fef52db03e6143cb274494ba
Change until() to accept any compatible temporal
Method until(Temporal,TemporalUnit) now uses from() to convert
Update Javadoc spec
Enhance from() methods where necessary
Add tests
Fixes GitHub #328
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
@@ -441,9 +441,13 @@
//-----------------------------------------------------------------------
/**
- * Obtains a {@code Duration} representing the duration between two instants.
+ * Obtains a {@code Duration} representing the duration between two temporal objects.
* <p>
- * This calculates the duration between two temporal objects of the same type.
+ * This calculates the duration between two temporal objects. If the objects
+ * are of different types, then the duration is calculated based on the type
+ * of the first object. For example, if the first argument is a {@code LocalTime}
+ * then the second argument is converted to a {@code LocalTime}.
+ * <p>
* The specified temporal objects must support the {@link ChronoUnit#SECONDS SECONDS} unit.
* For full accuracy, either the {@link ChronoUnit#NANOS NANOS} unit or the
* {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field should be supported.
diff --git a/src/share/classes/java/time/Instant.java b/src/share/classes/java/time/Instant.java
--- a/src/share/classes/java/time/Instant.java
+++ b/src/share/classes/java/time/Instant.java
@@ -362,6 +362,10 @@
* @throws DateTimeException if unable to convert to an {@code Instant}
*/
public static Instant from(TemporalAccessor temporal) {
+ if (temporal instanceof Instant) {
+ return (Instant) temporal;
+ }
+ Objects.requireNonNull(temporal, "temporal");
long instantSecs = temporal.getLong(INSTANT_SECONDS);
int nanoOfSecond = temporal.get(NANO_OF_SECOND);
return Instant.ofEpochSecond(instantSecs, nanoOfSecond);
@@ -1091,7 +1095,8 @@
* The result will be negative if the end is before the start.
* The calculation returns a whole number, representing the number of
* complete units between the two instants.
- * The {@code Temporal} passed to this method must be an {@code Instant}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code Instant} using {@link #from(TemporalAccessor)}.
* For example, the amount in days between two dates can be calculated
* using {@code startInstant.until(endInstant, SECONDS)}.
* <p>
@@ -1112,25 +1117,22 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endInstant the end date, which must be an {@code Instant}, not null
+ * @param endExclusive the end date, which is converted to an {@code Instant}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this instant and the end instant
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to an {@code Instant}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endInstant, TemporalUnit unit) {
- if (endInstant instanceof Instant == false) {
- Objects.requireNonNull(endInstant, "endInstant");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
- Instant end = (Instant) endInstant;
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ Instant end = Instant.from(endExclusive);
if (unit instanceof ChronoUnit) {
ChronoUnit f = (ChronoUnit) unit;
switch (f) {
@@ -1145,7 +1147,7 @@
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
- return unit.between(this, endInstant);
+ return unit.between(this, end);
}
private long nanosUntil(Instant end) {
diff --git a/src/share/classes/java/time/LocalDate.java b/src/share/classes/java/time/LocalDate.java
--- a/src/share/classes/java/time/LocalDate.java
+++ b/src/share/classes/java/time/LocalDate.java
@@ -353,6 +353,7 @@
* @throws DateTimeException if unable to convert to a {@code LocalDate}
*/
public static LocalDate from(TemporalAccessor temporal) {
+ Objects.requireNonNull(temporal, "temporal");
LocalDate date = temporal.query(TemporalQuery.localDate());
if (date == null) {
throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " + temporal.getClass());
@@ -1541,7 +1542,8 @@
* objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified date.
* The result will be negative if the end is before the start.
- * The {@code Temporal} passed to this method must be a {@code LocalDate}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code LocalDate} using {@link #from(TemporalAccessor)}.
* For example, the amount in days between two dates can be calculated
* using {@code startDate.until(endDate, DAYS)}.
* <p>
@@ -1567,26 +1569,22 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endDate the end date, which must be a {@code LocalDate}, not null
+ * @param endExclusive the end date, which is converted to a {@code LocalDate}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this date and the end date
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to a {@code LocalDate}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endDate, TemporalUnit unit) {
- Objects.requireNonNull(unit, "unit");
- if (endDate instanceof LocalDate == false) {
- Objects.requireNonNull(endDate, "endDate");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
- LocalDate end = (LocalDate) endDate;
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ LocalDate end = LocalDate.from(endExclusive);
if (unit instanceof ChronoUnit) {
switch ((ChronoUnit) unit) {
case DAYS: return daysUntil(end);
@@ -1600,7 +1598,7 @@
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
- return unit.between(this, endDate);
+ return unit.between(this, end);
}
long daysUntil(LocalDate end) {
diff --git a/src/share/classes/java/time/LocalDateTime.java b/src/share/classes/java/time/LocalDateTime.java
--- a/src/share/classes/java/time/LocalDateTime.java
+++ b/src/share/classes/java/time/LocalDateTime.java
@@ -1621,7 +1621,8 @@
* objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified date-time.
* The result will be negative if the end is before the start.
- * The {@code Temporal} passed to this method must be a {@code LocalDateTime}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code LocalDateTime} using {@link #from(TemporalAccessor)}.
* For example, the amount in days between two date-times can be calculated
* using {@code startDateTime.until(endDateTime, DAYS)}.
* <p>
@@ -1649,25 +1650,22 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endDateTime the end date-time, which must be a {@code LocalDateTime}, not null
+ * @param endExclusive the end date, which is converted to a {@code LocalDateTime}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this date-time and the end date-time
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to a {@code LocalDateTime}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endDateTime, TemporalUnit unit) {
- if (endDateTime instanceof LocalDateTime == false) {
- Objects.requireNonNull(endDateTime, "endDateTime");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
- LocalDateTime end = (LocalDateTime) endDateTime;
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ LocalDateTime end = LocalDateTime.from(endExclusive);
if (unit instanceof ChronoUnit) {
if (unit.isTimeBased()) {
long amount = date.daysUntil(end.date);
@@ -1721,7 +1719,7 @@
}
return date.until(endDate, unit);
}
- return unit.between(this, endDateTime);
+ return unit.between(this, end);
}
/**
diff --git a/src/share/classes/java/time/LocalTime.java b/src/share/classes/java/time/LocalTime.java
--- a/src/share/classes/java/time/LocalTime.java
+++ b/src/share/classes/java/time/LocalTime.java
@@ -394,6 +394,7 @@
* @throws DateTimeException if unable to convert to a {@code LocalTime}
*/
public static LocalTime from(TemporalAccessor temporal) {
+ Objects.requireNonNull(temporal, "temporal");
LocalTime time = temporal.query(TemporalQuery.localTime());
if (time == null) {
throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " + temporal.getClass());
@@ -1330,7 +1331,8 @@
* objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified time.
* The result will be negative if the end is before the start.
- * The {@code Temporal} passed to this method must be a {@code LocalTime}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code LocalTime} using {@link #from(TemporalAccessor)}.
* For example, the amount in hours between two times can be calculated
* using {@code startTime.until(endTime, HOURS)}.
* <p>
@@ -1356,25 +1358,22 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endTime the end time, which must be a {@code LocalTime}, not null
+ * @param endExclusive the end time, which is converted to a {@code LocalTime}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this time and the end time
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to a {@code LocalTime}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endTime, TemporalUnit unit) {
- if (endTime instanceof LocalTime == false) {
- Objects.requireNonNull(endTime, "endTime");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
- LocalTime end = (LocalTime) endTime;
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ LocalTime end = LocalTime.from(endExclusive);
if (unit instanceof ChronoUnit) {
long nanosUntil = end.toNanoOfDay() - toNanoOfDay(); // no overflow
switch ((ChronoUnit) unit) {
@@ -1388,7 +1387,7 @@
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
- return unit.between(this, endTime);
+ return unit.between(this, end);
}
/**
diff --git a/src/share/classes/java/time/MonthDay.java b/src/share/classes/java/time/MonthDay.java
--- a/src/share/classes/java/time/MonthDay.java
+++ b/src/share/classes/java/time/MonthDay.java
@@ -246,7 +246,8 @@
* <p>
* The conversion extracts the {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} and
* {@link ChronoField#DAY_OF_MONTH DAY_OF_MONTH} fields.
- * The extraction is only permitted if the date-time has an ISO chronology.
+ * The extraction is only permitted if the temporal object has an ISO
+ * chronology, or can be converted to a {@code LocalDate}.
* <p>
* This method matches the signature of the functional interface {@link TemporalQuery}
* allowing it to be used in queries via method reference, {@code MonthDay::from}.
diff --git a/src/share/classes/java/time/OffsetDateTime.java b/src/share/classes/java/time/OffsetDateTime.java
--- a/src/share/classes/java/time/OffsetDateTime.java
+++ b/src/share/classes/java/time/OffsetDateTime.java
@@ -1592,7 +1592,8 @@
* For example, the period in days between two date-times can be calculated
* using {@code startDateTime.until(endDateTime, DAYS)}.
* <p>
- * The {@code Temporal} passed to this method must be an {@code OffsetDateTime}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code OffsetDateTime} using {@link #from(TemporalAccessor)}.
* If the offset differs between the two date-times, the specified
* end date-time is normalized to have the same offset as this date-time.
* <p>
@@ -1620,30 +1621,27 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endDateTime the end date-time, which must be an {@code OffsetDateTime}, not null
+ * @param endExclusive the end date, which is converted to an {@code OffsetDateTime}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this date-time and the end date-time
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to an {@code OffsetDateTime}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endDateTime, TemporalUnit unit) {
- if (endDateTime instanceof OffsetDateTime == false) {
- Objects.requireNonNull(endDateTime, "endDateTime");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ OffsetDateTime end = OffsetDateTime.from(endExclusive);
if (unit instanceof ChronoUnit) {
- OffsetDateTime end = (OffsetDateTime) endDateTime;
end = end.withOffsetSameInstant(offset);
return dateTime.until(end.dateTime, unit);
}
- return unit.between(this, endDateTime);
+ return unit.between(this, end);
}
/**
diff --git a/src/share/classes/java/time/OffsetTime.java b/src/share/classes/java/time/OffsetTime.java
--- a/src/share/classes/java/time/OffsetTime.java
+++ b/src/share/classes/java/time/OffsetTime.java
@@ -1124,7 +1124,8 @@
* For example, the period in hours between two times can be calculated
* using {@code startTime.until(endTime, HOURS)}.
* <p>
- * The {@code Temporal} passed to this method must be an {@code OffsetTime}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code OffsetTime} using {@link #from(TemporalAccessor)}.
* If the offset differs between the two times, then the specified
* end time is normalized to have the same offset as this time.
* <p>
@@ -1150,26 +1151,23 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endTime the end time, which must be an {@code OffsetTime}, not null
+ * @param endExclusive the end date, which is converted to an {@code OffsetTime}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this time and the end time
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to an {@code OffsetTime}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endTime, TemporalUnit unit) {
- if (endTime instanceof OffsetTime == false) {
- Objects.requireNonNull(endTime, "endTime");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ OffsetTime end = OffsetTime.from(endExclusive);
if (unit instanceof ChronoUnit) {
- OffsetTime end = (OffsetTime) endTime;
long nanosUntil = end.toEpochNano() - toEpochNano(); // no overflow
switch ((ChronoUnit) unit) {
case NANOS: return nanosUntil;
@@ -1182,7 +1180,7 @@
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
- return unit.between(this, endTime);
+ return unit.between(this, end);
}
/**
diff --git a/src/share/classes/java/time/Year.java b/src/share/classes/java/time/Year.java
--- a/src/share/classes/java/time/Year.java
+++ b/src/share/classes/java/time/Year.java
@@ -242,6 +242,7 @@
if (temporal instanceof Year) {
return (Year) temporal;
}
+ Objects.requireNonNull(temporal, "temporal");
try {
if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {
temporal = LocalDate.from(temporal);
@@ -859,7 +860,8 @@
* objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified year.
* The result will be negative if the end is before the start.
- * The {@code Temporal} passed to this method must be a {@code Year}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code Year} using {@link #from(TemporalAccessor)}.
* For example, the period in decades between two year can be calculated
* using {@code startYear.until(endYear, DECADES)}.
* <p>
@@ -885,25 +887,22 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endYear the end year, which must be a {@code Year}, not null
+ * @param endExclusive the end date, which is converted to a {@code Year}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this year and the end year
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to a {@code Year}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endYear, TemporalUnit unit) {
- if (endYear instanceof Year == false) {
- Objects.requireNonNull(endYear, "endYear");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
- Year end = (Year) endYear;
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ Year end = Year.from(endExclusive);
if (unit instanceof ChronoUnit) {
long yearsUntil = ((long) end.year) - year; // no overflow
switch ((ChronoUnit) unit) {
@@ -915,7 +914,7 @@
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
- return unit.between(this, endYear);
+ return unit.between(this, end);
}
/**
diff --git a/src/share/classes/java/time/YearMonth.java b/src/share/classes/java/time/YearMonth.java
--- a/src/share/classes/java/time/YearMonth.java
+++ b/src/share/classes/java/time/YearMonth.java
@@ -245,6 +245,7 @@
if (temporal instanceof YearMonth) {
return (YearMonth) temporal;
}
+ Objects.requireNonNull(temporal, "temporal");
try {
if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {
temporal = LocalDate.from(temporal);
@@ -992,7 +993,8 @@
* objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified year-month.
* The result will be negative if the end is before the start.
- * The {@code Temporal} passed to this method must be a {@code YearMonth}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code YearMonth} using {@link #from(TemporalAccessor)}.
* For example, the period in years between two year-months can be calculated
* using {@code startYearMonth.until(endYearMonth, YEARS)}.
* <p>
@@ -1018,25 +1020,22 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endYearMonth the end year-month, which must be a {@code YearMonth}, not null
+ * @param endExclusive the end date, which is converted to a {@code YearMonth}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this year-month and the end year-month
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to a {@code YearMonth}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endYearMonth, TemporalUnit unit) {
- if (endYearMonth instanceof YearMonth == false) {
- Objects.requireNonNull(endYearMonth, "endYearMonth");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
- YearMonth end = (YearMonth) endYearMonth;
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ YearMonth end = YearMonth.from(endExclusive);
if (unit instanceof ChronoUnit) {
long monthsUntil = end.getProlepticMonth() - getProlepticMonth(); // no overflow
switch ((ChronoUnit) unit) {
@@ -1049,7 +1048,7 @@
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
- return unit.between(this, endYearMonth);
+ return unit.between(this, end);
}
/**
diff --git a/src/share/classes/java/time/ZoneOffset.java b/src/share/classes/java/time/ZoneOffset.java
--- a/src/share/classes/java/time/ZoneOffset.java
+++ b/src/share/classes/java/time/ZoneOffset.java
@@ -333,6 +333,7 @@
* @throws DateTimeException if unable to convert to an {@code ZoneOffset}
*/
public static ZoneOffset from(TemporalAccessor temporal) {
+ Objects.requireNonNull(temporal, "temporal");
ZoneOffset offset = temporal.query(TemporalQuery.offset());
if (offset == null) {
throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " + temporal.getClass());
diff --git a/src/share/classes/java/time/ZonedDateTime.java b/src/share/classes/java/time/ZonedDateTime.java
--- a/src/share/classes/java/time/ZonedDateTime.java
+++ b/src/share/classes/java/time/ZonedDateTime.java
@@ -2044,7 +2044,8 @@
* For example, the period in days between two date-times can be calculated
* using {@code startDateTime.until(endDateTime, DAYS)}.
* <p>
- * The {@code Temporal} passed to this method must be a {@code ZonedDateTime}.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code ZonedDateTime} using {@link #from(TemporalAccessor)}.
* If the time-zone differs between the two zoned date-times, the specified
* end date-time is normalized to have the same zone as this date-time.
* <p>
@@ -2086,26 +2087,23 @@
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
- * passing {@code this} as the first argument and the input temporal as
- * the second argument.
+ * passing {@code this} as the first argument and the converted input temporal
+ * as the second argument.
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endDateTime the end date-time, which must be a {@code ZonedDateTime}, not null
+ * @param endExclusive the end date, which is converted to a {@code ZonedDateTime}, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this date-time and the end date-time
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to a {@code ZonedDateTime}
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override
- public long until(Temporal endDateTime, TemporalUnit unit) {
- if (endDateTime instanceof ZonedDateTime == false) {
- Objects.requireNonNull(endDateTime, "endDateTime");
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ ZonedDateTime end = ZonedDateTime.from(endExclusive);
if (unit instanceof ChronoUnit) {
- ZonedDateTime end = (ZonedDateTime) endDateTime;
end = end.withZoneSameInstant(zone);
if (unit.isDateBased()) {
return dateTime.until(end.dateTime, unit);
@@ -2113,7 +2111,7 @@
return toOffsetDateTime().until(end.toOffsetDateTime(), unit);
}
}
- return unit.between(this, endDateTime);
+ return unit.between(this, end);
}
/**
diff --git a/src/share/classes/java/time/chrono/ChronoLocalDate.java b/src/share/classes/java/time/chrono/ChronoLocalDate.java
--- a/src/share/classes/java/time/chrono/ChronoLocalDate.java
+++ b/src/share/classes/java/time/chrono/ChronoLocalDate.java
@@ -291,6 +291,7 @@
if (temporal instanceof ChronoLocalDate) {
return (ChronoLocalDate) temporal;
}
+ Objects.requireNonNull(temporal, "temporal");
Chronology chrono = temporal.query(TemporalQuery.chronology());
if (chrono == null) {
throw new DateTimeException("Unable to obtain ChronoLocalDate from TemporalAccessor: " + temporal.getClass());
@@ -560,8 +561,8 @@
* objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified date.
* The result will be negative if the end is before the start.
- * The {@code Temporal} passed to this method must be a
- * {@code ChronoLocalDate} in the same chronology.
+ * The {@code Temporal} passed to this method is converted to a
+ * {@code ChronoLocalDate} using {@link Chronology#date(TemporalAccessor)}.
* The calculation returns a whole number, representing the number of
* complete units between the two dates.
* For example, the amount in days between two dates can be calculated
@@ -590,15 +591,17 @@
* <p>
* This instance is immutable and unaffected by this method call.
*
- * @param endDate the end date, which must be a {@code ChronoLocalDate}
- * in the same chronology, not null
+ * @param endExclusive the end date, which is converted to a
+ * {@code ChronoLocalDate} in the same chronology, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this date and the end date
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to a {@code ChronoLocalDate}
+ * @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@Override // override for Javadoc
- long until(Temporal endDate, TemporalUnit unit);
+ long until(Temporal endExclusive, TemporalUnit unit);
/**
* Calculates the period between this date and another date as a {@code ChronoPeriod}.
diff --git a/src/share/classes/java/time/chrono/ChronoLocalDateImpl.java b/src/share/classes/java/time/chrono/ChronoLocalDateImpl.java
--- a/src/share/classes/java/time/chrono/ChronoLocalDateImpl.java
+++ b/src/share/classes/java/time/chrono/ChronoLocalDateImpl.java
@@ -72,7 +72,6 @@
import java.time.temporal.TemporalUnit;
import java.time.temporal.UnsupportedTemporalTypeException;
import java.time.temporal.ValueRange;
-import java.util.Objects;
/**
* A date expressed in terms of a standard year-month-day calendar system.
@@ -372,22 +371,9 @@
}
//-----------------------------------------------------------------------
- /**
- * {@inheritDoc}
- * @throws DateTimeException {@inheritDoc}
- * @throws ArithmeticException {@inheritDoc}
- */
@Override
- public long until(Temporal endDateTime, TemporalUnit unit) {
- Objects.requireNonNull(endDateTime, "endDateTime");
- Objects.requireNonNull(unit, "unit");
- if (endDateTime instanceof ChronoLocalDate == false) {
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
- ChronoLocalDate end = (ChronoLocalDate) endDateTime;
- if (getChronology().equals(end.getChronology()) == false) {
- throw new DateTimeException("Unable to calculate amount as objects have different chronologies");
- }
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ ChronoLocalDate end = getChronology().date(endExclusive);
if (unit instanceof ChronoUnit) {
switch ((ChronoUnit) unit) {
case DAYS: return daysUntil(end);
@@ -401,7 +387,7 @@
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
- return unit.between(this, endDateTime);
+ return unit.between(this, end);
}
private long daysUntil(ChronoLocalDate end) {
diff --git a/src/share/classes/java/time/chrono/ChronoLocalDateTime.java b/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
--- a/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
+++ b/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
@@ -165,6 +165,7 @@
if (temporal instanceof ChronoLocalDateTime) {
return (ChronoLocalDateTime<?>) temporal;
}
+ Objects.requireNonNull(temporal, "temporal");
Chronology chrono = temporal.query(TemporalQuery.chronology());
if (chrono == null) {
throw new DateTimeException("Unable to obtain ChronoLocalDateTime from TemporalAccessor: " + temporal.getClass());
diff --git a/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java b/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java
--- a/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java
+++ b/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java
@@ -69,7 +69,6 @@
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.io.Serializable;
-import java.time.DateTimeException;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoField;
@@ -369,15 +368,9 @@
//-----------------------------------------------------------------------
@Override
- public long until(Temporal endDateTime, TemporalUnit unit) {
- if (endDateTime instanceof ChronoLocalDateTime == false) {
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
+ public long until(Temporal endExclusive, TemporalUnit unit) {
@SuppressWarnings("unchecked")
- ChronoLocalDateTime<D> end = (ChronoLocalDateTime<D>) endDateTime;
- if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) {
- throw new DateTimeException("Unable to calculate amount as objects have different chronologies");
- }
+ ChronoLocalDateTime<D> end = (ChronoLocalDateTime<D>) toLocalDate().getChronology().localDateTime(endExclusive);
if (unit instanceof ChronoUnit) {
if (unit.isTimeBased()) {
long amount = end.getLong(EPOCH_DAY) - date.getLong(EPOCH_DAY);
@@ -398,7 +391,7 @@
}
return date.until(endDate, unit);
}
- return unit.between(this, endDateTime);
+ return unit.between(this, end);
}
//-----------------------------------------------------------------------
diff --git a/src/share/classes/java/time/chrono/ChronoZonedDateTime.java b/src/share/classes/java/time/chrono/ChronoZonedDateTime.java
--- a/src/share/classes/java/time/chrono/ChronoZonedDateTime.java
+++ b/src/share/classes/java/time/chrono/ChronoZonedDateTime.java
@@ -166,6 +166,7 @@
if (temporal instanceof ChronoZonedDateTime) {
return (ChronoZonedDateTime<?>) temporal;
}
+ Objects.requireNonNull(temporal, "temporal");
Chronology chrono = temporal.query(TemporalQuery.chronology());
if (chrono == null) {
throw new DateTimeException("Unable to obtain ChronoZonedDateTime from TemporalAccessor: " + temporal.getClass());
diff --git a/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java b/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java
--- a/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java
+++ b/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java
@@ -69,7 +69,6 @@
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.io.Serializable;
-import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -232,7 +231,7 @@
if (trans != null && trans.isOverlap()) {
ZoneOffset earlierOffset = trans.getOffsetBefore();
if (earlierOffset.equals(offset) == false) {
- return new ChronoZonedDateTimeImpl<D>(dateTime, earlierOffset, zone);
+ return new ChronoZonedDateTimeImpl<>(dateTime, earlierOffset, zone);
}
}
return this;
@@ -244,7 +243,7 @@
if (trans != null) {
ZoneOffset offset = trans.getOffsetAfter();
if (offset.equals(getOffset()) == false) {
- return new ChronoZonedDateTimeImpl<D>(dateTime, offset, zone);
+ return new ChronoZonedDateTimeImpl<>(dateTime, offset, zone);
}
}
return this;
@@ -304,20 +303,14 @@
//-----------------------------------------------------------------------
@Override
- public long until(Temporal endDateTime, TemporalUnit unit) {
- if (endDateTime instanceof ChronoZonedDateTime == false) {
- throw new DateTimeException("Unable to calculate amount as objects are of two different types");
- }
+ public long until(Temporal endExclusive, TemporalUnit unit) {
@SuppressWarnings("unchecked")
- ChronoZonedDateTime<D> end = (ChronoZonedDateTime<D>) endDateTime;
- if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) {
- throw new DateTimeException("Unable to calculate amount as objects have different chronologies");
- }
+ ChronoZonedDateTime<D> end = (ChronoZonedDateTime<D>) toLocalDate().getChronology().zonedDateTime(endExclusive);
if (unit instanceof ChronoUnit) {
end = end.withZoneSameInstant(offset);
return dateTime.until(end.toLocalDateTime(), unit);
}
- return unit.between(this, endDateTime);
+ return unit.between(this, end);
}
//-----------------------------------------------------------------------
diff --git a/src/share/classes/java/time/temporal/ChronoUnit.java b/src/share/classes/java/time/temporal/ChronoUnit.java
--- a/src/share/classes/java/time/temporal/ChronoUnit.java
+++ b/src/share/classes/java/time/temporal/ChronoUnit.java
@@ -268,8 +268,8 @@
//-----------------------------------------------------------------------
@Override
- public long between(Temporal temporal1, Temporal temporal2) {
- return temporal1.until(temporal2, this);
+ public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
+ return temporal1Inclusive.until(temporal2Exclusive, this);
}
//-----------------------------------------------------------------------
diff --git a/src/share/classes/java/time/temporal/IsoFields.java b/src/share/classes/java/time/temporal/IsoFields.java
--- a/src/share/classes/java/time/temporal/IsoFields.java
+++ b/src/share/classes/java/time/temporal/IsoFields.java
@@ -684,13 +684,16 @@
}
@Override
- public long between(Temporal temporal1, Temporal temporal2) {
+ public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
+ if (temporal1Inclusive.getClass() != temporal2Exclusive.getClass()) {
+ return temporal1Inclusive.until(temporal2Exclusive, this);
+ }
switch(this) {
case WEEK_BASED_YEARS:
- return Math.subtractExact(temporal2.getLong(WEEK_BASED_YEAR),
- temporal1.getLong(WEEK_BASED_YEAR));
+ return Math.subtractExact(temporal2Exclusive.getLong(WEEK_BASED_YEAR),
+ temporal1Inclusive.getLong(WEEK_BASED_YEAR));
case QUARTER_YEARS:
- return temporal1.until(temporal2, MONTHS) / 3;
+ return temporal1Inclusive.until(temporal2Exclusive, MONTHS) / 3;
default:
throw new IllegalStateException("Unreachable");
}
diff --git a/src/share/classes/java/time/temporal/Temporal.java b/src/share/classes/java/time/temporal/Temporal.java
--- a/src/share/classes/java/time/temporal/Temporal.java
+++ b/src/share/classes/java/time/temporal/Temporal.java
@@ -374,8 +374,9 @@
* Calculates the amount of time until another temporal in terms of the specified unit.
* <p>
* This calculates the amount of time between two temporal objects
- * of the same type in terms of a single {@code TemporalUnit}.
+ * in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified temporal.
+ * The end point is converted to be of the same type as the start point if different.
* The result will be negative if the end is before the start.
* For example, the period in hours between two temporal objects can be
* calculated using {@code startTime.until(endTime, HOURS)}.
@@ -415,28 +416,33 @@
* passing {@code this} as the first argument and the input temporal as
* the second argument.
* <p>
- * In summary, implementations must behave in a manner equivalent to this code:
+ * In summary, implementations must behave in a manner equivalent to this pseudo-code:
* <pre>
- * // check input temporal is the same type as this class
+ * // convert the end temporal to the same type as this class
* if (unit instanceof ChronoUnit) {
* // if unit is supported, then calculate and return result
* // else throw UnsupportedTemporalTypeException for unsupported units
* }
- * return unit.between(this, endTemporal);
+ * return unit.between(this, convertedEndTemporal);
* </pre>
* <p>
+ * Note that the unit's {@code between} method must only be invoked if the
+ * two temporal objects have exactly the same type evaluated by {@code getClass()}.
+ * <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
*
- * @param endTemporal the end temporal, of the same type as this object, not null
+ * @param endExclusive the end temporal, converted to be of the
+ * same type as this object, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this temporal object and the specified one
* in terms of the unit; positive if the specified object is later than this one,
* negative if it is earlier than this one
- * @throws DateTimeException if the amount cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to the same type as this temporal
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
- long until(Temporal endTemporal, TemporalUnit unit);
+ long until(Temporal endExclusive, TemporalUnit unit);
}
diff --git a/src/share/classes/java/time/temporal/TemporalUnit.java b/src/share/classes/java/time/temporal/TemporalUnit.java
--- a/src/share/classes/java/time/temporal/TemporalUnit.java
+++ b/src/share/classes/java/time/temporal/TemporalUnit.java
@@ -231,7 +231,9 @@
* Calculates the amount of time between two temporal objects.
* <p>
* This calculates the amount in terms of this unit. The start and end
- * points are supplied as temporal objects and must be of the same type.
+ * points are supplied as temporal objects and must be of compatible types.
+ * The implementation will convert the second type to be an instance of the
+ * first type before the calculating the amount.
* The result will be negative if the end is before the start.
* For example, the amount in hours between two temporal objects can be
* calculated using {@code HOURS.between(startTime, endTime)}.
@@ -264,15 +266,21 @@
* If the unit is not supported an {@code UnsupportedTemporalTypeException} must be thrown.
* Implementations must not alter the specified temporal objects.
*
- * @param temporal1 the base temporal object, not null
- * @param temporal2 the other temporal object, not null
- * @return the amount of time between temporal1 and temporal2 in terms of this unit;
- * positive if temporal2 is later than temporal1, negative if earlier
- * @throws DateTimeException if the amount cannot be calculated
+ * @implSpec
+ * Implementations must begin by checking to if the two temporals have the
+ * same type. If they do not, then the result must be obtained by calling
+ * {@code temporal1Inclusive.until(temporal2Exclusive, this)}.
+ *
+ * @param temporal1Inclusive the base temporal object, not null
+ * @param temporal2Exclusive the other temporal object, not null
+ * @return the amount of time between temporal1 and temporal2Exclusive in terms of this unit;
+ * positive if temporal2Exclusive is later than temporal1, negative if earlier
+ * @throws DateTimeException if the amount cannot be calculated, or the end
+ * temporal cannot be converted to the same type as the start temporal
* @throws UnsupportedTemporalTypeException if the unit is not supported by the temporal
* @throws ArithmeticException if numeric overflow occurs
*/
- long between(Temporal temporal1, Temporal temporal2);
+ long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive);
//-----------------------------------------------------------------------
/**
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
@@ -77,6 +77,7 @@
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
@@ -863,10 +864,17 @@
assertEquals(Duration.between(end, start), Duration.between(start, end).negated());
}
- @Test(expectedExceptions=DateTimeException.class)
+ @Test
public void factory_between_TemporalTemporal_mixedTypes() {
Instant start = Instant.ofEpochSecond(1);
ZonedDateTime end = Instant.ofEpochSecond(4).atZone(ZoneOffset.UTC);
+ assertEquals(Duration.between(start, end), Duration.ofSeconds(3));
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void factory_between_TemporalTemporal_invalidMixedTypes() {
+ Instant start = Instant.ofEpochSecond(1);
+ LocalDate end = LocalDate.of(2010, 6, 20);
Duration.between(start, end);
}
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,6 +84,7 @@
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
@@ -1818,7 +1819,7 @@
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit(long seconds1, int nanos1, long seconds2, long nanos2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit(long seconds1, int nanos1, long seconds2, long nanos2, TemporalUnit unit, long expected) {
Instant i1 = Instant.ofEpochSecond(seconds1, nanos1);
Instant i2 = Instant.ofEpochSecond(seconds2, nanos2);
long amount = i1.until(i2, unit);
@@ -1826,25 +1827,46 @@
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit_negated(long seconds1, int nanos1, long seconds2, long nanos2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit_negated(long seconds1, int nanos1, long seconds2, long nanos2, TemporalUnit unit, long expected) {
Instant i1 = Instant.ofEpochSecond(seconds1, nanos1);
Instant i2 = Instant.ofEpochSecond(seconds2, nanos2);
long amount = i2.until(i1, unit);
assertEquals(amount, -expected);
}
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(long seconds1, int nanos1, long seconds2, long nanos2, TemporalUnit unit, long expected) {
+ Instant i1 = Instant.ofEpochSecond(seconds1, nanos1);
+ Instant i2 = Instant.ofEpochSecond(seconds2, nanos2);
+ long amount = unit.between(i1, i2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ Instant start = Instant.ofEpochSecond(12, 3000);
+ OffsetDateTime end = start.plusSeconds(2).atOffset(ZoneOffset.ofHours(2));
+ assertEquals(start.until(end, SECONDS), 2);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidType() {
+ Instant start = Instant.ofEpochSecond(12, 3000);
+ start.until(LocalTime.of(11, 30), SECONDS);
+ }
+
@Test(expectedExceptions = UnsupportedTemporalTypeException.class)
- public void test_periodUntil_TemporalUnit_unsupportedUnit() {
+ public void test_until_TemporalUnit_unsupportedUnit() {
TEST_12345_123456789.until(TEST_12345_123456789, MONTHS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullEnd() {
+ public void test_until_TemporalUnit_nullEnd() {
TEST_12345_123456789.until(null, HOURS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullUnit() {
+ public void test_until_TemporalUnit_nullUnit() {
TEST_12345_123456789.until(TEST_12345_123456789, null);
}
diff --git a/test/java/time/tck/java/time/TCKLocalDate.java b/test/java/time/tck/java/time/TCKLocalDate.java
--- a/test/java/time/tck/java/time/TCKLocalDate.java
+++ b/test/java/time/tck/java/time/TCKLocalDate.java
@@ -1745,29 +1745,48 @@
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit(LocalDate date1, LocalDate date2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit(LocalDate date1, LocalDate date2, TemporalUnit unit, long expected) {
long amount = date1.until(date2, unit);
assertEquals(amount, expected);
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit_negated(LocalDate date1, LocalDate date2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit_negated(LocalDate date1, LocalDate date2, TemporalUnit unit, long expected) {
long amount = date2.until(date1, unit);
assertEquals(amount, -expected);
}
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(LocalDate date1, LocalDate date2, TemporalUnit unit, long expected) {
+ long amount = unit.between(date1, date2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ LocalDate start = LocalDate.of(2010, 6, 30);
+ OffsetDateTime end = start.plusDays(2).atStartOfDay().atOffset(OFFSET_PONE);
+ assertEquals(start.until(end, DAYS), 2);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidType() {
+ LocalDate start = LocalDate.of(2010, 6, 30);
+ start.until(LocalTime.of(11, 30), DAYS);
+ }
+
@Test(expectedExceptions = UnsupportedTemporalTypeException.class)
- public void test_periodUntil_TemporalUnit_unsupportedUnit() {
+ public void test_until_TemporalUnit_unsupportedUnit() {
TEST_2007_07_15.until(TEST_2007_07_15, HOURS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullEnd() {
+ public void test_until_TemporalUnit_nullEnd() {
TEST_2007_07_15.until(null, DAYS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullUnit() {
+ public void test_until_TemporalUnit_nullUnit() {
TEST_2007_07_15.until(TEST_2007_07_15, null);
}
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
@@ -2920,24 +2920,43 @@
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit(LocalDateTime dt1, LocalDateTime dt2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit(LocalDateTime dt1, LocalDateTime dt2, TemporalUnit unit, long expected) {
long amount = dt1.until(dt2, unit);
assertEquals(amount, expected);
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit_negated(LocalDateTime dt1, LocalDateTime dt2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit_negated(LocalDateTime dt1, LocalDateTime dt2, TemporalUnit unit, long expected) {
long amount = dt2.until(dt1, unit);
assertEquals(amount, -expected);
}
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(LocalDateTime dt1, LocalDateTime dt2, TemporalUnit unit, long expected) {
+ long amount = unit.between(dt1, dt2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ LocalDateTime start = LocalDateTime.of(2010, 6, 30, 2, 30);
+ OffsetDateTime end = start.plusDays(2).atOffset(OFFSET_PONE);
+ assertEquals(start.until(end, DAYS), 2);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidType() {
+ LocalDateTime start = LocalDateTime.of(2010, 6, 30, 2, 30);
+ start.until(LocalTime.of(11, 30), DAYS);
+ }
+
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullEnd() {
+ public void test_until_TemporalUnit_nullEnd() {
TEST_2007_07_15_12_30_40_987654321.until(null, HOURS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullUnit() {
+ public void test_until_TemporalUnit_nullUnit() {
TEST_2007_07_15_12_30_40_987654321.until(TEST_2007_07_15_12_30_40_987654321, null);
}
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
@@ -2039,29 +2039,48 @@
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit(LocalTime time1, LocalTime time2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit(LocalTime time1, LocalTime time2, TemporalUnit unit, long expected) {
long amount = time1.until(time2, unit);
assertEquals(amount, expected);
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit_negated(LocalTime time1, LocalTime time2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit_negated(LocalTime time1, LocalTime time2, TemporalUnit unit, long expected) {
long amount = time2.until(time1, unit);
assertEquals(amount, -expected);
}
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(LocalTime time1, LocalTime time2, TemporalUnit unit, long expected) {
+ long amount = unit.between(time1, time2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ LocalTime start = LocalTime.of(11, 30);
+ LocalDateTime end = start.plusSeconds(2).atDate(LocalDate.of(2010, 6, 30));
+ assertEquals(start.until(end, SECONDS), 2);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidType() {
+ LocalTime start = LocalTime.of(11, 30);
+ start.until(LocalDate.of(2010, 6, 30), SECONDS);
+ }
+
@Test(expectedExceptions = UnsupportedTemporalTypeException.class)
- public void test_periodUntil_TemporalUnit_unsupportedUnit() {
+ public void test_until_TemporalUnit_unsupportedUnit() {
TEST_12_30_40_987654321.until(TEST_12_30_40_987654321, DAYS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullEnd() {
+ public void test_until_TemporalUnit_nullEnd() {
TEST_12_30_40_987654321.until(null, HOURS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullUnit() {
+ public void test_until_TemporalUnit_nullUnit() {
TEST_12_30_40_987654321.until(TEST_12_30_40_987654321, null);
}
diff --git a/test/java/time/tck/java/time/TCKOffsetDateTime.java b/test/java/time/tck/java/time/TCKOffsetDateTime.java
--- a/test/java/time/tck/java/time/TCKOffsetDateTime.java
+++ b/test/java/time/tck/java/time/TCKOffsetDateTime.java
@@ -91,6 +91,13 @@
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.FOREVER;
+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 org.testng.Assert.assertEquals;
@@ -1166,6 +1173,74 @@
}
//-----------------------------------------------------------------------
+ // until(Temporal, TemporalUnit)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="periodUntilUnit")
+ Object[][] data_untilUnit() {
+ return new Object[][] {
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 13, 1, 1, 0, OFFSET_PONE), HALF_DAYS, 1},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 2, 1, 1, 0, OFFSET_PONE), HOURS, 1},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 2, 1, 1, 0, OFFSET_PONE), MINUTES, 60},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 2, 1, 1, 0, OFFSET_PONE), SECONDS, 3600},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 2, 1, 1, 0, OFFSET_PONE), MILLIS, 3600*1000},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 2, 1, 1, 0, OFFSET_PONE), MICROS, 3600*1000*1000L},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 2, 1, 1, 0, OFFSET_PONE), NANOS, 3600*1000*1000L*1000},
+
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 14, 1, 1, 0, OFFSET_PTWO), HALF_DAYS, 1},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 3, 1, 1, 0, OFFSET_PTWO), HOURS, 1},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 3, 1, 1, 0, OFFSET_PTWO), MINUTES, 60},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 3, 1, 1, 0, OFFSET_PTWO), SECONDS, 3600},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 3, 1, 1, 0, OFFSET_PTWO), MILLIS, 3600*1000},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 3, 1, 1, 0, OFFSET_PTWO), MICROS, 3600*1000*1000L},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 6, 30, 3, 1, 1, 0, OFFSET_PTWO), NANOS, 3600*1000*1000L*1000},
+
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 7, 1, 1, 1, 0, 999999999, OFFSET_PONE), DAYS, 0},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 7, 1, 1, 1, 1, 0, OFFSET_PONE), DAYS, 1},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 8, 29, 1, 1, 1, 0, OFFSET_PONE), MONTHS, 1},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 8, 30, 1, 1, 1, 0, OFFSET_PONE), MONTHS, 2},
+ {OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE), OffsetDateTime.of(2010, 8, 31, 1, 1, 1, 0, OFFSET_PONE), MONTHS, 2},
+ };
+ }
+
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit(OffsetDateTime odt1, OffsetDateTime odt2, TemporalUnit unit, long expected) {
+ long amount = odt1.until(odt2, unit);
+ assertEquals(amount, expected);
+ }
+
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_negated(OffsetDateTime odt1, OffsetDateTime odt2, TemporalUnit unit, long expected) {
+ long amount = odt2.until(odt1, unit);
+ assertEquals(amount, -expected);
+ }
+
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(OffsetDateTime odt1, OffsetDateTime odt2, TemporalUnit unit, long expected) {
+ long amount = unit.between(odt1, odt2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ OffsetDateTime odt = OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE);
+ ZonedDateTime zdt = odt.plusSeconds(3).toZonedDateTime();
+ assertEquals(odt.until(zdt, SECONDS), 3);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidType() {
+ OffsetDateTime odt = OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE);
+ odt.until(Instant.ofEpochSecond(12), SECONDS);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidTemporalUnit() {
+ OffsetDateTime odt1 = OffsetDateTime.of(2010, 6, 30, 1, 1, 1, 0, OFFSET_PONE);
+ OffsetDateTime odt2 = OffsetDateTime.of(2010, 6, 30, 2, 1, 1, 0, OFFSET_PONE);
+ odt1.until(odt2, FOREVER);
+ }
+
+ //-----------------------------------------------------------------------
// format(DateTimeFormatter)
//-----------------------------------------------------------------------
@Test
diff --git a/test/java/time/tck/java/time/TCKOffsetTime.java b/test/java/time/tck/java/time/TCKOffsetTime.java
--- a/test/java/time/tck/java/time/TCKOffsetTime.java
+++ b/test/java/time/tck/java/time/TCKOffsetTime.java
@@ -1103,49 +1103,61 @@
// until(Temporal, TemporalUnit)
//-----------------------------------------------------------------------
@DataProvider(name="periodUntilUnit")
- Object[][] data_periodUntilUnit() {
+ Object[][] data_untilUnit() {
return new Object[][] {
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(13, 1, 1), ZoneOffset.ofHours(1)), HALF_DAYS, 1},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), HOURS, 1},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), MINUTES, 60},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), SECONDS, 3600},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), MILLIS, 3600*1000},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), MICROS, 3600*1000*1000L},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), NANOS, 3600*1000*1000L*1000},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(13, 1, 1, 0, OFFSET_PONE), HALF_DAYS, 1},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(2, 1, 1, 0, OFFSET_PONE), HOURS, 1},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(2, 1, 1, 0, OFFSET_PONE), MINUTES, 60},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(2, 1, 1, 0, OFFSET_PONE), SECONDS, 3600},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(2, 1, 1, 0, OFFSET_PONE), MILLIS, 3600*1000},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(2, 1, 1, 0, OFFSET_PONE), MICROS, 3600*1000*1000L},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(2, 1, 1, 0, OFFSET_PONE), NANOS, 3600*1000*1000L*1000},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(14, 1, 1), ZoneOffset.ofHours(2)), HALF_DAYS, 1},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), HOURS, 1},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), MINUTES, 60},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), SECONDS, 3600},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), MILLIS, 3600*1000},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), MICROS, 3600*1000*1000L},
- {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), NANOS, 3600*1000*1000L*1000},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(14, 1, 1, 0, OFFSET_PTWO), HALF_DAYS, 1},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(3, 1, 1, 0, OFFSET_PTWO), HOURS, 1},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(3, 1, 1, 0, OFFSET_PTWO), MINUTES, 60},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(3, 1, 1, 0, OFFSET_PTWO), SECONDS, 3600},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(3, 1, 1, 0, OFFSET_PTWO), MILLIS, 3600*1000},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(3, 1, 1, 0, OFFSET_PTWO), MICROS, 3600*1000*1000L},
+ {OffsetTime.of(1, 1, 1, 0, OFFSET_PONE), OffsetTime.of(3, 1, 1, 0, OFFSET_PTWO), NANOS, 3600*1000*1000L*1000},
};
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit(OffsetTime offsetTime1, OffsetTime offsetTime2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit(OffsetTime offsetTime1, OffsetTime offsetTime2, TemporalUnit unit, long expected) {
long amount = offsetTime1.until(offsetTime2, unit);
assertEquals(amount, expected);
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit_negated(OffsetTime offsetTime1, OffsetTime offsetTime2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit_negated(OffsetTime offsetTime1, OffsetTime offsetTime2, TemporalUnit unit, long expected) {
long amount = offsetTime2.until(offsetTime1, unit);
assertEquals(amount, -expected);
}
- @Test(expectedExceptions=DateTimeException.class)
- public void test_periodUntil_InvalidType() {
- OffsetTime offsetTime = OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1));
- OffsetDateTime offsetDateTime = offsetTime.atDate(LocalDate.of(1980, 2, 10));
- offsetTime.until(offsetDateTime, SECONDS);
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(OffsetTime offsetTime1, OffsetTime offsetTime2, TemporalUnit unit, long expected) {
+ long amount = unit.between(offsetTime1, offsetTime2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ OffsetTime offsetTime = OffsetTime.of(1, 1, 1, 0, OFFSET_PONE);
+ OffsetDateTime offsetDateTime = offsetTime.plusSeconds(3).atDate(LocalDate.of(1980, 2, 10));
+ assertEquals(offsetTime.until(offsetDateTime, SECONDS), 3);
}
@Test(expectedExceptions=DateTimeException.class)
- public void test_periodUntil_InvalidTemporalUnit() {
- OffsetTime offsetTime1 = OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1));
- OffsetTime offsetTime2 = OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1));
+ public void test_until_invalidType() {
+ OffsetTime offsetTime = OffsetTime.of(1, 1, 1, 0, OFFSET_PONE);
+ offsetTime.until(LocalDate.of(1980, 2, 10), SECONDS);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidTemporalUnit() {
+ OffsetTime offsetTime1 = OffsetTime.of(1, 1, 1, 0, OFFSET_PONE);
+ OffsetTime offsetTime2 = OffsetTime.of(2, 1, 1, 0, OFFSET_PONE);
offsetTime1.until(offsetTime2, MONTHS);
}
diff --git a/test/java/time/tck/java/time/TCKYear.java b/test/java/time/tck/java/time/TCKYear.java
--- a/test/java/time/tck/java/time/TCKYear.java
+++ b/test/java/time/tck/java/time/TCKYear.java
@@ -65,10 +65,8 @@
import static java.time.temporal.ChronoUnit.CENTURIES;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.DECADES;
-import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MILLENNIA;
import static java.time.temporal.ChronoUnit.MONTHS;
-import static java.time.temporal.ChronoUnit.WEEKS;
import static java.time.temporal.ChronoUnit.YEARS;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@@ -90,8 +88,8 @@
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZoneOffset;
+import java.time.chrono.IsoChronology;
import java.time.chrono.IsoEra;
-import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
@@ -248,17 +246,17 @@
//-----------------------------------------------------------------------
@Test
- public void test_factory_CalendricalObject() {
+ public void test_from_TemporalAccessor() {
assertEquals(Year.from(LocalDate.of(2007, 7, 15)), Year.of(2007));
}
@Test(expectedExceptions=DateTimeException.class)
- public void test_factory_CalendricalObject_invalid_noDerive() {
+ public void test_from_TemporalAccessor_invalid_noDerive() {
Year.from(LocalTime.of(12, 30));
}
@Test(expectedExceptions=NullPointerException.class)
- public void test_factory_CalendricalObject_null() {
+ public void test_from_TemporalAccessor_null() {
Year.from((TemporalAccessor) null);
}
@@ -616,13 +614,13 @@
};
}
- @Test(groups={"tck"}, dataProvider="plus_long_TemporalUnit")
+ @Test(dataProvider="plus_long_TemporalUnit")
public void test_plus_long_TemporalUnit(Year base, long amount, TemporalUnit unit, Year expectedYear, Class expectedEx) {
if (expectedEx == null) {
assertEquals(base.plus(amount, unit), expectedYear);
} else {
try {
- Year result = base.plus(amount, unit);
+ base.plus(amount, unit);
fail();
} catch (Exception ex) {
assertTrue(expectedEx.isInstance(ex));
@@ -748,7 +746,7 @@
};
}
- @Test(groups={"tck"}, dataProvider="minus_long_TemporalUnit")
+ @Test(dataProvider="minus_long_TemporalUnit")
public void test_minus_long_TemporalUnit(Year base, long amount, TemporalUnit unit, Year expectedYear, Class expectedEx) {
if (expectedEx == null) {
assertEquals(base.minus(amount, unit), expectedYear);
@@ -807,7 +805,7 @@
//-----------------------------------------------------------------------
// with(TemporalField, long)
//-----------------------------------------------------------------------
- @Test(groups={"tck"})
+ @Test
public void test_with() {
Year base = Year.of(5);
Year result = base.with(ChronoField.ERA, 0);
@@ -942,29 +940,48 @@
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit(Year year1, Year year2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit(Year year1, Year year2, TemporalUnit unit, long expected) {
long amount = year1.until(year2, unit);
assertEquals(amount, expected);
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit_negated(Year year1, Year year2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit_negated(Year year1, Year year2, TemporalUnit unit, long expected) {
long amount = year2.until(year1, unit);
assertEquals(amount, -expected);
}
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(Year year1, Year year2, TemporalUnit unit, long expected) {
+ long amount = unit.between(year1, year2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ Year start = Year.of(2010);
+ YearMonth end = start.plusYears(2).atMonth(Month.APRIL);
+ assertEquals(start.until(end, YEARS), 2);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidType() {
+ Year start = Year.of(2010);
+ start.until(LocalTime.of(11, 30), YEARS);
+ }
+
@Test(expectedExceptions = UnsupportedTemporalTypeException.class)
- public void test_periodUntil_TemporalUnit_unsupportedUnit() {
+ public void test_until_TemporalUnit_unsupportedUnit() {
TEST_2008.until(TEST_2008, MONTHS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullEnd() {
+ public void test_until_TemporalUnit_nullEnd() {
TEST_2008.until(null, DAYS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullUnit() {
+ public void test_until_TemporalUnit_nullUnit() {
TEST_2008.until(TEST_2008, null);
}
diff --git a/test/java/time/tck/java/time/TCKYearMonth.java b/test/java/time/tck/java/time/TCKYearMonth.java
--- a/test/java/time/tck/java/time/TCKYearMonth.java
+++ b/test/java/time/tck/java/time/TCKYearMonth.java
@@ -70,7 +70,6 @@
import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MILLENNIA;
import static java.time.temporal.ChronoUnit.MONTHS;
-import static java.time.temporal.ChronoUnit.WEEKS;
import static java.time.temporal.ChronoUnit.YEARS;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@@ -288,17 +287,17 @@
//-----------------------------------------------------------------------
@Test
- public void test_factory_CalendricalObject() {
+ public void test_from_TemporalAccessor() {
assertEquals(YearMonth.from(LocalDate.of(2007, 7, 15)), YearMonth.of(2007, 7));
}
@Test(expectedExceptions=DateTimeException.class)
- public void test_factory_CalendricalObject_invalid_noDerive() {
+ public void test_from_TemporalAccessor_invalid_noDerive() {
YearMonth.from(LocalTime.of(12, 30));
}
@Test(expectedExceptions=NullPointerException.class)
- public void test_factory_CalendricalObject_null() {
+ public void test_from_TemporalAccessor_null() {
YearMonth.from((TemporalAccessor) null);
}
@@ -786,7 +785,7 @@
};
}
- @Test(groups={"tck"}, dataProvider="plus_long_TemporalUnit")
+ @Test(dataProvider="plus_long_TemporalUnit")
public void test_plus_long_TemporalUnit(YearMonth base, long amount, TemporalUnit unit, YearMonth expectedYearMonth, Class expectedEx) {
if (expectedEx == null) {
assertEquals(base.plus(amount, unit), expectedYearMonth);
@@ -838,7 +837,7 @@
};
}
- @Test(groups={"tck"}, dataProvider="plus_TemporalAmount")
+ @Test(dataProvider="plus_TemporalAmount")
public void test_plus_TemporalAmount(YearMonth base, TemporalAmount temporalAmount, YearMonth expectedYearMonth, Class expectedEx) {
if (expectedEx == null) {
assertEquals(base.plus(temporalAmount), expectedYearMonth);
@@ -1001,7 +1000,7 @@
};
}
- @Test(groups={"tck"}, dataProvider="minus_long_TemporalUnit")
+ @Test(dataProvider="minus_long_TemporalUnit")
public void test_minus_long_TemporalUnit(YearMonth base, long amount, TemporalUnit unit, YearMonth expectedYearMonth, Class expectedEx) {
if (expectedEx == null) {
assertEquals(base.minus(amount, unit), expectedYearMonth);
@@ -1053,7 +1052,7 @@
};
}
- @Test(groups={"tck"}, dataProvider="minus_TemporalAmount")
+ @Test(dataProvider="minus_TemporalAmount")
public void test_minus_TemporalAmount(YearMonth base, TemporalAmount temporalAmount, YearMonth expectedYearMonth, Class expectedEx) {
if (expectedEx == null) {
assertEquals(base.minus(temporalAmount), expectedYearMonth);
@@ -1261,29 +1260,48 @@
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit(YearMonth ym1, YearMonth ym2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit(YearMonth ym1, YearMonth ym2, TemporalUnit unit, long expected) {
long amount = ym1.until(ym2, unit);
assertEquals(amount, expected);
}
@Test(dataProvider="periodUntilUnit")
- public void test_periodUntil_TemporalUnit_negated(YearMonth ym1, YearMonth ym2, TemporalUnit unit, long expected) {
+ public void test_until_TemporalUnit_negated(YearMonth ym1, YearMonth ym2, TemporalUnit unit, long expected) {
long amount = ym2.until(ym1, unit);
assertEquals(amount, -expected);
}
+ @Test(dataProvider="periodUntilUnit")
+ public void test_until_TemporalUnit_between(YearMonth ym1, YearMonth ym2, TemporalUnit unit, long expected) {
+ long amount = unit.between(ym1, ym2);
+ assertEquals(amount, expected);
+ }
+
+ @Test
+ public void test_until_convertedType() {
+ YearMonth start = YearMonth.of(2010, 6);
+ LocalDate end = start.plusMonths(2).atDay(12);
+ assertEquals(start.until(end, MONTHS), 2);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_until_invalidType() {
+ YearMonth start = YearMonth.of(2010, 6);
+ start.until(LocalTime.of(11, 30), MONTHS);
+ }
+
@Test(expectedExceptions = UnsupportedTemporalTypeException.class)
- public void test_periodUntil_TemporalUnit_unsupportedUnit() {
+ public void test_until_TemporalUnit_unsupportedUnit() {
TEST_2008_06.until(TEST_2008_06, HOURS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullEnd() {
+ public void test_until_TemporalUnit_nullEnd() {
TEST_2008_06.until(null, DAYS);
}
@Test(expectedExceptions = NullPointerException.class)
- public void test_periodUntil_TemporalUnit_nullUnit() {
+ public void test_until_TemporalUnit_nullUnit() {
TEST_2008_06.until(TEST_2008_06, null);
}
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
@@ -2049,7 +2049,7 @@
// compare results to OffsetDateTime.until, especially wrt dates
@Test(dataProvider="plusDays")
- public void test_periodUntil_days(ZonedDateTime base, long expected, ZonedDateTime end) {
+ public void test_until_days(ZonedDateTime base, long expected, ZonedDateTime end) {
if (base.toLocalTime().equals(end.toLocalTime()) == false) {
return; // avoid DST gap input values
}
@@ -2057,27 +2057,27 @@
}
@Test(dataProvider="plusTime")
- public void test_periodUntil_hours(ZonedDateTime base, long expected, ZonedDateTime end) {
+ public void test_until_hours(ZonedDateTime base, long expected, ZonedDateTime end) {
assertEquals(base.until(end, HOURS), expected);
}
@Test(dataProvider="plusTime")
- public void test_periodUntil_minutes(ZonedDateTime base, long expected, ZonedDateTime end) {
+ public void test_until_minutes(ZonedDateTime base, long expected, ZonedDateTime end) {
assertEquals(base.until(end, MINUTES), expected * 60);
}
@Test(dataProvider="plusTime")
- public void test_periodUntil_seconds(ZonedDateTime base, long expected, ZonedDateTime end) {
+ public void test_until_seconds(ZonedDateTime base, long expected, ZonedDateTime end) {
assertEquals(base.until(end, SECONDS), expected * 3600);
}
@Test(dataProvider="plusTime")
- public void test_periodUntil_nanos(ZonedDateTime base, long expected, ZonedDateTime end) {
+ public void test_until_nanos(ZonedDateTime base, long expected, ZonedDateTime end) {
assertEquals(base.until(end, NANOS), expected * 3600_000_000_000L);
}
@Test
- public void test_periodUntil_parisLondon() {
+ public void test_until_parisLondon() {
ZonedDateTime midnightLondon = LocalDate.of(2012, 6, 28).atStartOfDay(ZONE_LONDON);
ZonedDateTime midnightParis1 = LocalDate.of(2012, 6, 29).atStartOfDay(ZONE_PARIS);
ZonedDateTime oneAm1 = LocalDateTime.of(2012, 6, 29, 1, 0).atZone(ZONE_PARIS);
@@ -2093,7 +2093,7 @@
}
@Test
- public void test_periodUntil_gap() {
+ public void test_until_gap() {
ZonedDateTime before = TEST_PARIS_GAP_2008_03_30_02_30.withHour(0).withMinute(0).atZone(ZONE_PARIS);
ZonedDateTime after = TEST_PARIS_GAP_2008_03_30_02_30.withHour(0).withMinute(0).plusDays(1).atZone(ZONE_PARIS);
@@ -2102,7 +2102,7 @@
}
@Test
- public void test_periodUntil_overlap() {
+ public void test_until_overlap() {
ZonedDateTime before = TEST_PARIS_OVERLAP_2008_10_26_02_30.withHour(0).withMinute(0).atZone(ZONE_PARIS);
ZonedDateTime after = TEST_PARIS_OVERLAP_2008_10_26_02_30.withHour(0).withMinute(0).plusDays(1).atZone(ZONE_PARIS);
@@ -2111,17 +2111,17 @@
}
@Test(expectedExceptions=DateTimeException.class)
- public void test_periodUntil_differentType() {
+ public void test_until_differentType() {
TEST_DATE_TIME_PARIS.until(TEST_LOCAL_2008_06_30_11_30_59_500, DAYS);
}
@Test(expectedExceptions=NullPointerException.class)
- public void test_periodUntil_nullTemporal() {
+ public void test_until_nullTemporal() {
TEST_DATE_TIME_PARIS.until(null, DAYS);
}
@Test(expectedExceptions=NullPointerException.class)
- public void test_periodUntil_nullUnit() {
+ public void test_until_nullUnit() {
TEST_DATE_TIME_PARIS.until(TEST_DATE_TIME_PARIS, null);
}
diff --git a/test/java/time/tck/java/time/chrono/CopticDate.java b/test/java/time/tck/java/time/chrono/CopticDate.java
--- a/test/java/time/tck/java/time/chrono/CopticDate.java
+++ b/test/java/time/tck/java/time/chrono/CopticDate.java
@@ -297,18 +297,12 @@
}
@Override
- public long until(Temporal endDateTime, TemporalUnit unit) {
- if (endDateTime instanceof ChronoLocalDate == false) {
- throw new DateTimeException("Unable to calculate period between objects of two different types");
- }
- ChronoLocalDate end = (ChronoLocalDate) endDateTime;
- if (getChronology().equals(end.getChronology()) == false) {
- throw new DateTimeException("Unable to calculate period between two different chronologies");
- }
+ public long until(Temporal endExclusive, TemporalUnit unit) {
+ CopticDate end = getChronology().date(endExclusive);
if (unit instanceof ChronoUnit) {
return LocalDate.from(this).until(end, unit); // TODO: this is wrong
}
- return unit.between(this, endDateTime);
+ return unit.between(this, end);
}
@Override
diff --git a/test/java/time/tck/java/time/temporal/TCKIsoFields.java b/test/java/time/tck/java/time/temporal/TCKIsoFields.java
--- a/test/java/time/tck/java/time/temporal/TCKIsoFields.java
+++ b/test/java/time/tck/java/time/temporal/TCKIsoFields.java
@@ -70,11 +70,13 @@
import java.time.DayOfWeek;
import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.time.temporal.IsoFields;
+import java.time.temporal.Temporal;
import java.time.temporal.ValueRange;
import org.testng.annotations.DataProvider;
@@ -276,14 +278,21 @@
{LocalDate.of(2000, 1, 1), LocalDate.of(1998, 12, 31), -4},
{LocalDate.of(2000, 1, 1), LocalDate.of(1998, 10, 2), -4},
{LocalDate.of(2000, 1, 1), LocalDate.of(1998, 10, 1), -5},
+
+ {LocalDate.of(2000, 1, 1), LocalDateTime.of(2001, 4, 5, 0, 0), 5},
};
}
@Test(dataProvider="quartersBetween")
- public void test_quarters_between(LocalDate start, LocalDate end, long expected) {
+ public void test_quarters_between(LocalDate start, Temporal end, long expected) {
assertEquals(IsoFields.QUARTER_YEARS.between(start, end), expected);
}
+ @Test(dataProvider="quartersBetween")
+ public void test_quarters_between_until(LocalDate start, Temporal end, long expected) {
+ assertEquals(start.until(end, IsoFields.QUARTER_YEARS), expected);
+ }
+
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
@JeremyBetts
Copy link

looks good

@RogerRiggs
Copy link

Line 143: should Objects.requireNonNull(unit, "unit"); be retained? Though the switch will throw NPE.

Line 919, 920: temporal1 should be temporal1Inclusive

Otherwise, looks ok

@jodastephen
Copy link
Author

NotNull check will fall through to a standard method invocation NPE uniquely identified by the stack trace, so its fine left out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment