Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Java.time] Retain prefixed date pattern in formatter (#48703) backport#48703 #49640

Closed
wants to merge 10 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,21 @@ static DateFormatter forPattern(String input) {
return Joda.forPattern(input);
}

// dates starting with 8 will not be using joda but java time formatters
input = input.substring(1);

List<String> patterns = splitCombinedPatterns(input);
// support the 6.x BWC compatible way of parsing java 8 dates
String format = strip8Prefix(input);
List<String> patterns = splitCombinedPatterns(format);
List<DateFormatter> formatters = patterns.stream()
.map(DateFormatters::forPattern)
.collect(Collectors.toList());

if (formatters.size() == 1) {
return formatters.get(0);
}
return JavaDateFormatter.combined(input, formatters);
}

return DateFormatters.merge(input, formatters);
static String strip8Prefix(String input) {
if (input.startsWith("8")) {
return input.substring(1);
}
return input;
}

static List<String> splitCombinedPatterns(String input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalQueries;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import static java.time.temporal.ChronoField.DAY_OF_MONTH;
Expand Down Expand Up @@ -1593,27 +1591,6 @@ public static DateFormatter forPattern(String input) {
}
}

static JavaDateFormatter merge(String pattern, List<DateFormatter> formatters) {
assert formatters.size() > 0;

List<DateTimeFormatter> dateTimeFormatters = new ArrayList<>(formatters.size());
DateTimeFormatterBuilder roundupBuilder = new DateTimeFormatterBuilder();
DateTimeFormatter printer = null;
for (DateFormatter formatter : formatters) {
assert formatter instanceof JavaDateFormatter;
JavaDateFormatter javaDateFormatter = (JavaDateFormatter) formatter;
if (printer == null) {
printer = javaDateFormatter.getPrinter();
}
dateTimeFormatters.addAll(javaDateFormatter.getParsers());
roundupBuilder.appendOptional(javaDateFormatter.getRoundupParser());
}
DateTimeFormatter roundUpParser = roundupBuilder.toFormatter(Locale.ROOT);

return new JavaDateFormatter(pattern, printer, builder -> builder.append(roundUpParser),
dateTimeFormatters.toArray(new DateTimeFormatter[0]));
}

private static final LocalDate LOCALDATE_EPOCH = LocalDate.of(1970, 1, 1);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -38,6 +39,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

