From 74c0d1a3dd159db90199257abbff4dad6e55050a Mon Sep 17 00:00:00 2001 From: rriggs Date: Thu, 26 Sep 2013 23:05:29 -0700 Subject: [PATCH] 8025720: Separate temporal interface layer Summary: Remove ZoneId and Chronology from TemporalField interface Reviewed-by: sherman Contributed-by: scolebourne@joda.org --- .../classes/java/time/format/Parsed.java | 2 +- .../classes/java/time/temporal/IsoFields.java | 13 +++++++++-- .../java/time/temporal/JulianFields.java | 7 +++--- .../java/time/temporal/TemporalField.java | 23 +++++++++++-------- .../java/time/temporal/WeekFields.java | 9 ++++---- .../time/format/TCKDateTimeParseResolver.java | 12 ++++------ 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/share/classes/java/time/format/Parsed.java b/src/share/classes/java/time/format/Parsed.java index 908c7deca..a86697a31 100644 --- a/src/share/classes/java/time/format/Parsed.java +++ b/src/share/classes/java/time/format/Parsed.java @@ -262,7 +262,7 @@ final class Parsed implements TemporalAccessor { while (changedCount < 50) { for (Map.Entry entry : fieldValues.entrySet()) { TemporalField targetField = entry.getKey(); - TemporalAccessor resolvedObject = targetField.resolve(fieldValues, chrono, zone, resolverStyle); + TemporalAccessor resolvedObject = targetField.resolve(fieldValues, this, resolverStyle); if (resolvedObject != null) { if (resolvedObject instanceof ChronoZonedDateTime) { ChronoZonedDateTime czdt = (ChronoZonedDateTime) resolvedObject; diff --git a/src/share/classes/java/time/temporal/IsoFields.java b/src/share/classes/java/time/temporal/IsoFields.java index bb19c2998..e8ccff15f 100644 --- a/src/share/classes/java/time/temporal/IsoFields.java +++ b/src/share/classes/java/time/temporal/IsoFields.java @@ -69,6 +69,7 @@ import static java.time.temporal.ChronoUnit.MONTHS; import static java.time.temporal.ChronoUnit.WEEKS; import static java.time.temporal.ChronoUnit.YEARS; +import java.time.DateTimeException; import java.time.Duration; import java.time.LocalDate; import java.time.ZoneId; @@ -343,7 +344,7 @@ public final class IsoFields { } @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { Long yearLong = fieldValues.get(YEAR); Long qoyLong = fieldValues.get(QUARTER_OF_YEAR); if (yearLong == null || qoyLong == null) { @@ -351,6 +352,7 @@ public final class IsoFields { } int y = YEAR.checkValidIntValue(yearLong); // always validate long doq = fieldValues.get(DAY_OF_QUARTER); + ensureIso(partialTemporal); LocalDate date; if (resolverStyle == ResolverStyle.LENIENT) { date = LocalDate.of(y, 1, 1).plusMonths(Math.multiplyExact(Math.subtractExact(qoyLong, 1), 3)); @@ -464,7 +466,7 @@ public final class IsoFields { } @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { Long wbyLong = fieldValues.get(WEEK_BASED_YEAR); Long dowLong = fieldValues.get(DAY_OF_WEEK); if (wbyLong == null || dowLong == null) { @@ -472,6 +474,7 @@ public final class IsoFields { } int wby = WEEK_BASED_YEAR.range().checkValidIntValue(wbyLong, WEEK_BASED_YEAR); // always validate long wowby = fieldValues.get(WEEK_OF_WEEK_BASED_YEAR); + ensureIso(partialTemporal); LocalDate date = LocalDate.of(wby, 1, 4); if (resolverStyle == ResolverStyle.LENIENT) { long dow = dowLong; // unvalidated @@ -568,6 +571,12 @@ public final class IsoFields { return Chronology.from(temporal).equals(IsoChronology.INSTANCE); } + private static void ensureIso(TemporalAccessor temporal) { + if (isIso(temporal) == false) { + throw new DateTimeException("Resolve requires IsoChronology"); + } + } + private static ValueRange getWeekRange(LocalDate date) { int wby = getWeekBasedYear(date); date = date.withDayOfYear(1).withYear(wby); diff --git a/src/share/classes/java/time/temporal/JulianFields.java b/src/share/classes/java/time/temporal/JulianFields.java index 326f20d22..f950d8720 100644 --- a/src/share/classes/java/time/temporal/JulianFields.java +++ b/src/share/classes/java/time/temporal/JulianFields.java @@ -291,13 +291,14 @@ public final class JulianFields { //----------------------------------------------------------------------- @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { long value = fieldValues.remove(this); + Chronology chrono = Chronology.from(partialTemporal); if (resolverStyle == ResolverStyle.LENIENT) { - return chronology.dateEpochDay(Math.subtractExact(value, offset)); + return chrono.dateEpochDay(Math.subtractExact(value, offset)); } range().checkValidValue(value, this); - return chronology.dateEpochDay(value - offset); + return chrono.dateEpochDay(value - offset); } //----------------------------------------------------------------------- diff --git a/src/share/classes/java/time/temporal/TemporalField.java b/src/share/classes/java/time/temporal/TemporalField.java index e75773451..51903ede3 100644 --- a/src/share/classes/java/time/temporal/TemporalField.java +++ b/src/share/classes/java/time/temporal/TemporalField.java @@ -62,7 +62,6 @@ package java.time.temporal; import java.time.DateTimeException; -import java.time.ZoneId; import java.time.chrono.Chronology; import java.time.format.ResolverStyle; import java.util.Locale; @@ -338,6 +337,13 @@ public interface TemporalField { * complete {@code LocalDate}. The resolve method will remove all three * fields from the map before returning the {@code LocalDate}. *

+ * A partially complete temporal is used to allow the chronology and zone + * to be queried. In general, only the chronology will be needed. + * Querying items other than the zone or chronology is undefined and + * must not be relied on. + * The behavior of other methods such as {@code get}, {@code getLong}, + * {@code range} and {@code isSupported} is unpredictable and the results undefined. + *

* If resolution should be possible, but the data is invalid, the resolver * style should be used to determine an appropriate level of leniency, which * may require throwing a {@code DateTimeException} or {@code ArithmeticException}. @@ -350,16 +356,14 @@ public interface TemporalField { * instances that can produce a date, such as {@code EPOCH_DAY}. *

* Not all {@code TemporalAccessor} implementations are accepted as return values. - * Implementations must accept {@code ChronoLocalDate}, {@code ChronoLocalDateTime}, - * {@code ChronoZonedDateTime} and {@code LocalTime}. - *

- * The zone is not normally required for resolution, but is provided for completeness. + * Implementations that call this method must accept {@code ChronoLocalDate}, + * {@code ChronoLocalDateTime}, {@code ChronoZonedDateTime} and {@code LocalTime}. *

* The default implementation must return null. * * @param fieldValues the map of fields to values, which can be updated, not null - * @param chronology the effective chronology, not null - * @param zone the effective zone, not null + * @param partialTemporal the partially complete temporal to query for zone and + * chronology; querying for other things is undefined and not recommended, not null * @param resolverStyle the requested type of resolve, not null * @return the resolved temporal object; null if resolving only * changed the map, or no resolve occurred @@ -368,8 +372,9 @@ public interface TemporalField { * by querying a field on the temporal without first checking if it is supported */ default TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, + TemporalAccessor partialTemporal, + ResolverStyle resolverStyle) { return null; } diff --git a/src/share/classes/java/time/temporal/WeekFields.java b/src/share/classes/java/time/temporal/WeekFields.java index b3eb13834..0edfa73e2 100644 --- a/src/share/classes/java/time/temporal/WeekFields.java +++ b/src/share/classes/java/time/temporal/WeekFields.java @@ -892,7 +892,7 @@ public final class WeekFields implements Serializable { @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { final long value = fieldValues.get(this); final int newValue = Math.toIntExact(value); // broad limit makes overflow checking lighter // first convert localized day-of-week to ISO day-of-week @@ -915,19 +915,20 @@ public final class WeekFields implements Serializable { int dow = localizedDayOfWeek(isoDow); // build date + Chronology chrono = Chronology.from(partialTemporal); if (fieldValues.containsKey(YEAR)) { int year = YEAR.checkValidIntValue(fieldValues.get(YEAR)); // validate if (rangeUnit == MONTHS && fieldValues.containsKey(MONTH_OF_YEAR)) { // week-of-month long month = fieldValues.get(MONTH_OF_YEAR); // not validated yet - return resolveWoM(fieldValues, chronology, year, month, newValue, dow, resolverStyle); + return resolveWoM(fieldValues, chrono, year, month, newValue, dow, resolverStyle); } if (rangeUnit == YEARS) { // week-of-year - return resolveWoY(fieldValues, chronology, year, newValue, dow, resolverStyle); + return resolveWoY(fieldValues, chrono, year, newValue, dow, resolverStyle); } } else if ((rangeUnit == WEEK_BASED_YEARS || rangeUnit == FOREVER) && fieldValues.containsKey(weekDef.weekBasedYear) && fieldValues.containsKey(weekDef.weekOfWeekBasedYear)) { // week-of-week-based-year and year-of-week-based-year - return resolveWBY(fieldValues, chronology, dow, resolverStyle); + return resolveWBY(fieldValues, chrono, dow, resolverStyle); } return null; } diff --git a/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java b/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java index 4ef01317b..b99d9bb47 100644 --- a/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java +++ b/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java @@ -927,8 +927,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { return LocalTime.MIDNIGHT.plusNanos(fieldValues.remove(this)); } }; @@ -979,8 +978,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { fieldValues.remove(this); return LocalDateTime.of(2010, 6, 30, 12, 30); } @@ -1032,8 +1030,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { return ThaiBuddhistChronology.INSTANCE.dateNow(); } }; @@ -1082,8 +1079,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { return ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, ZoneId.of("Europe/Paris")); } }; -- GitLab