8025718: Enhance error messages for parsing
Summary: Add values and types to exception messages
Reviewed-by: lancea
Contributed-by: scolebourne@joda.org
--- a/jdk/src/share/classes/java/time/DayOfWeek.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/DayOfWeek.java Thu Sep 26 15:19:27 2013 -0700
@@ -187,7 +187,12 @@
if (temporal instanceof DayOfWeek) {
return (DayOfWeek) temporal;
}
- return of(temporal.get(DAY_OF_WEEK));
+ try {
+ return of(temporal.get(DAY_OF_WEEK));
+ } catch (DateTimeException ex) {
+ throw new DateTimeException("Unable to obtain DayOfWeek from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
+ }
}
//-----------------------------------------------------------------------
--- a/jdk/src/share/classes/java/time/Instant.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/Instant.java Thu Sep 26 15:19:27 2013 -0700
@@ -366,9 +366,14 @@
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);
+ try {
+ long instantSecs = temporal.getLong(INSTANT_SECONDS);
+ int nanoOfSecond = temporal.get(NANO_OF_SECOND);
+ return Instant.ofEpochSecond(instantSecs, nanoOfSecond);
+ } catch (DateTimeException ex) {
+ throw new DateTimeException("Unable to obtain Instant from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName());
+ }
}
//-----------------------------------------------------------------------
--- a/jdk/src/share/classes/java/time/LocalDate.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/LocalDate.java Thu Sep 26 15:19:27 2013 -0700
@@ -356,7 +356,8 @@
Objects.requireNonNull(temporal, "temporal");
LocalDate date = temporal.query(TemporalQuery.localDate());
if (date == null) {
- throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " + temporal.getClass());
+ throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName());
}
return date;
}
--- a/jdk/src/share/classes/java/time/LocalDateTime.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/LocalDateTime.java Thu Sep 26 15:19:27 2013 -0700
@@ -449,7 +449,8 @@
LocalTime time = LocalTime.from(temporal);
return new LocalDateTime(date, time);
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to obtain LocalDateTime from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain LocalDateTime from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/LocalTime.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/LocalTime.java Thu Sep 26 15:19:27 2013 -0700
@@ -397,7 +397,8 @@
Objects.requireNonNull(temporal, "temporal");
LocalTime time = temporal.query(TemporalQuery.localTime());
if (time == null) {
- throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " + temporal.getClass());
+ throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName());
}
return time;
}
--- a/jdk/src/share/classes/java/time/Month.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/Month.java Thu Sep 26 15:19:27 2013 -0700
@@ -217,7 +217,8 @@
}
return of(temporal.get(MONTH_OF_YEAR));
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to obtain Month from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain Month from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/MonthDay.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/MonthDay.java Thu Sep 26 15:19:27 2013 -0700
@@ -266,7 +266,8 @@
}
return of(temporal.get(MONTH_OF_YEAR), temporal.get(DAY_OF_MONTH));
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to obtain MonthDay from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain MonthDay from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/OffsetDateTime.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/OffsetDateTime.java Thu Sep 26 15:19:27 2013 -0700
@@ -347,8 +347,8 @@
if (temporal instanceof OffsetDateTime) {
return (OffsetDateTime) temporal;
}
- ZoneOffset offset = ZoneOffset.from(temporal);
try {
+ ZoneOffset offset = ZoneOffset.from(temporal);
try {
LocalDateTime ldt = LocalDateTime.from(temporal);
return OffsetDateTime.of(ldt, offset);
@@ -357,7 +357,8 @@
return OffsetDateTime.ofInstant(instant, offset);
}
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to obtain OffsetDateTime from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain OffsetDateTime from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/OffsetTime.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/OffsetTime.java Thu Sep 26 15:19:27 2013 -0700
@@ -284,7 +284,8 @@
ZoneOffset offset = ZoneOffset.from(temporal);
return new OffsetTime(time, offset);
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to obtain OffsetTime from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain OffsetTime from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/Year.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/Year.java Thu Sep 26 15:19:27 2013 -0700
@@ -249,7 +249,8 @@
}
return of(temporal.get(YEAR));
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to obtain Year from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain Year from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/YearMonth.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/YearMonth.java Thu Sep 26 15:19:27 2013 -0700
@@ -252,7 +252,8 @@
}
return of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR));
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to obtain YearMonth from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain YearMonth from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/ZoneId.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/ZoneId.java Thu Sep 26 15:19:27 2013 -0700
@@ -504,7 +504,8 @@
public static ZoneId from(TemporalAccessor temporal) {
ZoneId obj = temporal.query(TemporalQuery.zone());
if (obj == null) {
- throw new DateTimeException("Unable to obtain ZoneId from TemporalAccessor: " + temporal.getClass());
+ throw new DateTimeException("Unable to obtain ZoneId from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName());
}
return obj;
}
--- a/jdk/src/share/classes/java/time/ZoneOffset.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/ZoneOffset.java Thu Sep 26 15:19:27 2013 -0700
@@ -336,7 +336,8 @@
Objects.requireNonNull(temporal, "temporal");
ZoneOffset offset = temporal.query(TemporalQuery.offset());
if (offset == null) {
- throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " + temporal.getClass());
+ throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName());
}
return offset;
}
--- a/jdk/src/share/classes/java/time/ZonedDateTime.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/ZonedDateTime.java Thu Sep 26 15:19:27 2013 -0700
@@ -553,7 +553,8 @@
return of(ldt, zone);
}
} catch (DateTimeException ex) {
- throw new DateTimeException("Unable to create ZonedDateTime from TemporalAccessor: " + temporal.getClass(), ex);
+ throw new DateTimeException("Unable to obtain ZonedDateTime from TemporalAccessor: " +
+ temporal + " of type " + temporal.getClass().getName(), ex);
}
}
--- a/jdk/src/share/classes/java/time/format/Parsed.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/src/share/classes/java/time/format/Parsed.java Thu Sep 26 15:19:27 2013 -0700
@@ -588,11 +588,23 @@
//-----------------------------------------------------------------------
@Override
public String toString() {
- String str = fieldValues.toString() + "," + chrono + "," + zone;
+ StringBuilder buf = new StringBuilder(64);
+ buf.append(fieldValues).append(',').append(chrono);
+ if (zone != null) {
+ buf.append(',').append(zone);
+ }
if (date != null || time != null) {
- str += " resolved to " + date + "," + time;
+ buf.append(" resolved to ");
+ if (date != null) {
+ buf.append(date);
+ if (time != null) {
+ buf.append('T').append(time);
+ }
+ } else {
+ buf.append(time);
+ }
}
- return str;
+ return buf.toString();
}
}
--- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java Wed Oct 09 11:02:55 2013 -0400
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java Thu Sep 26 15:19:27 2013 -0700
@@ -61,12 +61,32 @@
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
-import java.time.format.DecimalStyle;
+import java.time.DateTimeException;
+import java.time.DayOfWeek;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.Month;
+import java.time.MonthDay;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.Year;
+import java.time.YearMonth;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.chrono.ThaiBuddhistChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DecimalStyle;
import java.time.format.SignStyle;
+import java.time.temporal.TemporalAccessor;
import java.util.Locale;
+import java.util.function.Function;
import org.testng.annotations.Test;
@@ -87,4 +107,93 @@
assertSame(test, base);
}
+ @Test
+ public void test_parse_errorMessage() throws Exception {
+ assertGoodErrorDate(DayOfWeek::from, "DayOfWeek");
+ assertGoodErrorDate(Month::from, "Month");
+ assertGoodErrorDate(YearMonth::from, "YearMonth");
+ assertGoodErrorDate(MonthDay::from, "MonthDay");
+ assertGoodErrorDate(LocalDate::from, "LocalDate");
+ assertGoodErrorDate(LocalTime::from, "LocalTime");
+ assertGoodErrorDate(LocalDateTime::from, "LocalDateTime");
+ assertGoodErrorDate(OffsetTime::from, "OffsetTime");
+ assertGoodErrorDate(OffsetDateTime::from, "OffsetDateTime");
+ assertGoodErrorDate(ZonedDateTime::from, "ZonedDateTime");
+ assertGoodErrorDate(Instant::from, "Instant");
+ assertGoodErrorDate(ZoneOffset::from, "ZoneOffset");
+ assertGoodErrorDate(ZoneId::from, "ZoneId");
+ assertGoodErrorDate(ThaiBuddhistChronology.INSTANCE::date, "");
+
+ assertGoodErrorTime(DayOfWeek::from, "DayOfWeek");
+ assertGoodErrorTime(Month::from, "Month");
+ assertGoodErrorTime(Year::from, "Year");
+ assertGoodErrorTime(YearMonth::from, "YearMonth");
+ assertGoodErrorTime(MonthDay::from, "MonthDay");
+ assertGoodErrorTime(LocalDate::from, "LocalDate");
+ assertGoodErrorTime(LocalTime::from, "LocalTime");
+ assertGoodErrorTime(LocalDateTime::from, "LocalDateTime");
+ assertGoodErrorTime(OffsetTime::from, "OffsetTime");
+ assertGoodErrorTime(OffsetDateTime::from, "OffsetDateTime");
+ assertGoodErrorTime(ZonedDateTime::from, "ZonedDateTime");
+ assertGoodErrorTime(Instant::from, "Instant");
+ assertGoodErrorTime(ZoneOffset::from, "ZoneOffset");
+ assertGoodErrorTime(ZoneId::from, "ZoneId");
+ assertGoodErrorTime(ThaiBuddhistChronology.INSTANCE::date, "");
+ }
+
+ private void assertGoodErrorDate(Function<TemporalAccessor, Object> function, String expectedText) {
+ DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-mm-dd");
+ TemporalAccessor temporal = f.parse("2010-06-30");
+ try {
+ function.apply(temporal);
+ fail("Should have failed");
+ } catch (DateTimeException ex) {
+ String msg = ex.getMessage();
+ assertTrue(msg.contains(expectedText), msg);
+ assertTrue(msg.contains("Year"), msg);
+ assertTrue(msg.contains("MinuteOfHour"), msg);
+ assertTrue(msg.contains("DayOfMonth"), msg);
+ }
+ }
+
+ private void assertGoodErrorTime(Function<TemporalAccessor, Object> function, String expectedText) {
+ DateTimeFormatter f = DateTimeFormatter.ofPattern("HH:MM:ss");
+ TemporalAccessor temporal = f.parse("11:30:56");
+ try {
+ function.apply(temporal);
+ fail("Should have failed");
+ } catch (DateTimeException ex) {
+ String msg = ex.getMessage();
+ assertTrue(msg.contains(expectedText), msg);
+ assertTrue(msg.contains("HourOfDay"), msg);
+ assertTrue(msg.contains("MonthOfYear"), msg);
+ assertTrue(msg.contains("SecondOfMinute"), msg);
+ }
+ }
+
+ @Test
+ public void test_parsed_toString_resolvedTime() {
+ DateTimeFormatter f = DateTimeFormatter.ofPattern("HH:mm:ss");
+ TemporalAccessor temporal = f.parse("11:30:56");
+ String msg = temporal.toString();
+ assertTrue(msg.contains("11:30:56"), msg);
+ }
+
+ @Test
+ public void test_parsed_toString_resolvedDate() {
+ DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ TemporalAccessor temporal = f.parse("2010-06-30");
+ String msg = temporal.toString();
+ assertTrue(msg.contains("2010-06-30"), msg);
+ }
+
+ @Test
+ public void test_parsed_toString_resolvedDateTime() {
+ DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ TemporalAccessor temporal = f.parse("2010-06-30 11:30:56");
+ String msg = temporal.toString();
+ assertTrue(msg.contains("2010-06-30"), msg);
+ assertTrue(msg.contains("11:30:56"), msg);
+ }
+
}