Skip to content

Commit 0c439fe

Browse files
authored
[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
1 parent fd1c4c1 commit 0c439fe

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

server/src/main/java/org/elasticsearch/common/time/DateFormatters.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,14 @@ public class DateFormatters {
5959

6060
private static final DateTimeFormatter STRICT_YEAR_MONTH_DAY_FORMATTER = new DateTimeFormatterBuilder()
6161
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
62+
.optionalStart()
6263
.appendLiteral("-")
6364
.appendValue(MONTH_OF_YEAR, 2, 2, SignStyle.NOT_NEGATIVE)
65+
.optionalStart()
6466
.appendLiteral('-')
6567
.appendValue(DAY_OF_MONTH, 2, 2, SignStyle.NOT_NEGATIVE)
68+
.optionalEnd()
69+
.optionalEnd()
6670
.toFormatter(Locale.ROOT);
6771

6872
private static final DateTimeFormatter STRICT_HOUR_MINUTE_SECOND_FORMATTER = new DateTimeFormatterBuilder()
@@ -910,12 +914,14 @@ public class DateFormatters {
910914

911915
private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
912916
.appendValue(ChronoField.YEAR, 1, 5, SignStyle.NORMAL)
917+
.optionalStart()
913918
.appendLiteral('-')
914919
.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NOT_NEGATIVE)
915920
.optionalStart()
916921
.appendLiteral('-')
917922
.appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE)
918923
.optionalEnd()
924+
.optionalEnd()
919925
.toFormatter(Locale.ROOT);
920926

921927
private static final DateTimeFormatter HOUR_MINUTE_FORMATTER = new DateTimeFormatterBuilder()

server/src/test/java/org/elasticsearch/common/joda/JavaJodaTimeDuellingTests.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,37 @@
3838
import java.util.Locale;
3939

4040
import static org.hamcrest.Matchers.containsString;
41-
import static org.hamcrest.Matchers.equalTo;
4241
import static org.hamcrest.Matchers.is;
42+
import static org.hamcrest.core.IsEqual.equalTo;
4343

4444
public class JavaJodaTimeDuellingTests extends ESTestCase {
45+
@Override
46+
protected boolean enableWarningsCheck() {
47+
return false;
48+
}
49+
// date_optional part of a parser names "strict_date_optional_time" or "date_optional"time
50+
// means that date part can be partially parsed.
51+
public void testPartialParsing() {
52+
assertSameDateAs("2001", "strict_date_optional_time_nanos", "strict_date_optional_time");
53+
assertSameDateAs("2001-01", "strict_date_optional_time_nanos", "strict_date_optional_time");
54+
assertSameDateAs("2001-01-01", "strict_date_optional_time_nanos", "strict_date_optional_time");
55+
56+
assertSameDate("2001", "strict_date_optional_time");
57+
assertSameDate("2001-01", "strict_date_optional_time");
58+
assertSameDate("2001-01-01", "strict_date_optional_time");
59+
60+
assertSameDate("2001", "date_optional_time");
61+
assertSameDate("2001-01", "date_optional_time");
62+
assertSameDate("2001-01-01", "date_optional_time");
63+
64+
65+
assertSameDateAs("2001", "iso8601", "strict_date_optional_time");
66+
assertSameDateAs("2001-01", "iso8601", "strict_date_optional_time");
67+
assertSameDateAs("2001-01-01", "iso8601", "strict_date_optional_time");
68+
69+
assertSameDate("9999","date_optional_time||epoch_second");
70+
}
71+
4572
public void testCompositeDateMathParsing(){
4673
//in all these examples the second pattern will be used
4774
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 @@ private void assertDateMathEquals(String text, String pattern) {
909936

910937
assertEquals(gotMillisJoda, gotMillisJava);
911938
}
939+
940+
private void assertSameDateAs(String input, String javaPattern, String jodaPattern) {
941+
DateFormatter javaFormatter = DateFormatter.forPattern(javaPattern);
942+
DateFormatter jodaFormatter = Joda.forPattern(jodaPattern);
943+
assertSameDate(input, javaPattern, jodaFormatter, javaFormatter);
944+
}
912945
}

server/src/test/java/org/elasticsearch/common/time/JavaDateMathParserTests.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,11 @@ public void testTimestamps() {
258258
long datetime = parser.parse("1418248078", () -> 0).toEpochMilli();
259259
assertDateEquals(datetime, "1418248078", "2014-12-10T21:47:58.000");
260260

261-
// a timestamp before 10000 is a year
262-
assertDateMathEquals("9999", "1970-01-01T00:00:09.999Z");
263-
// 10000 is also a year, breaking bwc, used to be a timestamp
264-
assertDateMathEquals("10000", "1970-01-01T00:00:10.000Z");
261+
// a timestamp before 100000 is a year
262+
assertDateMathEquals("9999", "9999-01-01T00:00:00.000");
263+
assertDateMathEquals("10000", "10000-01-01T00:00:00.000");
264+
assertDateMathEquals("100000", "1970-01-01T00:01:40.000");
265+
265266
// but 10000 with T is still a date format
266267
assertDateMathEquals("10000-01-01T", "10000-01-01T00:00:00.000");
267268
}

0 commit comments

Comments
 (0)