Create ISO8601 joda compatible java time formatter (#38434)
The existing formatter being used was not on par with the joda formatter as it was missing the ability to parse a comma as a separator between seconds and milliseconds. While a real iso8601 would be much more complex, this might be sufficient for some more use-cases. The ingest date formatter now also uses the iso8601 formatter by default. Closes #38345
This commit is contained in:
parent
e7868e92bd
commit
884b5063a4
|
@ -45,7 +45,7 @@ enum DateFormat {
|
|||
Iso8601 {
|
||||
@Override
|
||||
Function<String, ZonedDateTime> getFunction(String format, ZoneId timezone, Locale locale) {
|
||||
return (date) -> DateFormatters.from(DateFormatter.forPattern("strict_date_time").parse(date)).withZoneSameInstant(timezone);
|
||||
return (date) -> DateFormatters.from(DateFormatter.forPattern("iso8601").parse(date)).withZoneSameInstant(timezone);
|
||||
}
|
||||
},
|
||||
Unix {
|
||||
|
|
|
@ -175,6 +175,43 @@ public class DateFormatters {
|
|||
private static final DateFormatter STRICT_DATE_OPTIONAL_TIME_NANOS = new JavaDateFormatter("strict_date_optional_time_nanos",
|
||||
STRICT_DATE_OPTIONAL_TIME_PRINTER_NANOS, STRICT_DATE_OPTIONAL_TIME_FORMATTER_WITH_NANOS);
|
||||
|
||||
/**
|
||||
* Returns a ISO 8601 compatible date time formatter and parser.
|
||||
* This is not fully compatible to the existing spec, which would require far more edge cases, but merely compatible with the
|
||||
* existing joda time ISO data formater
|
||||
*/
|
||||
private static final DateFormatter ISO_8601 = new JavaDateFormatter("iso8601", STRICT_DATE_OPTIONAL_TIME_PRINTER,
|
||||
new DateTimeFormatterBuilder()
|
||||
.append(STRICT_YEAR_MONTH_DAY_FORMATTER)
|
||||
.optionalStart()
|
||||
.appendLiteral('T')
|
||||
.optionalStart()
|
||||
.appendValue(HOUR_OF_DAY, 2, 2, SignStyle.NOT_NEGATIVE)
|
||||
.optionalStart()
|
||||
.appendLiteral(':')
|
||||
.appendValue(MINUTE_OF_HOUR, 2, 2, SignStyle.NOT_NEGATIVE)
|
||||
.optionalStart()
|
||||
.appendLiteral(':')
|
||||
.appendValue(SECOND_OF_MINUTE, 2, 2, SignStyle.NOT_NEGATIVE)
|
||||
.optionalStart()
|
||||
.appendFraction(NANO_OF_SECOND, 1, 9, true)
|
||||
.optionalEnd()
|
||||
.optionalStart()
|
||||
.appendLiteral(",")
|
||||
.appendFraction(NANO_OF_SECOND, 1, 9, false)
|
||||
.optionalEnd()
|
||||
.optionalEnd()
|
||||
.optionalStart()
|
||||
.appendZoneOrOffsetId()
|
||||
.optionalEnd()
|
||||
.optionalStart()
|
||||
.append(TIME_ZONE_FORMATTER_NO_COLON)
|
||||
.optionalEnd()
|
||||
.optionalEnd()
|
||||
.optionalEnd()
|
||||
.optionalEnd()
|
||||
.toFormatter(Locale.ROOT));
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
// BEGIN basic time formatters
|
||||
|
@ -1363,7 +1400,9 @@ public class DateFormatters {
|
|||
throw new IllegalArgumentException("No date pattern provided");
|
||||
}
|
||||
|
||||
if ("basicDate".equals(input) || "basic_date".equals(input)) {
|
||||
if ("iso8601".equals(input)) {
|
||||
return ISO_8601;
|
||||
} else if ("basicDate".equals(input) || "basic_date".equals(input)) {
|
||||
return BASIC_DATE;
|
||||
} else if ("basicDateTime".equals(input) || "basic_date_time".equals(input)) {
|
||||
return BASIC_DATE_TIME;
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.elasticsearch.common.time.DateFormatters;
|
|||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
|
@ -665,6 +666,23 @@ public class JavaJodaTimeDuellingTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
// the iso 8601 parser is available via Joda.forPattern(), so we have to test this slightly differently
|
||||
public void testIso8601Parsers() {
|
||||
String format = "iso8601";
|
||||
org.joda.time.format.DateTimeFormatter isoFormatter = ISODateTimeFormat.dateTimeParser().withZone(DateTimeZone.UTC);
|
||||
JodaDateFormatter jodaFormatter = new JodaDateFormatter(format, isoFormatter, isoFormatter);
|
||||
DateFormatter javaFormatter = DateFormatter.forPattern(format);
|
||||
|
||||
assertSameDate("2018-10-10T", format, jodaFormatter, javaFormatter);
|
||||
assertSameDate("2018-10-10T10", format, jodaFormatter, javaFormatter);
|
||||
assertSameDate("2018-10-10T10:11", format, jodaFormatter, javaFormatter);
|
||||
assertSameDate("2018-10-10T10:11:12", format, jodaFormatter, javaFormatter);
|
||||
assertSameDate("2018-10-10T10:11:12.123", format, jodaFormatter, javaFormatter);
|
||||
assertSameDate("2018-10-10T10:11:12.123Z", format, jodaFormatter, javaFormatter);
|
||||
assertSameDate("2018-10-10T10:11:12,123", format, jodaFormatter, javaFormatter);
|
||||
assertSameDate("2018-10-10T10:11:12,123Z", format, jodaFormatter, javaFormatter);
|
||||
}
|
||||
|
||||
private void assertSamePrinterOutput(String format, ZonedDateTime javaDate, DateTime jodaDate) {
|
||||
assertThat(jodaDate.getMillis(), is(javaDate.toInstant().toEpochMilli()));
|
||||
String javaTimeOut = DateFormatter.forPattern(format).format(javaDate);
|
||||
|
|
Loading…
Reference in New Issue