提交 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 {
*/
private TemporalAccessor parseResolved0(final CharSequence text, final ParsePosition position) {
ParsePosition pos = (position != null ? position : new ParsePosition(0));
Parsed unresolved = parseUnresolved0(text, pos);
if (unresolved == null || pos.getErrorIndex() >= 0 || (position == null && pos.getIndex() < text.length())) {
DateTimeParseContext context = parseUnresolved0(text, pos);
if (context == null || pos.getErrorIndex() >= 0 || (position == null && pos.getIndex() < text.length())) {
String abbr;
if (text.length() > 64) {
abbr = text.subSequence(0, 64).toString() + "...";
......@@ -1950,7 +1950,7 @@ public final class DateTimeFormatter {
pos.getIndex(), text, pos.getIndex());
}
}
return unresolved.resolve(resolverStyle, resolverFields);
return context.toResolved(resolverStyle, resolverFields);
}
/**
......@@ -1993,10 +1993,14 @@ public final class DateTimeFormatter {
* @throws IndexOutOfBoundsException if the position is invalid
*/
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(position, "position");
DateTimeParseContext context = new DateTimeParseContext(this);
......@@ -2007,7 +2011,7 @@ public final class DateTimeFormatter {
return null;
}
position.setIndex(pos); // errorIndex not updated from input
return context.toParsed();
return context;
}
//-----------------------------------------------------------------------
......@@ -2128,23 +2132,23 @@ public final class DateTimeFormatter {
@Override
public Object parseObject(String text, ParsePosition pos) {
Objects.requireNonNull(text, "text");
Parsed unresolved;
DateTimeParseContext context;
try {
unresolved = formatter.parseUnresolved0(text, pos);
context = formatter.parseUnresolved0(text, pos);
} catch (IndexOutOfBoundsException ex) {
if (pos.getErrorIndex() < 0) {
pos.setErrorIndex(0);
}
return null;
}
if (unresolved == null) {
if (context == null) {
if (pos.getErrorIndex() < 0) {
pos.setErrorIndex(0);
}
return null;
}
try {
TemporalAccessor resolved = unresolved.resolve(formatter.resolverStyle, formatter.resolverFields);
TemporalAccessor resolved = context.toResolved(formatter.resolverStyle, formatter.resolverFields);
if (parseType == null) {
return resolved;
}
......
......@@ -64,10 +64,12 @@ package java.time.format;
import java.time.ZoneId;
import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
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 also provides key information to the parsing methods.
* <p>
* Once parsing is complete, the {@link #toParsed()} is used to obtain the data.
* It contains a method to resolve the separate parsed fields into meaningful values.
* Once parsing is complete, the {@link #toUnresolved()} is used to obtain the unresolved
* result data. The {@link #toResolved()} is used to obtain the resolved result.
*
* @implSpec
* This class is a mutable context intended for use from a single thread.
......@@ -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
*/
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.effectiveChrono = getEffectiveChronology();
return parsed;
parsed.chrono = getEffectiveChronology();
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.
......
......@@ -135,10 +135,6 @@ final class Parsed implements TemporalAccessor {
* Whether a leap-second is parsed.
*/
boolean leapSecond;
/**
* The effective chronology.
*/
Chronology effectiveChrono;
/**
* The resolver style to use.
*/
......@@ -241,7 +237,6 @@ final class Parsed implements TemporalAccessor {
fieldValues.keySet().retainAll(resolverFields);
}
this.resolverStyle = resolverStyle;
chrono = effectiveChrono;
resolveFields();
resolveTimeLenient();
crossCheck();
......@@ -266,14 +261,16 @@ final class Parsed implements TemporalAccessor {
TemporalAccessor resolvedObject = targetField.resolve(fieldValues, this, resolverStyle);
if (resolvedObject != null) {
if (resolvedObject instanceof ChronoZonedDateTime) {
ChronoZonedDateTime<?> czdt = (ChronoZonedDateTime) resolvedObject;
if (zone.equals(czdt.getZone()) == false) {
ChronoZonedDateTime<?> czdt = (ChronoZonedDateTime<?>) resolvedObject;
if (zone == null) {
zone = czdt.getZone();
} else if (zone.equals(czdt.getZone()) == false) {
throw new DateTimeException("ChronoZonedDateTime must use the effective parsed zone: " + zone);
}
resolvedObject = czdt.toLocalDateTime();
}
if (resolvedObject instanceof ChronoLocalDateTime) {
ChronoLocalDateTime<?> cldt = (ChronoLocalDateTime) resolvedObject;
ChronoLocalDateTime<?> cldt = (ChronoLocalDateTime<?>) resolvedObject;
updateCheckConflict(cldt.toLocalTime(), Period.ZERO);
updateCheckConflict(cldt.toLocalDate());
changedCount++;
......
......@@ -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.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.NANOS;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
......@@ -102,13 +99,17 @@ import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
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.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.IsoFields;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
......@@ -129,6 +130,9 @@ public class TCKDateTimeParseResolver {
// TODO: tests with weird TenporalField implementations
// 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")
Object[][] data_resolveOneNoChange() {
......@@ -886,161 +890,231 @@ public class TCKDateTimeParseResolver {
}
//-----------------------------------------------------------------------
// SPEC: DateTimeFormatter.withChronology()
@Test
public void test_fieldResolvesToLocalTime() {
TemporalField field = new TemporalField() {
@Override
public TemporalUnit getBaseUnit() {
throw new UnsupportedOperationException();
}
@Override
public TemporalUnit getRangeUnit() {
throw new UnsupportedOperationException();
}
@Override
public ValueRange range() {
throw new UnsupportedOperationException();
public void test_withChronology_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.chronology()), IsoChronology.INSTANCE);
}
@Override
public boolean isDateBased() {
throw new UnsupportedOperationException();
@Test
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() {
throw new UnsupportedOperationException();
@Test
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) {
throw new UnsupportedOperationException();
@Test
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) {
throw new UnsupportedOperationException();
@Test
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) {
throw new UnsupportedOperationException();
@Test
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(
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
return LocalTime.MIDNIGHT.plusNanos(fieldValues.remove(this));
@Test
public void test_withZone_parsedZone_override() {
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");
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
public void test_fieldResolvesToChronoLocalDateTime() {
TemporalField field = new TemporalField() {
@Override
public TemporalUnit getBaseUnit() {
throw new UnsupportedOperationException();
}
@Override
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();
public void test_fieldResolvesToChronoLocalDate_noOverrideChrono_matches() {
LocalDate ldt = LocalDate.of(2010, 6, 30);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(ldt)).toFormatter();
TemporalAccessor accessor = f.parse("1234567890");
assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30));
assertEquals(accessor.query(TemporalQueries.localTime()), null);
assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
}
@Override
public long getFrom(TemporalAccessor temporal) {
throw new UnsupportedOperationException();
@Test
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) {
throw new UnsupportedOperationException();
@Test(expectedExceptions = DateTimeParseException.class)
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(
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
fieldValues.remove(this);
return LocalDateTime.of(2010, 6, 30, 12, 30);
@Test(expectedExceptions = DateTimeParseException.class)
public void test_fieldResolvesToChronoLocalDate_overrideChrono_wrongChrono() {
ChronoLocalDate cld = ThaiBuddhistChronology.INSTANCE.dateNow();
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");
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);
}
@Test(expectedExceptions = DateTimeParseException.class)
public void test_fieldResolvesWrongChrono() {
TemporalField field = new TemporalField() {
@Override
public TemporalUnit getBaseUnit() {
throw new UnsupportedOperationException();
}
@Override
public TemporalUnit getRangeUnit() {
throw new UnsupportedOperationException();
}
@Override
public ValueRange range() {
throw new UnsupportedOperationException();
@Test
public void test_fieldResolvesToChronoLocalDateTime_overrideChrono_matches() {
MinguoDate mdt = MinguoDate.of(100, 6, 30);
DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(mdt.atTime(LocalTime.NOON))).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);
}
@Override
public boolean isDateBased() {
throw new UnsupportedOperationException();
@Test(expectedExceptions = DateTimeParseException.class)
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() {
throw new UnsupportedOperationException();
@Test(expectedExceptions = DateTimeParseException.class)
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) {
throw new UnsupportedOperationException();
@Test
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) {
throw new UnsupportedOperationException();
@Test(expectedExceptions = DateTimeParseException.class)
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) {
throw new UnsupportedOperationException();
@Test(expectedExceptions = DateTimeParseException.class)
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(
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
return ThaiBuddhistChronology.INSTANCE.dateNow();
@Test
public void test_fieldResolvesToChronoZonedDateTime_overrideZone_matches() {
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");
}
@Test(expectedExceptions = DateTimeParseException.class)
public void test_fieldResolvesWrongZone() {
TemporalField field = new TemporalField() {
//-------------------------------------------------------------------------
private static class ResolvingField implements TemporalField {
private final TemporalAccessor resolvedValue;
ResolvingField(TemporalAccessor resolvedValue) {
this.resolvedValue = resolvedValue;
}
@Override
public TemporalUnit getBaseUnit() {
throw new UnsupportedOperationException();
......@@ -1080,11 +1154,9 @@ public class TCKDateTimeParseResolver {
@Override
public TemporalAccessor resolve(
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.
先完成此消息的编辑!
想要评论请 注册