Skip to content

Commit 6ab58de

Browse files
authored
[7.x] Enable ResolverStyle.STRICT for java formatters backport(#46675) (#47913)
Joda was using ResolverStyle.STRICT when parsing. This means that date will be validated to be a correct year, year-of-month, day-of-month However, we also want to make it works with Year-Of-Era as Joda used to, hence custom temporalquery.localdate in DateFormatters.from Within DateFormatters we use the correct uuuu year instead of yyyy year of era worth noting: if yyyy(without an era) is used in code, the parsing result will be a TemporalAccessor which will fail to be converted into LocalDate. We mostly use DateFormatters.from so this takes care of this. If possible the uuuu format should be used.
1 parent 627faf1 commit 6ab58de

File tree

7 files changed

+562
-314
lines changed

7 files changed

+562
-314
lines changed

modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/DateFormat.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ Function<String, ZonedDateTime> getFunction(String format, ZoneId zoneId, Locale
9898
final DateFormatter formatter = dateFormatter;
9999
return text -> {
100100
TemporalAccessor accessor = formatter.parse(text);
101-
// if there is no year, we fall back to the current one and
101+
// if there is no year nor year-of-era, we fall back to the current one and
102102
// fill the rest of the date up with the parsed date
103-
if (accessor.isSupported(ChronoField.YEAR) == false) {
103+
if (accessor.isSupported(ChronoField.YEAR) == false && accessor.isSupported(ChronoField.YEAR_OF_ERA) == false ) {
104104
int year = LocalDate.now(ZoneOffset.UTC).getYear();
105105
ZonedDateTime newTime = Instant.EPOCH.atZone(ZoneOffset.UTC).withYear(year);
106106
for (ChronoField field : FIELDS) {

modules/ingest-common/src/test/java/org/elasticsearch/ingest/common/DateFormatTests.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,22 @@ public void testParseJava() {
4444
equalTo("11 24 01:29:01"));
4545
}
4646

47-
public void testParseJavaWithTimeZone() {
47+
public void testParseYearOfEraJavaWithTimeZone() {
4848
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction("yyyy-MM-dd'T'HH:mm:ss.SSSZZ",
4949
ZoneOffset.UTC, Locale.ROOT);
5050
ZonedDateTime datetime = javaFunction.apply("2018-02-05T13:44:56.657+0100");
5151
String expectedDateTime = DateFormatter.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").withZone(ZoneOffset.UTC).format(datetime);
5252
assertThat(expectedDateTime, is("2018-02-05T12:44:56.657Z"));
5353
}
5454

55+
public void testParseYearJavaWithTimeZone() {
56+
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction("uuuu-MM-dd'T'HH:mm:ss.SSSZZ",
57+
ZoneOffset.UTC, Locale.ROOT);
58+
ZonedDateTime datetime = javaFunction.apply("2018-02-05T13:44:56.657+0100");
59+
String expectedDateTime = DateFormatter.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").withZone(ZoneOffset.UTC).format(datetime);
60+
assertThat(expectedDateTime, is("2018-02-05T12:44:56.657Z"));
61+
}
62+
5563
public void testParseJavaDefaultYear() {
5664
String format = randomFrom("8dd/MM", "dd/MM");
5765
ZoneId timezone = DateUtils.of("Europe/Amsterdam");

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

+539-303
Large diffs are not rendered by default.

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

+4
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,10 @@ public void testIso8601Parsers() {
872872
assertSameDate("2018-10-10T10:11:12,123+05:30", format, jodaFormatter, javaFormatter);
873873
}
874874

875+
public void testParsingLocalDateFromYearOfEra(){
876+
//with strict resolving, YearOfEra expect an era, otherwise it won't resolve to a date
877+
assertSameDate("2018363","yyyyDDD",Joda.forPattern("YYYYDDD"),DateFormatter.forPattern("uuuuDDD"));
878+
}
875879
public void testParsingMissingTimezone() {
876880
long millisJava = DateFormatter.forPattern("8yyyy-MM-dd HH:mm:ss").parseMillis("2018-02-18 17:47:17");
877881
long millisJoda = DateFormatter.forPattern("yyyy-MM-dd HH:mm:ss").parseMillis("2018-02-18 17:47:17");

server/src/test/java/org/elasticsearch/search/aggregations/pipeline/DateDerivativeIT.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public void testSingleValuedFieldNormalised_timeZone_CET_DstStart() throws Excep
198198
List<IndexRequestBuilder> builders = new ArrayList<>();
199199

200200
ZoneId timezone = ZoneId.of("CET");
201-
DateFormatter formatter = DateFormatter.forPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(timezone);
201+
DateFormatter formatter = DateFormatter.forPattern("uuuu-MM-dd'T'HH:mm:ss").withZone(timezone);
202202
// epoch millis: 1332547200000
203203
addNTimes(1, IDX_DST_START, DateFormatters.from(formatter.parse("2012-03-24T01:00:00")), builders);
204204
// day with dst shift, only 23h long
@@ -223,7 +223,7 @@ public void testSingleValuedFieldNormalised_timeZone_CET_DstStart() throws Excep
223223
List<? extends Bucket> buckets = deriv.getBuckets();
224224
assertThat(buckets.size(), equalTo(4));
225225

226-
DateFormatter dateFormatter = DateFormatter.forPattern("yyyy-MM-dd");
226+
DateFormatter dateFormatter = DateFormatter.forPattern("uuuu-MM-dd");
227227
ZonedDateTime expectedKeyFirstBucket =
228228
LocalDate.from(dateFormatter.parse("2012-03-24")).atStartOfDay(timezone).withZoneSameInstant(ZoneOffset.UTC);
229229
assertBucket(buckets.get(0), expectedKeyFirstBucket, 1L, nullValue(), null, null);
@@ -250,7 +250,7 @@ public void testSingleValuedFieldNormalised_timeZone_CET_DstEnd() throws Excepti
250250
ZoneId timezone = ZoneId.of("CET");
251251
List<IndexRequestBuilder> builders = new ArrayList<>();
252252

253-
DateFormatter formatter = DateFormatter.forPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(timezone);
253+
DateFormatter formatter = DateFormatter.forPattern("uuuu-MM-dd'T'HH:mm:ss").withZone(timezone);
254254
addNTimes(1, IDX_DST_END, DateFormatters.from(formatter.parse("2012-10-27T01:00:00")), builders);
255255
// day with dst shift -1h, 25h long
256256
addNTimes(2, IDX_DST_END, DateFormatters.from(formatter.parse("2012-10-28T01:00:00")), builders);
@@ -274,7 +274,7 @@ public void testSingleValuedFieldNormalised_timeZone_CET_DstEnd() throws Excepti
274274
List<? extends Bucket> buckets = deriv.getBuckets();
275275
assertThat(buckets.size(), equalTo(4));
276276

277-
DateFormatter dateFormatter = DateFormatter.forPattern("yyyy-MM-dd").withZone(ZoneOffset.UTC);
277+
DateFormatter dateFormatter = DateFormatter.forPattern("uuuu-MM-dd").withZone(ZoneOffset.UTC);
278278

279279
ZonedDateTime expectedKeyFirstBucket =
280280
LocalDate.from(dateFormatter.parse("2012-10-27")).atStartOfDay(timezone).withZoneSameInstant(ZoneOffset.UTC);
@@ -303,7 +303,7 @@ public void testSingleValuedFieldNormalised_timeZone_AsiaKathmandu() throws Exce
303303
ZoneId timezone = ZoneId.of("Asia/Kathmandu");
304304
List<IndexRequestBuilder> builders = new ArrayList<>();
305305

306-
DateFormatter formatter = DateFormatter.forPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(timezone);
306+
DateFormatter formatter = DateFormatter.forPattern("uuuu-MM-dd'T'HH:mm:ss").withZone(timezone);
307307
addNTimes(1, IDX_DST_KATHMANDU, DateFormatters.from(formatter.parse("1985-12-31T22:30:00")), builders);
308308
// the shift happens during the next bucket, which includes the 45min that do not start on the full hour
309309
addNTimes(2, IDX_DST_KATHMANDU, DateFormatters.from(formatter.parse("1985-12-31T23:30:00")), builders);
@@ -327,7 +327,7 @@ public void testSingleValuedFieldNormalised_timeZone_AsiaKathmandu() throws Exce
327327
List<? extends Bucket> buckets = deriv.getBuckets();
328328
assertThat(buckets.size(), equalTo(4));
329329

330-
DateFormatter dateFormatter = DateFormatter.forPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(ZoneOffset.UTC);
330+
DateFormatter dateFormatter = DateFormatter.forPattern("uuuu-MM-dd'T'HH:mm:ss").withZone(ZoneOffset.UTC);
331331

332332
ZonedDateTime expectedKeyFirstBucket =
333333
LocalDateTime.from(dateFormatter.parse("1985-12-31T22:00:00")).atZone(timezone).withZoneSameInstant(ZoneOffset.UTC);

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/IndexLifecycleOriginationDateParser.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
public class IndexLifecycleOriginationDateParser {
1919

20-
private static final DateFormatter DATE_FORMATTER = DateFormatter.forPattern("yyyy.MM.dd");
20+
private static final DateFormatter DATE_FORMATTER = DateFormatter.forPattern("uuuu.MM.dd");
2121
private static final String INDEX_NAME_REGEX = "^.*-(\\d{4}.\\d{2}.\\d{2})(-[\\d]+)?$";
2222
private static final Pattern INDEX_NAME_PATTERN = Pattern.compile(INDEX_NAME_REGEX);
2323

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/IndexLifecycleOriginationDateParserTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
public class IndexLifecycleOriginationDateParserTests extends ESTestCase {
1919

20-
private static final DateFormatter dateFormatter = DateFormatter.forPattern("yyyy.MM.dd");
20+
private static final DateFormatter dateFormatter = DateFormatter.forPattern("uuuu.MM.dd");
2121

2222
public void testShouldParseIndexNameReturnsFalseWhenOriginationDateIsSet() {
2323
Settings settings = Settings.builder()

0 commit comments

Comments
 (0)