class JavaDateFormatter implements DateFormatter {

Expand All @@ -56,13 +58,33 @@ class JavaDateFormatter implements DateFormatter {
private final String format;
private final DateTimeFormatter printer;
private final List<DateTimeFormatter> parsers;
private final DateTimeFormatter roundupParser;
private final JavaDateFormatter roundupParser;

static class RoundUpFormatter extends JavaDateFormatter{

RoundUpFormatter(String format, List<DateTimeFormatter> roundUpParsers) {
super(format, firstFrom(roundUpParsers),null, roundUpParsers);
}

private static DateTimeFormatter firstFrom(List<DateTimeFormatter> roundUpParsers) {
return roundUpParsers.get(0);
}

@Override
JavaDateFormatter getRoundupParser() {
throw new UnsupportedOperationException("RoundUpFormatter does not have another roundUpFormatter");
}
}

// named formatters use default roundUpParser
JavaDateFormatter(String format, DateTimeFormatter printer, DateTimeFormatter... parsers) {
this(format, printer, builder -> ROUND_UP_BASE_FIELDS.forEach(builder::parseDefaulting), parsers);
}

JavaDateFormatter(String format, DateTimeFormatter printer, Consumer<DateTimeFormatterBuilder> roundupParserConsumer,
// subclasses override roundUpParser
JavaDateFormatter(String format,
DateTimeFormatter printer,
Consumer<DateTimeFormatterBuilder> roundupParserConsumer,
DateTimeFormatter... parsers) {
if (printer == null) {
throw new IllegalArgumentException("printer may not be null");
Expand All @@ -83,20 +105,51 @@ class JavaDateFormatter implements DateFormatter {
} else {
this.parsers = Arrays.asList(parsers);
}
//this is when the RoundUp Formatter is created. In further merges (with ||) it will only append this one to a list.
List<DateTimeFormatter> roundUp = createRoundUpParser(format, roundupParserConsumer);
this.roundupParser = new RoundUpFormatter(format, roundUp) ;
}

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
private List<DateTimeFormatter> createRoundUpParser(String format,
Consumer<DateTimeFormatterBuilder> roundupParserConsumer) {
if (format.contains("||") == false) {
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.append(this.parsers.get(0));
roundupParserConsumer.accept(builder);
return Arrays.asList(builder.toFormatter(locale()));
}
roundupParserConsumer.accept(builder);
DateTimeFormatter roundupFormatter = builder.toFormatter(locale());
if (printer.getZone() != null) {
roundupFormatter = roundupFormatter.withZone(zone());
return null;
}

public static DateFormatter combined(String input, List<DateFormatter> formatters) {
assert formatters.size() > 0;

List<DateTimeFormatter> parsers = new ArrayList<>(formatters.size());
List<DateTimeFormatter> roundUpParsers = new ArrayList<>(formatters.size());

DateTimeFormatter printer = null;
for (DateFormatter formatter : formatters) {
assert formatter instanceof JavaDateFormatter;
JavaDateFormatter javaDateFormatter = (JavaDateFormatter) formatter;
if (printer == null) {
printer = javaDateFormatter.getPrinter();
}
parsers.addAll(javaDateFormatter.getParsers());
roundUpParsers.addAll(javaDateFormatter.getRoundupParser().getParsers());
}
this.roundupParser = roundupFormatter;

return new JavaDateFormatter(input, printer, roundUpParsers, parsers);
}

DateTimeFormatter getRoundupParser() {
private JavaDateFormatter(String format, DateTimeFormatter printer, List<DateTimeFormatter> roundUpParsers,
List<DateTimeFormatter> parsers) {
this.format = format;
this.printer = printer;
this.roundupParser = roundUpParsers != null ? new RoundUpFormatter(format, roundUpParsers ) : null;
this.parsers = parsers;
}

JavaDateFormatter getRoundupParser() {
return roundupParser;
}

Expand Down Expand Up @@ -155,9 +208,12 @@ public DateFormatter withZone(ZoneId zoneId) {
if (zoneId.equals(zone())) {
return this;
}

return new JavaDateFormatter(format, printer.withZone(zoneId),
parsers.stream().map(p -> p.withZone(zoneId)).toArray(size -> new DateTimeFormatter[size]));
List<DateTimeFormatter> parsers = this.parsers.stream().map(p -> p.withZone(zoneId)).collect(Collectors.toList());
List<DateTimeFormatter> roundUpParsers = this.roundupParser.getParsers()
.stream()
.map(p -> p.withZone(zoneId))
.collect(Collectors.toList());
return new JavaDateFormatter(format, printer.withZone(zoneId), roundUpParsers, parsers);
}

@Override
Expand All @@ -166,9 +222,12 @@ public DateFormatter withLocale(Locale locale) {
if (locale.equals(locale())) {
return this;
}

return new JavaDateFormatter(format, printer.withLocale(locale),
parsers.stream().map(p -> p.withLocale(locale)).toArray(size -> new DateTimeFormatter[size]));
List<DateTimeFormatter> parsers = this.parsers.stream().map(p -> p.withLocale(locale)).collect(Collectors.toList());
List<DateTimeFormatter> roundUpParsers = this.roundupParser.getParsers()
.stream()
.map(p -> p.withLocale(locale))
.collect(Collectors.toList());
return new JavaDateFormatter(format, printer.withLocale(locale), roundUpParsers, parsers);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalQueries;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.LongSupplier;

/**
Expand All @@ -48,14 +46,14 @@
public class JavaDateMathParser implements DateMathParser {

private final JavaDateFormatter formatter;
private final DateTimeFormatter roundUpFormatter;
private final String format;
private final JavaDateFormatter roundupParser;

JavaDateMathParser(String format, JavaDateFormatter formatter, DateTimeFormatter roundUpFormatter) {
Objects.requireNonNull(formatter);
JavaDateMathParser(String format, JavaDateFormatter formatter, JavaDateFormatter roundupParser) {
this.format = format;
this.roundupParser = roundupParser;
Objects.requireNonNull(formatter);
this.formatter = formatter;
this.roundUpFormatter = roundUpFormatter;
}

@Override
Expand Down Expand Up @@ -215,12 +213,12 @@ private long parseDateTime(String value, ZoneId timeZone, boolean roundUpIfNoTim
throw new IllegalArgumentException("cannot parse empty date");
}

Function<String,TemporalAccessor> formatter = roundUpIfNoTime ? this.roundUpFormatter::parse : this.formatter::parse;
DateFormatter formatter = roundUpIfNoTime ? this.roundupParser : this.formatter;
try {
if (timeZone == null) {
return DateFormatters.from(formatter.apply(value)).toInstant().toEpochMilli();
return DateFormatters.from(formatter.parse(value)).toInstant().toEpochMilli();
} else {
TemporalAccessor accessor = formatter.apply(value);
TemporalAccessor accessor = formatter.parse(value);
ZoneId zoneId = TemporalQueries.zone().queryFrom(accessor);
if (zoneId != null) {
timeZone = zoneId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,4 +357,21 @@ public DocumentMapper updateFieldType(Map<String, MappedFieldType> fullNameToFie
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return mapping.toXContent(builder, params);
}

@Override
public String toString() {
return "DocumentMapper{" +
"mapperService=" + mapperService +
", type='" + type + '\'' +
", typeText=" + typeText +
", mappingSource=" + mappingSource +
", mapping=" + mapping +
", documentParser=" + documentParser +
", fieldMappers=" + fieldMappers +
", objectMappers=" + objectMappers +
", hasNestedObjects=" + hasNestedObjects +
", deleteTombstoneMetadataFieldMappers=" + Arrays.toString(deleteTombstoneMetadataFieldMappers) +
", noopTombstoneMetadataFieldMappers=" + Arrays.toString(noopTombstoneMetadataFieldMappers) +
'}';
}
}
Loading