Skip to content

Commit 2f7776c

Browse files
authored
Switch default time format for ingest from Joda to Java for v7 (#37934)
Date formats with and without the "8" prefix are now all treated as Java time formats, so that ingest does the same as mappings in this respect.
1 parent ecbaa38 commit 2f7776c

File tree

5 files changed

+31
-43
lines changed

5 files changed

+31
-43
lines changed

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

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.elasticsearch.ingest.common;
2121

22-
import org.elasticsearch.common.joda.Joda;
2322
import org.elasticsearch.common.time.DateFormatter;
2423
import org.elasticsearch.common.time.DateFormatters;
2524
import org.elasticsearch.common.time.DateUtils;
@@ -73,30 +72,22 @@ private long parseMillis(String date) {
7372
Java {
7473
@Override
7574
Function<String, DateTime> getFunction(String format, DateTimeZone timezone, Locale locale) {
76-
// in case you are wondering why we do not call 'DateFormatter.forPattern(format)' for all cases here, but only for the
77-
// non java time case:
78-
// When the joda date formatter parses a date then a year is always set, so that no fallback can be used, like
79-
// done in the JodaDateFormatter.withYear() code below
80-
// This means that we leave the existing parsing logic in place, but will fall back to the new java date parsing logic, if an
81-
// "8" is prepended to the date format string
82-
int year = LocalDate.now(ZoneOffset.UTC).getYear();
75+
76+
// support the 6.x BWC compatible way of parsing java 8 dates
8377
if (format.startsWith("8")) {
84-
DateFormatter formatter = DateFormatter.forPattern(format)
85-
.withLocale(locale)
86-
.withZone(DateUtils.dateTimeZoneToZoneId(timezone));
87-
return text -> {
88-
ZonedDateTime defaultZonedDateTime = Instant.EPOCH.atZone(ZoneOffset.UTC).withYear(year);
89-
TemporalAccessor accessor = formatter.parse(text);
90-
long millis = DateFormatters.toZonedDateTime(accessor, defaultZonedDateTime).toInstant().toEpochMilli();
91-
return new DateTime(millis, timezone);
92-
};
93-
} else {
94-
DateFormatter formatter = Joda.forPattern(format)
95-
.withYear(year)
96-
.withZone(DateUtils.dateTimeZoneToZoneId(timezone))
97-
.withLocale(locale);
98-
return text -> new DateTime(formatter.parseMillis(text), timezone);
78+
format = format.substring(1);
9979
}
80+
81+
int year = LocalDate.now(ZoneOffset.UTC).getYear();
82+
DateFormatter formatter = DateFormatter.forPattern(format)
83+
.withLocale(locale)
84+
.withZone(DateUtils.dateTimeZoneToZoneId(timezone));
85+
return text -> {
86+
ZonedDateTime defaultZonedDateTime = Instant.EPOCH.atZone(ZoneOffset.UTC).withYear(year);
87+
TemporalAccessor accessor = formatter.parse(text);
88+
long millis = DateFormatters.toZonedDateTime(accessor, defaultZonedDateTime).toInstant().toEpochMilli();
89+
return new DateTime(millis, timezone);
90+
};
10091
}
10192
};
10293

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public DateIndexNameProcessor create(Map<String, Processor.Factory> registry, St
157157
}
158158
List<String> dateFormatStrings = ConfigurationUtils.readOptionalList(TYPE, tag, config, "date_formats");
159159
if (dateFormatStrings == null) {
160-
dateFormatStrings = Collections.singletonList("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
160+
dateFormatStrings = Collections.singletonList("yyyy-MM-dd'T'HH:mm:ss.SSSXX");
161161
}
162162
List<Function<String, DateTime>> dateFormats = new ArrayList<>(dateFormatStrings.size());
163163
for (String format : dateFormatStrings) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434

3535
public class DateIndexNameProcessorTests extends ESTestCase {
3636

37-
public void testJodaPattern() throws Exception {
38-
Function<String, DateTime> function = DateFormat.Java.getFunction("yyyy-MM-dd'T'HH:mm:ss.SSSZ", DateTimeZone.UTC, Locale.ROOT);
37+
public void testJavaPattern() throws Exception {
38+
Function<String, DateTime> function = DateFormat.Java.getFunction("yyyy-MM-dd'T'HH:mm:ss.SSSXX", DateTimeZone.UTC, Locale.ROOT);
3939
DateIndexNameProcessor processor = createProcessor("_field", Collections.singletonList(function),
4040
DateTimeZone.UTC, "events-", "y", "yyyyMMdd");
4141
IngestDocument document = new IngestDocument("_index", "_type", "_id", null, null, null,
@@ -82,7 +82,7 @@ public void testUnix()throws Exception {
8282
public void testTemplatedFields() throws Exception {
8383
String indexNamePrefix = randomAlphaOfLength(10);
8484
String dateRounding = randomFrom("y", "M", "w", "d", "h", "m", "s");
85-
String indexNameFormat = randomFrom("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyyMMdd", "MM/dd/yyyy");
85+
String indexNameFormat = randomFrom("yyyy-MM-dd'T'HH:mm:ss.SSSXX", "yyyyMMdd", "MM/dd/yyyy");
8686
String date = Integer.toString(randomInt());
8787
Function<String, DateTime> dateTimeFunction = DateFormat.Unix.getFunction(null, DateTimeZone.UTC, null);
8888

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,19 @@ private TemplateScript.Factory templatize(ZoneId timezone) {
4949
String id = timezone.equals(ZoneOffset.UTC) ? "UTC" : timezone.getId();
5050
return new TestTemplateService.MockTemplateScript.Factory(id);
5151
}
52-
public void testJodaPattern() {
52+
53+
public void testJavaPattern() {
5354
DateProcessor dateProcessor = new DateProcessor(randomAlphaOfLength(10),
5455
templatize(ZoneId.of("Europe/Amsterdam")), templatize(Locale.ENGLISH),
55-
"date_as_string", Collections.singletonList("yyyy dd MM hh:mm:ss"), "date_as_date");
56+
"date_as_string", Collections.singletonList("yyyy dd MM HH:mm:ss"), "date_as_date");
5657
Map<String, Object> document = new HashMap<>();
5758
document.put("date_as_string", "2010 12 06 11:05:15");
5859
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), document);
5960
dateProcessor.execute(ingestDocument);
6061
assertThat(ingestDocument.getFieldValue("date_as_date", String.class), equalTo("2010-06-12T11:05:15.000+02:00"));
6162
}
6263

63-
public void testJodaPatternMultipleFormats() {
64+
public void testJavaPatternMultipleFormats() {
6465
List<String> matchFormats = new ArrayList<>();
6566
matchFormats.add("yyyy dd MM");
6667
matchFormats.add("dd/MM/yyyy");
@@ -98,7 +99,7 @@ public void testJodaPatternMultipleFormats() {
9899
}
99100
}
100101

101-
public void testInvalidJodaPattern() {
102+
public void testInvalidJavaPattern() {
102103
try {
103104
DateProcessor processor = new DateProcessor(randomAlphaOfLength(10),
104105
templatize(ZoneOffset.UTC), templatize(randomLocale(random())),
@@ -109,24 +110,22 @@ public void testInvalidJodaPattern() {
109110
fail("date processor execution should have failed");
110111
} catch(IllegalArgumentException e) {
111112
assertThat(e.getMessage(), equalTo("unable to parse date [2010]"));
112-
assertThat(e.getCause().getMessage(), equalTo("Invalid format: [invalid pattern]: Illegal pattern component: i"));
113+
assertThat(e.getCause().getMessage(), equalTo("Invalid format: [invalid pattern]: Unknown pattern letter: i"));
113114
}
114115
}
115116

116-
public void testJodaPatternLocale() {
117-
//TODO investigate if this is a bug in Joda
118-
assumeFalse("Can't run in a FIPS JVM, Joda parse date error", inFipsJvm());
119-
DateProcessor dateProcessor = new DateProcessor(randomAlphaOfLength(10),
117+
public void testJavaPatternLocale() {
118+
DateProcessor dateProcessor = new DateProcessor(randomAlphaOfLength(10),
120119
templatize(ZoneId.of("Europe/Amsterdam")), templatize(Locale.ITALIAN),
121-
"date_as_string", Collections.singletonList("yyyy dd MMM"), "date_as_date");
120+
"date_as_string", Collections.singletonList("yyyy dd MMMM"), "date_as_date");
122121
Map<String, Object> document = new HashMap<>();
123122
document.put("date_as_string", "2010 12 giugno");
124123
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), document);
125124
dateProcessor.execute(ingestDocument);
126125
assertThat(ingestDocument.getFieldValue("date_as_date", String.class), equalTo("2010-06-12T00:00:00.000+02:00"));
127126
}
128127

129-
public void testJodaPatternDefaultYear() {
128+
public void testJavaPatternDefaultYear() {
130129
String format = randomFrom("dd/MM", "8dd/MM");
131130
DateProcessor dateProcessor = new DateProcessor(randomAlphaOfLength(10),
132131
templatize(ZoneId.of("Europe/Amsterdam")), templatize(Locale.ENGLISH),

qa/smoke-test-ingest-with-all-dependencies/src/test/resources/rest-api-spec/test/ingest/20_combine_processors.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
2-
"Test logging":
2+
"Test with date processor":
33
- skip:
44
version: " - 6.9.99"
5-
reason: pre-7.0.0 will send no warnings
5+
reason: pre-7.0.0 requires the 8 prefix for Java time formats, so would treat the format in this test as a Joda time format
66
features: "warnings"
77

88
- do:
@@ -33,7 +33,7 @@
3333
"date" : {
3434
"field" : "timestamp",
3535
"target_field" : "timestamp",
36-
"formats" : ["dd/MMM/YYYY:HH:mm:ss Z"]
36+
"formats" : ["dd/MMM/yyyy:HH:mm:ss xx"]
3737
}
3838
},
3939
{
@@ -46,8 +46,6 @@
4646
- match: { acknowledged: true }
4747

4848
- do:
49-
warnings:
50-
- "Use of 'Y' (year-of-era) will change to 'y' in the next major version of Elasticsearch. Prefix your date format with '8' to use the new specifier."
5149
index:
5250
index: test
5351
type: test

0 commit comments

Comments
 (0)