# HG changeset patch # User rriggs # Date 1380233967 25200 # Node ID 86a86a94b367b40bf053f63f8b814e78d2da633a # Parent e41a8a513b3e8a0628ee42c143eece072f9207ae 8025718: Enhance error messages for parsing Summary: Add values and types to exception messages Reviewed-by: lancea Contributed-by: scolebourne@joda.org diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/DayOfWeek.java --- 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); + } } //----------------------------------------------------------------------- diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/Instant.java --- 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()); + } } //----------------------------------------------------------------------- diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/LocalDate.java --- 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; } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/LocalDateTime.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/LocalTime.java --- 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; } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/Month.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/MonthDay.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/OffsetDateTime.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/OffsetTime.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/Year.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/YearMonth.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/ZoneId.java --- 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; } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/ZoneOffset.java --- 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; } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/ZonedDateTime.java --- 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); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/src/share/classes/java/time/format/Parsed.java --- 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(); } } diff -r e41a8a513b3e -r 86a86a94b367 jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java --- 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 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 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); + } + }