Allow parsing timezone without fully provided time backport(#50178) (#50740)

strict_date_optional_time changes to have optional minute part.
It already allowed optional second and fraction of second part.
This allows parsing 2018-01-01T00+01 , 2018-01-01T00:00+01 , 2018-01-01T00:00:00+01 , 2018-01-01T00:00:00.000+01
It won't allow parsing a timezone without an hour part as this is not allowed by iso8601 spec

closes #49351
This commit is contained in:
Przemyslaw Gomulka 2020-01-08 20:04:57 +01:00 committed by GitHub
parent 9d1567b13b
commit e95b0c447f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 28 deletions

View File

@ -108,31 +108,31 @@ public class DateFormatters {
private static final DateTimeFormatter STRICT_DATE_OPTIONAL_TIME_FORMATTER = new DateTimeFormatterBuilder()
.append(STRICT_YEAR_MONTH_DAY_FORMATTER)
.optionalStart()
.appendLiteral('T')
.optionalStart()
.appendValue(HOUR_OF_DAY, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendFraction(NANO_OF_SECOND, 1, 9, true)
.optionalEnd()
.optionalStart()
.appendLiteral(',')
.appendFraction(NANO_OF_SECOND, 1, 9, false)
.optionalEnd()
.optionalEnd()
.optionalStart()
.appendZoneOrOffsetId()
.optionalEnd()
.optionalStart()
.append(TIME_ZONE_FORMATTER_NO_COLON)
.optionalEnd()
.optionalEnd()
.optionalEnd()
.appendLiteral('T')
.optionalStart()
.appendValue(HOUR_OF_DAY, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendFraction(NANO_OF_SECOND, 1, 9, true)
.optionalEnd()
.optionalStart()
.appendLiteral(',')
.appendFraction(NANO_OF_SECOND, 1, 9, false)
.optionalEnd()
.optionalEnd()
.optionalEnd()
.optionalStart()
.appendZoneOrOffsetId()
.optionalEnd()
.optionalStart()
.append(TIME_ZONE_FORMATTER_NO_COLON)
.optionalEnd()
.optionalEnd()
.optionalEnd()
.toFormatter(Locale.ROOT)
.withResolverStyle(ResolverStyle.STRICT);

View File

@ -46,9 +46,42 @@ public class JavaJodaTimeDuellingTests extends ESTestCase {
protected boolean enableWarningsCheck() {
return false;
}
public void testTimezoneParsing() {
/** this testcase won't work in joda. See comment in {@link #testPartialTimeParsing()}
* assertSameDateAs("2016-11-30T+01", "strict_date_optional_time", "strict_date_optional_time");
*/
assertSameDateAs("2016-11-30T00+01", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T00+0100", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T00+01:00", "strict_date_optional_time", "strict_date_optional_time");
}
public void testPartialTimeParsing() {
/*
This does not work in Joda as it reports 2016-11-30T01:00:00Z
because StrictDateOptionalTime confuses +01 with an hour (which is a signed fixed length digit)
assertSameDateAs("2016-11-30T+01", "strict_date_optional_time", "strict_date_optional_time");
ES java.time implementation does not suffer from this,
but we intentionally not allow parsing timezone without an time part as it is not allowed in iso8601
*/
assertJavaTimeParseException("2016-11-30T+01","strict_date_optional_time");
assertSameDateAs("2016-11-30T12+01", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T12:00+01", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T12:00:00+01", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T12:00:00.000+01", "strict_date_optional_time", "strict_date_optional_time");
//without timezone
assertSameDateAs("2016-11-30T", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T12", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T12:00", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T12:00:00", "strict_date_optional_time", "strict_date_optional_time");
assertSameDateAs("2016-11-30T12:00:00.000", "strict_date_optional_time", "strict_date_optional_time");
}
// date_optional part of a parser names "strict_date_optional_time" or "date_optional"time
// means that date part can be partially parsed.
public void testPartialParsing() {
public void testPartialDateParsing() {
assertSameDateAs("2001", "strict_date_optional_time_nanos", "strict_date_optional_time");
assertSameDateAs("2001-01", "strict_date_optional_time_nanos", "strict_date_optional_time");
assertSameDateAs("2001-01-01", "strict_date_optional_time_nanos", "strict_date_optional_time");
@ -883,9 +916,28 @@ public class JavaJodaTimeDuellingTests extends ESTestCase {
}
private void assertSamePrinterOutput(String format, ZonedDateTime javaDate, DateTime jodaDate) {
DateFormatter dateFormatter = DateFormatter.forPattern(format);
JodaDateFormatter jodaDateFormatter = Joda.forPattern(format);
assertSamePrinterOutput(format, javaDate, jodaDate, dateFormatter, jodaDateFormatter);
}
private void assertSamePrinterOutput(String format, ZonedDateTime javaDate, DateTime jodaDate, Locale locale) {
DateFormatter dateFormatter = DateFormatter.forPattern(format).withLocale(locale);
DateFormatter jodaDateFormatter = Joda.forPattern(format).withLocale(locale);
assertSamePrinterOutput(format, javaDate, jodaDate, dateFormatter, jodaDateFormatter);
}
private void assertSamePrinterOutput(String format,
ZonedDateTime javaDate,
DateTime jodaDate,
DateFormatter dateFormatter,
DateFormatter jodaDateFormatter) {
String javaTimeOut = dateFormatter.format(javaDate);
String jodaTimeOut = jodaDateFormatter.formatJoda(jodaDate);
assertThat(jodaDate.getMillis(), is(javaDate.toInstant().toEpochMilli()));
String javaTimeOut = DateFormatter.forPattern(format).format(javaDate);
String jodaTimeOut = Joda.forPattern(format).formatJoda(jodaDate);
if (JavaVersion.current().getVersion().get(0) == 8 && javaTimeOut.endsWith(".0")
&& (format.equals("epoch_second") || format.equals("epoch_millis"))) {
@ -904,6 +956,12 @@ public class JavaJodaTimeDuellingTests extends ESTestCase {
assertSameDate(input, format, jodaFormatter, javaFormatter);
}
private void assertSameDate(String input, String format, Locale locale) {
DateFormatter jodaFormatter = Joda.forPattern(format).withLocale(locale);
DateFormatter javaFormatter = DateFormatter.forPattern(format).withLocale(locale);
assertSameDate(input, format, jodaFormatter, javaFormatter);
}
private void assertSameDate(String input, String format, DateFormatter jodaFormatter, DateFormatter javaFormatter) {
DateTime jodaDateTime = jodaFormatter.parseJoda(input);