[7.x] Allow partial parsing dates (#47872) backport(#46814)

Enable partial parsing of date part. This is making the behaviour in java.time implementation the same as with joda.
2018, 2018-01 and 2018-01-01 are all valid dates for date_optional_time or strict_date_optional_time
closes #45284
closes #47473
This commit is contained in:
Przemyslaw Gomulka 2019-10-11 11:17:19 +02:00 committed by GitHub
parent fd1c4c198a
commit 0c439fe495
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 5 deletions

View File

@ -59,10 +59,14 @@ public class DateFormatters {
private static final DateTimeFormatter STRICT_YEAR_MONTH_DAY_FORMATTER = new DateTimeFormatterBuilder() private static final DateTimeFormatter STRICT_YEAR_MONTH_DAY_FORMATTER = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD) .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
.optionalStart()
.appendLiteral("-") .appendLiteral("-")
.appendValue(MONTH_OF_YEAR, 2, 2, SignStyle.NOT_NEGATIVE) .appendValue(MONTH_OF_YEAR, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral('-') .appendLiteral('-')
.appendValue(DAY_OF_MONTH, 2, 2, SignStyle.NOT_NEGATIVE) .appendValue(DAY_OF_MONTH, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalEnd()
.optionalEnd()
.toFormatter(Locale.ROOT); .toFormatter(Locale.ROOT);
private static final DateTimeFormatter STRICT_HOUR_MINUTE_SECOND_FORMATTER = new DateTimeFormatterBuilder() private static final DateTimeFormatter STRICT_HOUR_MINUTE_SECOND_FORMATTER = new DateTimeFormatterBuilder()
@ -910,12 +914,14 @@ public class DateFormatters {
private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder() private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 1, 5, SignStyle.NORMAL) .appendValue(ChronoField.YEAR, 1, 5, SignStyle.NORMAL)
.optionalStart()
.appendLiteral('-') .appendLiteral('-')
.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NOT_NEGATIVE) .appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NOT_NEGATIVE)
.optionalStart() .optionalStart()
.appendLiteral('-') .appendLiteral('-')
.appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE) .appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE)
.optionalEnd() .optionalEnd()
.optionalEnd()
.toFormatter(Locale.ROOT); .toFormatter(Locale.ROOT);
private static final DateTimeFormatter HOUR_MINUTE_FORMATTER = new DateTimeFormatterBuilder() private static final DateTimeFormatter HOUR_MINUTE_FORMATTER = new DateTimeFormatterBuilder()

View File

@ -38,10 +38,37 @@ import java.time.temporal.TemporalAccessor;
import java.util.Locale; import java.util.Locale;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.core.IsEqual.equalTo;
public class JavaJodaTimeDuellingTests extends ESTestCase { public class JavaJodaTimeDuellingTests extends ESTestCase {
@Override
protected boolean enableWarningsCheck() {
return false;
}
// 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() {
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");
assertSameDate("2001", "strict_date_optional_time");
assertSameDate("2001-01", "strict_date_optional_time");
assertSameDate("2001-01-01", "strict_date_optional_time");
assertSameDate("2001", "date_optional_time");
assertSameDate("2001-01", "date_optional_time");
assertSameDate("2001-01-01", "date_optional_time");
assertSameDateAs("2001", "iso8601", "strict_date_optional_time");
assertSameDateAs("2001-01", "iso8601", "strict_date_optional_time");
assertSameDateAs("2001-01-01", "iso8601", "strict_date_optional_time");
assertSameDate("9999","date_optional_time||epoch_second");
}
public void testCompositeDateMathParsing(){ public void testCompositeDateMathParsing(){
//in all these examples the second pattern will be used //in all these examples the second pattern will be used
assertDateMathEquals("2014-06-06T12:01:02.123", "yyyy-MM-dd'T'HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSS"); assertDateMathEquals("2014-06-06T12:01:02.123", "yyyy-MM-dd'T'HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSS");
@ -909,4 +936,10 @@ public class JavaJodaTimeDuellingTests extends ESTestCase {
assertEquals(gotMillisJoda, gotMillisJava); assertEquals(gotMillisJoda, gotMillisJava);
} }
private void assertSameDateAs(String input, String javaPattern, String jodaPattern) {
DateFormatter javaFormatter = DateFormatter.forPattern(javaPattern);
DateFormatter jodaFormatter = Joda.forPattern(jodaPattern);
assertSameDate(input, javaPattern, jodaFormatter, javaFormatter);
}
} }

View File

@ -258,10 +258,11 @@ public class JavaDateMathParserTests extends ESTestCase {
long datetime = parser.parse("1418248078", () -> 0).toEpochMilli(); long datetime = parser.parse("1418248078", () -> 0).toEpochMilli();
assertDateEquals(datetime, "1418248078", "2014-12-10T21:47:58.000"); assertDateEquals(datetime, "1418248078", "2014-12-10T21:47:58.000");
// a timestamp before 10000 is a year // a timestamp before 100000 is a year
assertDateMathEquals("9999", "1970-01-01T00:00:09.999Z"); assertDateMathEquals("9999", "9999-01-01T00:00:00.000");
// 10000 is also a year, breaking bwc, used to be a timestamp assertDateMathEquals("10000", "10000-01-01T00:00:00.000");
assertDateMathEquals("10000", "1970-01-01T00:00:10.000Z"); assertDateMathEquals("100000", "1970-01-01T00:01:40.000");
// but 10000 with T is still a date format // but 10000 with T is still a date format
assertDateMathEquals("10000-01-01T", "10000-01-01T00:00:00.000"); assertDateMathEquals("10000-01-01T", "10000-01-01T00:00:00.000");
} }