Skip to content

Commit d87268a

Browse files
authored
Round up parsers should be based on a list of parsers backport(elastic#62290) (elastic#62604)
a dateformatter can be created with a list of parsers which are iterated during parsing and the first one that passes will return a parsed date. DateMathParser should do the same, when created based on a list of non-rounding parsers it should also iterate over all of them - it is at the moment only taking first element closing elastic#62207
1 parent 6e07158 commit d87268a

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,30 @@ JavaDateFormatter getRoundupParser() {
105105
} else {
106106
this.parsers = Arrays.asList(parsers);
107107
}
108-
//this is when the RoundUp Formatter is created. In further merges (with ||) it will only append this one to a list.
109108
List<DateTimeFormatter> roundUp = createRoundUpParser(format, roundupParserConsumer);
110109
this.roundupParser = new RoundUpFormatter(format, roundUp) ;
111110
}
112111

112+
/**
113+
* This is when the RoundUp Formatters are created. In further merges (with ||) it will only append them to a list.
114+
* || is not expected to be provided as format when a RoundUp formatter is created. It will be splitted before in
115+
* <code>DateFormatter.forPattern</code>
116+
* JavaDateFormatter created with a custom format like <code>DateFormatter.forPattern("YYYY")</code> will only have one parser
117+
* It is however possible to have a JavaDateFormatter with multiple parsers. For instance see a "date_time" formatter in
118+
* <code>DateFormatters</code>.
119+
* This means that we need to also have multiple RoundUp parsers.
120+
*/
113121
private List<DateTimeFormatter> createRoundUpParser(String format,
114122
Consumer<DateTimeFormatterBuilder> roundupParserConsumer) {
115123
if (format.contains("||") == false) {
116-
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
117-
builder.append(this.parsers.get(0));
118-
roundupParserConsumer.accept(builder);
119-
return Arrays.asList(builder.toFormatter(locale()));
124+
List<DateTimeFormatter> roundUpParsers = new ArrayList<>();
125+
for (DateTimeFormatter parser : this.parsers) {
126+
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
127+
builder.append(parser);
128+
roundupParserConsumer.accept(builder);
129+
roundUpParsers.add(builder.toFormatter(locale()));
130+
}
131+
return roundUpParsers;
120132
}
121133
return null;
122134
}

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,62 @@
2727
import java.time.ZoneId;
2828
import java.time.ZoneOffset;
2929
import java.time.ZonedDateTime;
30+
import java.time.format.DateTimeFormatterBuilder;
31+
import java.time.format.ResolverStyle;
32+
import java.util.Locale;
3033
import java.util.concurrent.atomic.AtomicBoolean;
3134
import java.util.function.LongSupplier;
3235

3336
import static org.hamcrest.Matchers.containsString;
37+
import static org.hamcrest.Matchers.equalTo;
3438
import static org.hamcrest.Matchers.is;
3539

3640
public class JavaDateMathParserTests extends ESTestCase {
3741

3842
private final DateFormatter formatter = DateFormatter.forPattern("date_optional_time||epoch_millis");
3943
private final DateMathParser parser = formatter.toDateMathParser();
4044

45+
46+
public void testRoundUpParserBasedOnList() {
47+
DateFormatter formatter = new JavaDateFormatter("test", new DateTimeFormatterBuilder()
48+
.appendPattern("uuuu-MM-dd")
49+
.toFormatter(Locale.ROOT),
50+
new DateTimeFormatterBuilder()
51+
.appendPattern("uuuu-MM-dd'T'HH:mm:ss.S").appendZoneOrOffsetId().toFormatter(Locale.ROOT)
52+
.withResolverStyle(ResolverStyle.STRICT),
53+
new DateTimeFormatterBuilder()
54+
.appendPattern("uuuu-MM-dd'T'HH:mm:ss.S").appendOffset("+HHmm", "Z").toFormatter(Locale.ROOT)
55+
.withResolverStyle(ResolverStyle.STRICT));
56+
Instant parsed = formatter.toDateMathParser().parse("1970-01-01T00:00:00.0+0000", () -> 0L, true, (ZoneId) null);
57+
assertThat(parsed.toEpochMilli(), equalTo(0L));
58+
}
59+
60+
public void testMergingOfMultipleParsers() {
61+
//date_time has 2 parsers, date_time_no_millis has 4. Parsing with rounding should be able to use all of them
62+
DateFormatter formatter = DateFormatter.forPattern("date_time||date_time_no_millis");
63+
//date_time 2 parsers
64+
Instant parsed = formatter.toDateMathParser().parse("1970-01-01T00:00:00.0+00:00", () -> 0L, true, (ZoneId) null);
65+
assertThat(parsed.toEpochMilli(), equalTo(0L));
66+
67+
68+
parsed = formatter.toDateMathParser().parse("1970-01-01T00:00:00.0+0000", () -> 0L, true, (ZoneId) null);
69+
assertThat(parsed.toEpochMilli(), equalTo(0L));
70+
71+
//date_time_no_millis 4 parsers
72+
parsed = formatter.toDateMathParser().parse("1970-01-01T00:00:00+00:00", () -> 0L, true, (ZoneId) null);
73+
assertThat(parsed.toEpochMilli(), equalTo(999L));//defaulting millis
74+
75+
parsed = formatter.toDateMathParser().parse("1970-01-01T00:00:00+0000", () -> 0L, true, (ZoneId) null);
76+
assertThat(parsed.toEpochMilli(), equalTo(999L));//defaulting millis
77+
78+
parsed = formatter.toDateMathParser().parse("1970-01-01T00:00:00UTC+00:00", () -> 0L, true, (ZoneId) null);
79+
assertThat(parsed.toEpochMilli(), equalTo(999L));//defaulting millis
80+
81+
// this one is actually still using parser number 3. I don't see a combination to use parser number 4
82+
parsed = formatter.toDateMathParser().parse("1970-01-01T00:00:00", () -> 0L, true, (ZoneId) null);
83+
assertThat(parsed.toEpochMilli(), equalTo(999L));//defaulting millis
84+
}
85+
4186
public void testOverridingLocaleOrZoneAndCompositeRoundUpParser() {
4287
//the pattern has to be composite and the match should not be on the first one
4388
DateFormatter formatter = DateFormatter.forPattern("date||epoch_millis").withLocale(randomLocale(random()));

0 commit comments

Comments
 (0)