提交 ac795f43 编写于 作者: S sherman

8033662: DateTimeFormatter parsing ignores withZone()

Summary: to include the set "zone" in resolved result
Reviewed-by: sherman, chegar
上级 4ef20345
...@@ -1934,8 +1934,8 @@ public final class DateTimeFormatter { ...@@ -1934,8 +1934,8 @@ public final class DateTimeFormatter {
*/ */
private TemporalAccessor parseResolved0(final CharSequence text, final ParsePosition position) { private TemporalAccessor parseResolved0(final CharSequence text, final ParsePosition position) {
ParsePosition pos = (position != null ? position : new ParsePosition(0)); ParsePosition pos = (position != null ? position : new ParsePosition(0));
Parsed unresolved = parseUnresolved0(text, pos); DateTimeParseContext context = parseUnresolved0(text, pos);
if (unresolved == null || pos.getErrorIndex() >= 0 || (position == null && pos.getIndex() < text.length())) { if (context == null || pos.getErrorIndex() >= 0 || (position == null && pos.getIndex() < text.length())) {
String abbr; String abbr;
if (text.length() > 64) { if (text.length() > 64) {
abbr = text.subSequence(0, 64).toString() + "..."; abbr = text.subSequence(0, 64).toString() + "...";
...@@ -1950,7 +1950,7 @@ public final class DateTimeFormatter { ...@@ -1950,7 +1950,7 @@ public final class DateTimeFormatter {
pos.getIndex(), text, pos.getIndex()); pos.getIndex(), text, pos.getIndex());
} }
} }
return unresolved.resolve(resolverStyle, resolverFields); return context.toResolved(resolverStyle, resolverFields);
} }
/** /**
...@@ -1993,10 +1993,14 @@ public final class DateTimeFormatter { ...@@ -1993,10 +1993,14 @@ public final class DateTimeFormatter {
* @throws IndexOutOfBoundsException if the position is invalid * @throws IndexOutOfBoundsException if the position is invalid
*/ */
public TemporalAccessor parseUnresolved(CharSequence text, ParsePosition position) { public TemporalAccessor parseUnresolved(CharSequence text, ParsePosition position) {
return parseUnresolved0(text, position); DateTimeParseContext context = parseUnresolved0(text, position);
if (context == null) {
return null;
}
return context.toUnresolved();
} }
private Parsed parseUnresolved0(CharSequence text, ParsePosition position) { private DateTimeParseContext parseUnresolved0(CharSequence text, ParsePosition position) {
Objects.requireNonNull(text, "text"); Objects.requireNonNull(text, "text");
Objects.requireNonNull(position, "position"); Objects.requireNonNull(position, "position");
DateTimeParseContext context = new DateTimeParseContext(this); DateTimeParseContext context = new DateTimeParseContext(this);
...@@ -2007,7 +2011,7 @@ public final class DateTimeFormatter { ...@@ -2007,7 +2011,7 @@ public final class DateTimeFormatter {
return null; return null;
} }
position.setIndex(pos); // errorIndex not updated from input position.setIndex(pos); // errorIndex not updated from input
return context.toParsed(); return context;
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
...@@ -2128,23 +2132,23 @@ public final class DateTimeFormatter { ...@@ -2128,23 +2132,23 @@ public final class DateTimeFormatter {
@Override @Override
public Object parseObject(String text, ParsePosition pos) { public Object parseObject(String text, ParsePosition pos) {
Objects.requireNonNull(text, "text"); Objects.requireNonNull(text, "text");
Parsed unresolved; DateTimeParseContext context;
try { try {
unresolved = formatter.parseUnresolved0(text, pos); context = formatter.parseUnresolved0(text, pos);
} catch (IndexOutOfBoundsException ex) { } catch (IndexOutOfBoundsException ex) {
if (pos.getErrorIndex() < 0) { if (pos.getErrorIndex() < 0) {
pos.setErrorIndex(0); pos.setErrorIndex(0);
} }
return null; return null;
} }
if (unresolved == null) { if (context == null) {
if (pos.getErrorIndex() < 0) { if (pos.getErrorIndex() < 0) {
pos.setErrorIndex(0); pos.setErrorIndex(0);
} }
return null; return null;
} }
try { try {
TemporalAccessor resolved = unresolved.resolve(formatter.resolverStyle, formatter.resolverFields); TemporalAccessor resolved = context.toResolved(formatter.resolverStyle, formatter.resolverFields);
if (parseType == null) { if (parseType == null) {
return resolved; return resolved;
} }
......
...@@ -64,10 +64,12 @@ package java.time.format; ...@@ -64,10 +64,12 @@ package java.time.format;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.chrono.Chronology; import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology; import java.time.chrono.IsoChronology;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField; import java.time.temporal.TemporalField;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
...@@ -77,8 +79,8 @@ import java.util.function.Consumer; ...@@ -77,8 +79,8 @@ import java.util.function.Consumer;
* It has the ability to store and retrieve the parsed values and manage optional segments. * It has the ability to store and retrieve the parsed values and manage optional segments.
* It also provides key information to the parsing methods. * It also provides key information to the parsing methods.
* <p> * <p>
* Once parsing is complete, the {@link #toParsed()} is used to obtain the data. * Once parsing is complete, the {@link #toUnresolved()} is used to obtain the unresolved
* It contains a method to resolve the separate parsed fields into meaningful values. * result data. The {@link #toResolved()} is used to obtain the resolved result.
* *
* @implSpec * @implSpec
* This class is a mutable context intended for use from a single thread. * This class is a mutable context intended for use from a single thread.
...@@ -309,16 +311,27 @@ final class DateTimeParseContext { ...@@ -309,16 +311,27 @@ final class DateTimeParseContext {
} }
/** /**
* Gets the result of the parse. * Gets the unresolved result of the parse.
* *
* @return the result of the parse, not null * @return the result of the parse, not null
*/ */
Parsed toParsed() { Parsed toUnresolved() {
return currentParsed();
}
/**
* Gets the resolved result of the parse.
*
* @return the result of the parse, not null
*/
TemporalAccessor toResolved(ResolverStyle resolverStyle, Set<TemporalField> resolverFields) {
Parsed parsed = currentParsed(); Parsed parsed = currentParsed();
parsed.effectiveChrono = getEffectiveChronology(); parsed.chrono = getEffectiveChronology();
return parsed; parsed.zone = (parsed.zone != null ? parsed.zone : formatter.getZone());
return parsed.resolve(resolverStyle, resolverFields);
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
/** /**
* Gets the first value that was parsed for the specified field. * Gets the first value that was parsed for the specified field.
......
...@@ -135,10 +135,6 @@ final class Parsed implements TemporalAccessor { ...@@ -135,10 +135,6 @@ final class Parsed implements TemporalAccessor {
* Whether a leap-second is parsed. * Whether a leap-second is parsed.
*/ */
boolean leapSecond; boolean leapSecond;
/**
* The effective chronology.
*/
Chronology effectiveChrono;
/** /**
* The resolver style to use. * The resolver style to use.
*/ */
...@@ -241,7 +237,6 @@ final class Parsed implements TemporalAccessor { ...@@ -241,7 +237,6 @@ final class Parsed implements TemporalAccessor {
fieldValues.keySet().retainAll(resolverFields); fieldValues.keySet().retainAll(resolverFields);
} }
this.resolverStyle = resolverStyle; this.resolverStyle = resolverStyle;
chrono = effectiveChrono;
resolveFields(); resolveFields();
resolveTimeLenient(); resolveTimeLenient();
crossCheck(); crossCheck();
...@@ -266,14 +261,16 @@ final class Parsed implements TemporalAccessor { ...@@ -266,14 +261,16 @@ final class Parsed implements TemporalAccessor {
TemporalAccessor resolvedObject = targetField.resolve(fieldValues, this, resolverStyle); TemporalAccessor resolvedObject = targetField.resolve(fieldValues, this, resolverStyle);
if (resolvedObject != null) { if (resolvedObject != null) {
if (resolvedObject instanceof ChronoZonedDateTime) { if (resolvedObject instanceof ChronoZonedDateTime) {
ChronoZonedDateTime<?> czdt = (ChronoZonedDateTime) resolvedObject; ChronoZonedDateTime<?> czdt = (ChronoZonedDateTime<?>) resolvedObject;
if (zone.equals(czdt.getZone()) == false) { if (zone == null) {
zone = czdt.getZone();
} else if (zone.equals(czdt.getZone()) == false) {
throw new DateTimeException("ChronoZonedDateTime must use the effective parsed zone: " + zone); throw new DateTimeException("ChronoZonedDateTime must use the effective parsed zone: " + zone);
} }
resolvedObject = czdt.toLocalDateTime(); resolvedObject = czdt.toLocalDateTime();
} }
if (resolvedObject instanceof ChronoLocalDateTime) { if (resolvedObject instanceof ChronoLocalDateTime) {
ChronoLocalDateTime<?> cldt = (ChronoLocalDateTime) resolvedObject; ChronoLocalDateTime<?> cldt = (ChronoLocalDateTime<?>) resolvedObject;
updateCheckConflict(cldt.toLocalTime(), Period.ZERO); updateCheckConflict(cldt.toLocalTime(), Period.ZERO);
updateCheckConflict(cldt.toLocalDate()); updateCheckConflict(cldt.toLocalDate());
changedCount++; changedCount++;
......
...@@ -90,9 +90,6 @@ import static java.time.temporal.ChronoField.SECOND_OF_DAY; ...@@ -90,9 +90,6 @@ import static java.time.temporal.ChronoField.SECOND_OF_DAY;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE; import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import static java.time.temporal.ChronoField.YEAR; import static java.time.temporal.ChronoField.YEAR;
import static java.time.temporal.ChronoField.YEAR_OF_ERA; 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.NANOS;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail; import static org.testng.Assert.fail;
...@@ -102,13 +99,17 @@ import java.time.LocalTime; ...@@ -102,13 +99,17 @@ import java.time.LocalTime;
import java.time.Period; import java.time.Period;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.chrono.Chronology; import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.time.chrono.ChronoZonedDateTime;
import java.time.chrono.IsoChronology;
import java.time.chrono.MinguoChronology;
import java.time.chrono.MinguoDate;
import java.time.chrono.ThaiBuddhistChronology; import java.time.chrono.ThaiBuddhistChronology;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle; import java.time.format.ResolverStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.IsoFields; import java.time.temporal.IsoFields;
import java.time.temporal.Temporal; import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
...@@ -129,6 +130,9 @@ public class TCKDateTimeParseResolver { ...@@ -129,6 +130,9 @@ public class TCKDateTimeParseResolver {
// TODO: tests with weird TenporalField implementations // TODO: tests with weird TenporalField implementations
// TODO: tests with non-ISO chronologies // TODO: tests with non-ISO chronologies
private static final ZoneId EUROPE_ATHENS = ZoneId.of("Europe/Athens");
private static final ZoneId EUROPE_PARIS = ZoneId.of("Europe/Paris");
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
@DataProvider(name="resolveOneNoChange") @DataProvider(name="resolveOneNoChange")
Object[][] data_resolveOneNoChange() { Object[][] data_resolveOneNoChange() {
...@@ -886,161 +890,231 @@ public class TCKDateTimeParseResolver { ...@@ -886,161 +890,231 @@ public class TCKDateTimeParseResolver {
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// SPEC: DateTimeFormatter.withChronology()
@Test @Test
public void test_fieldResolvesToLocalTime() { public void test_withChronology_noOverride() {
TemporalField field = new TemporalField() { DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
@Override TemporalAccessor accessor = f.parse("");
public TemporalUnit getBaseUnit() { assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
throw new UnsupportedOperationException(); assertEquals(accessor.query(TemporalQueries.localTime()), null);
} assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
@Override
public TemporalUnit getRangeUnit() {
throw new UnsupportedOperationException();
}
@Override
public ValueRange range() {
throw new UnsupportedOperationException();
} }
@Override
public boolean isDateBased() { @Test
throw new UnsupportedOperationException(); public void test_withChronology_override() {
DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
f = f.withChronology(MinguoChronology.INSTANCE);
TemporalAccessor accessor = f.parse("");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
} }
@Override
public boolean isTimeBased() { @Test
throw new UnsupportedOperationException(); public void test_withChronology_parsedChronology_noOverride() {
DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendChronologyId().toFormatter();
TemporalAccessor accessor = f.parse("ThaiBuddhist");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.chronology()), ThaiBuddhistChronology.INSTANCE);
} }
@Override
public boolean isSupportedBy(TemporalAccessor temporal) { @Test
throw new UnsupportedOperationException(); public void test_withChronology_parsedChronology_override() {
DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendChronologyId().toFormatter();
f = f.withChronology(MinguoChronology.INSTANCE);
TemporalAccessor accessor = f.parse("ThaiBuddhist");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.chronology()), ThaiBuddhistChronology.INSTANCE);
} }
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) { //-----------------------------------------------------------------------
throw new UnsupportedOperationException(); // SPEC: DateTimeFormatter.withZone()
@Test
public void test_withZone_noOverride() {
DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
TemporalAccessor accessor = f.parse("");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.zoneId()), null);
} }
@Override
public long getFrom(TemporalAccessor temporal) { @Test
throw new UnsupportedOperationException(); public void test_withZone_override() {
DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
f = f.withZone(EUROPE_ATHENS);
TemporalAccessor accessor = f.parse("");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_ATHENS);
} }
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) { @Test
throw new UnsupportedOperationException(); public void test_withZone_parsedZone_noOverride() {
DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendZoneId().toFormatter();
TemporalAccessor accessor = f.parse("Europe/Paris");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
} }
@Override
public TemporalAccessor resolve( @Test
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { public void test_withZone_parsedZone_override() {
return LocalTime.MIDNIGHT.plusNanos(fieldValues.remove(this)); DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendZoneId().toFormatter();
f = f.withZone(EUROPE_ATHENS);
TemporalAccessor accessor = f.parse("Europe/Paris");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
} }
};
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field).toFormatter(); //-----------------------------------------------------------------------
@Test
public void test_fieldResolvesToLocalTime() {
LocalTime lt = LocalTime.of(12, 30, 40);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(lt)).toFormatter();
TemporalAccessor accessor = f.parse("1234567890"); TemporalAccessor accessor = f.parse("1234567890");
assertEquals(accessor.query(TemporalQueries.localDate()), null); assertEquals(accessor.query(TemporalQueries.localDate()), null);
assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.of(0, 0, 1, 234_567_890)); assertEquals(accessor.query(TemporalQueries.localTime()), lt);
} }
//-------------------------------------------------------------------------
@Test @Test
public void test_fieldResolvesToChronoLocalDateTime() { public void test_fieldResolvesToChronoLocalDate_noOverrideChrono_matches() {
TemporalField field = new TemporalField() { LocalDate ldt = LocalDate.of(2010, 6, 30);
@Override DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(ldt)).toFormatter();
public TemporalUnit getBaseUnit() { TemporalAccessor accessor = f.parse("1234567890");
throw new UnsupportedOperationException(); assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30));
} assertEquals(accessor.query(TemporalQueries.localTime()), null);
@Override assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
public TemporalUnit getRangeUnit() {
throw new UnsupportedOperationException();
}
@Override
public ValueRange range() {
throw new UnsupportedOperationException();
}
@Override
public boolean isDateBased() {
throw new UnsupportedOperationException();
}
@Override
public boolean isTimeBased() {
throw new UnsupportedOperationException();
}
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
throw new UnsupportedOperationException();
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
throw new UnsupportedOperationException();
} }
@Override
public long getFrom(TemporalAccessor temporal) { @Test
throw new UnsupportedOperationException(); public void test_fieldResolvesToChronoLocalDate_overrideChrono_matches() {
MinguoDate mdt = MinguoDate.of(100, 6, 30);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(mdt)).toFormatter();
f = f.withChronology(MinguoChronology.INSTANCE);
TemporalAccessor accessor = f.parse("1234567890");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.from(mdt));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
} }
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) { @Test(expectedExceptions = DateTimeParseException.class)
throw new UnsupportedOperationException(); public void test_fieldResolvesToChronoLocalDate_noOverrideChrono_wrongChrono() {
ChronoLocalDate cld = ThaiBuddhistChronology.INSTANCE.dateNow();
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cld)).toFormatter();
f.parse("1234567890");
} }
@Override
public TemporalAccessor resolve( @Test(expectedExceptions = DateTimeParseException.class)
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { public void test_fieldResolvesToChronoLocalDate_overrideChrono_wrongChrono() {
fieldValues.remove(this); ChronoLocalDate cld = ThaiBuddhistChronology.INSTANCE.dateNow();
return LocalDateTime.of(2010, 6, 30, 12, 30); DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cld)).toFormatter();
f = f.withChronology(MinguoChronology.INSTANCE);
f.parse("1234567890");
} }
};
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field).toFormatter(); //-------------------------------------------------------------------------
@Test
public void test_fieldResolvesToChronoLocalDateTime_noOverrideChrono_matches() {
LocalDateTime ldt = LocalDateTime.of(2010, 6, 30, 12, 30);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(ldt)).toFormatter();
TemporalAccessor accessor = f.parse("1234567890"); TemporalAccessor accessor = f.parse("1234567890");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30)); assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30));
assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.of(12, 30)); assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.of(12, 30));
assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
} }
@Test(expectedExceptions = DateTimeParseException.class) @Test
public void test_fieldResolvesWrongChrono() { public void test_fieldResolvesToChronoLocalDateTime_overrideChrono_matches() {
TemporalField field = new TemporalField() { MinguoDate mdt = MinguoDate.of(100, 6, 30);
@Override DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(mdt.atTime(LocalTime.NOON))).toFormatter();
public TemporalUnit getBaseUnit() { f = f.withChronology(MinguoChronology.INSTANCE);
throw new UnsupportedOperationException(); TemporalAccessor accessor = f.parse("1234567890");
} assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.from(mdt));
@Override assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.NOON);
public TemporalUnit getRangeUnit() { assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
throw new UnsupportedOperationException();
}
@Override
public ValueRange range() {
throw new UnsupportedOperationException();
} }
@Override
public boolean isDateBased() { @Test(expectedExceptions = DateTimeParseException.class)
throw new UnsupportedOperationException(); public void test_fieldResolvesToChronoLocalDateTime_noOverrideChrono_wrongChrono() {
ChronoLocalDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
f.parse("1234567890");
} }
@Override
public boolean isTimeBased() { @Test(expectedExceptions = DateTimeParseException.class)
throw new UnsupportedOperationException(); public void test_fieldResolvesToChronoLocalDateTime_overrideChrono_wrongChrono() {
ChronoLocalDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
f = f.withChronology(MinguoChronology.INSTANCE);
f.parse("1234567890");
} }
@Override
public boolean isSupportedBy(TemporalAccessor temporal) { //-------------------------------------------------------------------------
throw new UnsupportedOperationException(); @Test
public void test_fieldResolvesToChronoZonedDateTime_noOverrideChrono_matches() {
ZonedDateTime zdt = ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, EUROPE_PARIS);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(zdt)).toFormatter();
TemporalAccessor accessor = f.parse("1234567890");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30));
assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.of(12, 30));
assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
} }
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) { @Test
throw new UnsupportedOperationException(); public void test_fieldResolvesToChronoZonedDateTime_overrideChrono_matches() {
MinguoDate mdt = MinguoDate.of(100, 6, 30);
ChronoZonedDateTime<MinguoDate> mzdt = mdt.atTime(LocalTime.NOON).atZone(EUROPE_PARIS);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(mzdt)).toFormatter();
f = f.withChronology(MinguoChronology.INSTANCE);
TemporalAccessor accessor = f.parse("1234567890");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.from(mdt));
assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.NOON);
assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
} }
@Override
public long getFrom(TemporalAccessor temporal) { @Test(expectedExceptions = DateTimeParseException.class)
throw new UnsupportedOperationException(); public void test_fieldResolvesToChronoZonedDateTime_noOverrideChrono_wrongChrono() {
ChronoZonedDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON).atZone(EUROPE_PARIS);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
f.parse("1234567890");
} }
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) { @Test(expectedExceptions = DateTimeParseException.class)
throw new UnsupportedOperationException(); public void test_fieldResolvesToChronoZonedDateTime_overrideChrono_wrongChrono() {
ChronoZonedDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON).atZone(EUROPE_PARIS);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
f = f.withChronology(MinguoChronology.INSTANCE);
f.parse("1234567890");
} }
@Override
public TemporalAccessor resolve( @Test
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { public void test_fieldResolvesToChronoZonedDateTime_overrideZone_matches() {
return ThaiBuddhistChronology.INSTANCE.dateNow(); ZonedDateTime zdt = ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, EUROPE_PARIS);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(zdt)).toFormatter();
f = f.withZone(EUROPE_PARIS);
assertEquals(f.parse("1234567890", ZonedDateTime::from), zdt);
} }
};
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field).toFormatter(); @Test(expectedExceptions = DateTimeParseException.class)
public void test_fieldResolvesToChronoZonedDateTime_overrideZone_wrongZone() {
ZonedDateTime zdt = ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, EUROPE_PARIS);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(zdt)).toFormatter();
f = f.withZone(ZoneId.of("Europe/London"));
f.parse("1234567890"); f.parse("1234567890");
} }
@Test(expectedExceptions = DateTimeParseException.class) //-------------------------------------------------------------------------
public void test_fieldResolvesWrongZone() { private static class ResolvingField implements TemporalField {
TemporalField field = new TemporalField() { private final TemporalAccessor resolvedValue;
ResolvingField(TemporalAccessor resolvedValue) {
this.resolvedValue = resolvedValue;
}
@Override @Override
public TemporalUnit getBaseUnit() { public TemporalUnit getBaseUnit() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
...@@ -1080,11 +1154,9 @@ public class TCKDateTimeParseResolver { ...@@ -1080,11 +1154,9 @@ public class TCKDateTimeParseResolver {
@Override @Override
public TemporalAccessor resolve( public TemporalAccessor resolve(
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
return ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, ZoneId.of("Europe/Paris")); fieldValues.remove(this);
return resolvedValue;
} }
}; };
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field).toFormatter().withZone(ZoneId.of("Europe/London"));
f.parse("1234567890");
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册