mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-09 14:34:43 +00:00
Dates: More strict parsing of ISO dates
If you are using the default date or the named identifiers of dates, the current implementation was allowed to read a year with only one digit. In order to make this more strict, this fixes a year to be at least 4 digits. Same applies for month, day, hour, minute, seconds. Also the new default is `strictDateOptionalTime` for indices created with Elasticsearch 2.0 or newer. In addition a couple of not exposed date formats have been exposed, as they have been mentioned in the documentation. Closes #6158
This commit is contained in:
parent
35ddc749b1
commit
b612cab96a
core/src
main/java/org
elasticsearch
common/joda
index/mapper
snapshots
joda/time/format
test/java/org/elasticsearch
deps/joda
index/mapper
search
docs/reference
mapping
migration
@ -118,6 +118,8 @@ public class Joda {
|
||||
formatter = ISODateTimeFormat.ordinalDateTimeNoMillis();
|
||||
} else if ("time".equals(input)) {
|
||||
formatter = ISODateTimeFormat.time();
|
||||
} else if ("timeNoMillis".equals(input) || "time_no_millis".equals(input)) {
|
||||
formatter = ISODateTimeFormat.timeNoMillis();
|
||||
} else if ("tTime".equals(input) || "t_time".equals(input)) {
|
||||
formatter = ISODateTimeFormat.tTime();
|
||||
} else if ("tTimeNoMillis".equals(input) || "t_time_no_millis".equals(input)) {
|
||||
@ -126,10 +128,14 @@ public class Joda {
|
||||
formatter = ISODateTimeFormat.weekDate();
|
||||
} else if ("weekDateTime".equals(input) || "week_date_time".equals(input)) {
|
||||
formatter = ISODateTimeFormat.weekDateTime();
|
||||
} else if ("weekDateTimeNoMillis".equals(input) || "week_date_time_no_millis".equals(input)) {
|
||||
formatter = ISODateTimeFormat.weekDateTimeNoMillis();
|
||||
} else if ("weekyear".equals(input) || "week_year".equals(input)) {
|
||||
formatter = ISODateTimeFormat.weekyear();
|
||||
} else if ("weekyearWeek".equals(input)) {
|
||||
} else if ("weekyearWeek".equals(input) || "weekyear_week".equals(input)) {
|
||||
formatter = ISODateTimeFormat.weekyearWeek();
|
||||
} else if ("weekyearWeekDay".equals(input) || "weekyear_week_day".equals(input)) {
|
||||
formatter = ISODateTimeFormat.weekyearWeekDay();
|
||||
} else if ("year".equals(input)) {
|
||||
formatter = ISODateTimeFormat.year();
|
||||
} else if ("yearMonth".equals(input) || "year_month".equals(input)) {
|
||||
@ -140,6 +146,77 @@ public class Joda {
|
||||
formatter = new DateTimeFormatterBuilder().append(new EpochTimePrinter(false), new EpochTimeParser(false)).toFormatter();
|
||||
} else if ("epoch_millis".equals(input)) {
|
||||
formatter = new DateTimeFormatterBuilder().append(new EpochTimePrinter(true), new EpochTimeParser(true)).toFormatter();
|
||||
// strict date formats here, must be at least 4 digits for year and two for months and two for day
|
||||
} else if ("strictBasicWeekDate".equals(input) || "strict_basic_week_date".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.basicWeekDate();
|
||||
} else if ("strictBasicWeekDateTime".equals(input) || "strict_basic_week_date_time".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.basicWeekDateTime();
|
||||
} else if ("strictBasicWeekDateTimeNoMillis".equals(input) || "strict_basic_week_date_time_no_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.basicWeekDateTimeNoMillis();
|
||||
} else if ("strictDate".equals(input) || "strict_date".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.date();
|
||||
} else if ("strictDateHour".equals(input) || "strict_date_hour".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.dateHour();
|
||||
} else if ("strictDateHourMinute".equals(input) || "strict_date_hour_minute".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.dateHourMinute();
|
||||
} else if ("strictDateHourMinuteSecond".equals(input) || "strict_date_hour_minute_second".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.dateHourMinuteSecond();
|
||||
} else if ("strictDateHourMinuteSecondFraction".equals(input) || "strict_date_hour_minute_second_fraction".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.dateHourMinuteSecondFraction();
|
||||
} else if ("strictDateHourMinuteSecondMillis".equals(input) || "strict_date_hour_minute_second_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.dateHourMinuteSecondMillis();
|
||||
} else if ("strictDateOptionalTime".equals(input) || "strict_date_optional_time".equals(input)) {
|
||||
// in this case, we have a separate parser and printer since the dataOptionalTimeParser can't print
|
||||
// this sucks we should use the root local by default and not be dependent on the node
|
||||
return new FormatDateTimeFormatter(input,
|
||||
StrictISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC),
|
||||
StrictISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC), locale);
|
||||
} else if ("strictDateTime".equals(input) || "strict_date_time".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.dateTime();
|
||||
} else if ("strictDateTimeNoMillis".equals(input) || "strict_date_time_no_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.dateTimeNoMillis();
|
||||
} else if ("strictHour".equals(input) || "strict_hour".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.hour();
|
||||
} else if ("strictHourMinute".equals(input) || "strict_hour_minute".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.hourMinute();
|
||||
} else if ("strictHourMinuteSecond".equals(input) || "strict_hour_minute_second".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.hourMinuteSecond();
|
||||
} else if ("strictHourMinuteSecondFraction".equals(input) || "strict_hour_minute_second_fraction".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.hourMinuteSecondFraction();
|
||||
} else if ("strictHourMinuteSecondMillis".equals(input) || "strict_hour_minute_second_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.hourMinuteSecondMillis();
|
||||
} else if ("strictOrdinalDate".equals(input) || "strict_ordinal_date".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.ordinalDate();
|
||||
} else if ("strictOrdinalDateTime".equals(input) || "strict_ordinal_date_time".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.ordinalDateTime();
|
||||
} else if ("strictOrdinalDateTimeNoMillis".equals(input) || "strict_ordinal_date_time_no_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.ordinalDateTimeNoMillis();
|
||||
} else if ("strictTime".equals(input) || "strict_time".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.time();
|
||||
} else if ("strictTimeNoMillis".equals(input) || "strict_time_no_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.timeNoMillis();
|
||||
} else if ("strictTTime".equals(input) || "strict_t_time".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.tTime();
|
||||
} else if ("strictTTimeNoMillis".equals(input) || "strict_t_time_no_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.tTimeNoMillis();
|
||||
} else if ("strictWeekDate".equals(input) || "strict_week_date".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.weekDate();
|
||||
} else if ("strictWeekDateTime".equals(input) || "strict_week_date_time".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.weekDateTime();
|
||||
} else if ("strictWeekDateTimeNoMillis".equals(input) || "strict_week_date_time_no_millis".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.weekDateTimeNoMillis();
|
||||
} else if ("strictWeekyear".equals(input) || "strict_weekyear".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.weekyear();
|
||||
} else if ("strictWeekyearWeek".equals(input) || "strict_weekyear_week".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.weekyearWeek();
|
||||
} else if ("strictWeekyearWeekDay".equals(input) || "strict_weekyear_week_day".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.weekyearWeekDay();
|
||||
} else if ("strictYear".equals(input) || "strict_year".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.year();
|
||||
} else if ("strictYearMonth".equals(input) || "strict_year_month".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.yearMonth();
|
||||
} else if ("strictYearMonthDay".equals(input) || "strict_year_month_day".equals(input)) {
|
||||
formatter = StrictISODateTimeFormat.yearMonthDay();
|
||||
} else if (Strings.hasLength(input) && input.contains("||")) {
|
||||
String[] formats = Strings.delimitedListToStringArray(input, "||");
|
||||
DateTimeParser[] parsers = new DateTimeParser[formats.length];
|
||||
@ -171,6 +248,38 @@ public class Joda {
|
||||
return new FormatDateTimeFormatter(input, formatter.withZone(DateTimeZone.UTC), locale);
|
||||
}
|
||||
|
||||
public static FormatDateTimeFormatter getStrictStandardDateFormatter() {
|
||||
// 2014/10/10
|
||||
DateTimeFormatter shortFormatter = new DateTimeFormatterBuilder()
|
||||
.appendFixedDecimal(DateTimeFieldType.year(), 4)
|
||||
.appendLiteral('/')
|
||||
.appendFixedDecimal(DateTimeFieldType.monthOfYear(), 2)
|
||||
.appendLiteral('/')
|
||||
.appendFixedDecimal(DateTimeFieldType.dayOfMonth(), 2)
|
||||
.toFormatter()
|
||||
.withZoneUTC();
|
||||
|
||||
// 2014/10/10 12:12:12
|
||||
DateTimeFormatter longFormatter = new DateTimeFormatterBuilder()
|
||||
.appendFixedDecimal(DateTimeFieldType.year(), 4)
|
||||
.appendLiteral('/')
|
||||
.appendFixedDecimal(DateTimeFieldType.monthOfYear(), 2)
|
||||
.appendLiteral('/')
|
||||
.appendFixedDecimal(DateTimeFieldType.dayOfMonth(), 2)
|
||||
.appendLiteral(' ')
|
||||
.appendFixedSignedDecimal(DateTimeFieldType.hourOfDay(), 2)
|
||||
.appendLiteral(':')
|
||||
.appendFixedSignedDecimal(DateTimeFieldType.minuteOfHour(), 2)
|
||||
.appendLiteral(':')
|
||||
.appendFixedSignedDecimal(DateTimeFieldType.secondOfMinute(), 2)
|
||||
.toFormatter()
|
||||
.withZoneUTC();
|
||||
|
||||
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder().append(longFormatter.withZone(DateTimeZone.UTC).getPrinter(), new DateTimeParser[] {longFormatter.getParser(), shortFormatter.getParser()});
|
||||
|
||||
return new FormatDateTimeFormatter("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd", builder.toFormatter().withZone(DateTimeZone.UTC), Locale.ROOT);
|
||||
}
|
||||
|
||||
|
||||
public static final DurationFieldType Quarters = new DurationFieldType("quarters") {
|
||||
private static final long serialVersionUID = -8167713675442491871L;
|
||||
|
@ -69,7 +69,8 @@ public class DateFieldMapper extends NumberFieldMapper {
|
||||
public static final String CONTENT_TYPE = "date";
|
||||
|
||||
public static class Defaults extends NumberFieldMapper.Defaults {
|
||||
public static final FormatDateTimeFormatter DATE_TIME_FORMATTER = Joda.forPattern("dateOptionalTime||epoch_millis", Locale.ROOT);
|
||||
public static final FormatDateTimeFormatter DATE_TIME_FORMATTER = Joda.forPattern("strictDateOptionalTime||epoch_millis", Locale.ROOT);
|
||||
public static final FormatDateTimeFormatter DATE_TIME_FORMATTER_BEFORE_2_0 = Joda.forPattern("dateOptionalTime", Locale.ROOT);
|
||||
public static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
|
||||
public static final DateFieldType FIELD_TYPE = new DateFieldType();
|
||||
|
||||
@ -123,15 +124,13 @@ public class DateFieldMapper extends NumberFieldMapper {
|
||||
}
|
||||
|
||||
protected void setupFieldType(BuilderContext context) {
|
||||
FormatDateTimeFormatter dateTimeFormatter = fieldType().dateTimeFormatter;
|
||||
// TODO MOVE ME OUTSIDE OF THIS SPACE?
|
||||
if (Version.indexCreated(context.indexSettings()).before(Version.V_2_0_0)) {
|
||||
boolean includesEpochFormatter = dateTimeFormatter.format().contains("epoch_");
|
||||
if (!includesEpochFormatter) {
|
||||
String format = fieldType().timeUnit().equals(TimeUnit.SECONDS) ? "epoch_second" : "epoch_millis";
|
||||
fieldType().setDateTimeFormatter(Joda.forPattern(format + "||" + dateTimeFormatter.format()));
|
||||
}
|
||||
if (Version.indexCreated(context.indexSettings()).before(Version.V_2_0_0) &&
|
||||
!fieldType().dateTimeFormatter().format().contains("epoch_")) {
|
||||
String format = fieldType().timeUnit().equals(TimeUnit.SECONDS) ? "epoch_second" : "epoch_millis";
|
||||
fieldType().setDateTimeFormatter(Joda.forPattern(format + "||" + fieldType().dateTimeFormatter().format()));
|
||||
}
|
||||
|
||||
FormatDateTimeFormatter dateTimeFormatter = fieldType().dateTimeFormatter;
|
||||
if (!locale.equals(dateTimeFormatter.locale())) {
|
||||
fieldType().setDateTimeFormatter(new FormatDateTimeFormatter(dateTimeFormatter.format(), dateTimeFormatter.parser(), dateTimeFormatter.printer(), locale));
|
||||
}
|
||||
@ -159,6 +158,7 @@ public class DateFieldMapper extends NumberFieldMapper {
|
||||
public Mapper.Builder<?, ?> parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
||||
DateFieldMapper.Builder builder = dateField(name);
|
||||
parseNumberField(builder, name, node, parserContext);
|
||||
boolean configuredFormat = false;
|
||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<String, Object> entry = iterator.next();
|
||||
String propName = Strings.toUnderscoreCase(entry.getKey());
|
||||
@ -171,6 +171,7 @@ public class DateFieldMapper extends NumberFieldMapper {
|
||||
iterator.remove();
|
||||
} else if (propName.equals("format")) {
|
||||
builder.dateTimeFormatter(parseDateTimeFormatter(propNode));
|
||||
configuredFormat = true;
|
||||
iterator.remove();
|
||||
} else if (propName.equals("numeric_resolution")) {
|
||||
builder.timeUnit(TimeUnit.valueOf(propNode.toString().toUpperCase(Locale.ROOT)));
|
||||
@ -180,6 +181,13 @@ public class DateFieldMapper extends NumberFieldMapper {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (!configuredFormat) {
|
||||
if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) {
|
||||
builder.dateTimeFormatter(Defaults.DATE_TIME_FORMATTER);
|
||||
} else {
|
||||
builder.dateTimeFormatter(Defaults.DATE_TIME_FORMATTER_BEFORE_2_0);
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
@ -24,14 +24,12 @@ import org.apache.lucene.document.NumericDocValuesField;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.TimestampParsingException;
|
||||
import org.elasticsearch.common.Explicit;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||
import org.elasticsearch.common.joda.Joda;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||
import org.elasticsearch.index.analysis.NumericDateAnalyzer;
|
||||
import org.elasticsearch.index.fielddata.FieldDataType;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
@ -41,10 +39,8 @@ import org.elasticsearch.index.mapper.MergeMappingException;
|
||||
import org.elasticsearch.index.mapper.MergeResult;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.DateFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.LongFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
@ -59,15 +55,16 @@ public class TimestampFieldMapper extends MetadataFieldMapper {
|
||||
|
||||
public static final String NAME = "_timestamp";
|
||||
public static final String CONTENT_TYPE = "_timestamp";
|
||||
public static final String DEFAULT_DATE_TIME_FORMAT = "epoch_millis||dateOptionalTime";
|
||||
public static final String DEFAULT_DATE_TIME_FORMAT = "epoch_millis||strictDateOptionalTime";
|
||||
|
||||
public static class Defaults extends DateFieldMapper.Defaults {
|
||||
public static final String NAME = "_timestamp";
|
||||
|
||||
// TODO: this should be removed
|
||||
public static final MappedFieldType PRE_20_FIELD_TYPE;
|
||||
public static final FormatDateTimeFormatter DATE_TIME_FORMATTER = Joda.forPattern(DEFAULT_DATE_TIME_FORMAT);
|
||||
public static final TimestampFieldType PRE_20_FIELD_TYPE;
|
||||
public static final TimestampFieldType FIELD_TYPE = new TimestampFieldType();
|
||||
public static final FormatDateTimeFormatter DATE_TIME_FORMATTER = Joda.forPattern(DEFAULT_DATE_TIME_FORMAT);
|
||||
public static final FormatDateTimeFormatter DATE_TIME_FORMATTER_BEFORE_2_0 = Joda.forPattern("epoch_millis||dateOptionalTime");
|
||||
|
||||
static {
|
||||
FIELD_TYPE.setStored(true);
|
||||
@ -82,6 +79,9 @@ public class TimestampFieldMapper extends MetadataFieldMapper {
|
||||
PRE_20_FIELD_TYPE = FIELD_TYPE.clone();
|
||||
PRE_20_FIELD_TYPE.setStored(false);
|
||||
PRE_20_FIELD_TYPE.setHasDocValues(false);
|
||||
PRE_20_FIELD_TYPE.setDateTimeFormatter(DATE_TIME_FORMATTER_BEFORE_2_0);
|
||||
PRE_20_FIELD_TYPE.setIndexAnalyzer(NumericDateAnalyzer.buildNamedAnalyzer(DATE_TIME_FORMATTER_BEFORE_2_0, Defaults.PRECISION_STEP_64_BIT));
|
||||
PRE_20_FIELD_TYPE.setSearchAnalyzer(NumericDateAnalyzer.buildNamedAnalyzer(DATE_TIME_FORMATTER_BEFORE_2_0, Integer.MAX_VALUE));
|
||||
PRE_20_FIELD_TYPE.freeze();
|
||||
}
|
||||
|
||||
@ -146,8 +146,23 @@ public class TimestampFieldMapper extends MetadataFieldMapper {
|
||||
if (explicitStore == false && context.indexCreatedVersion().before(Version.V_2_0_0)) {
|
||||
fieldType.setStored(false);
|
||||
}
|
||||
|
||||
if (fieldType().dateTimeFormatter().equals(Defaults.DATE_TIME_FORMATTER)) {
|
||||
fieldType().setDateTimeFormatter(getDateTimeFormatter(context.indexSettings()));
|
||||
}
|
||||
|
||||
setupFieldType(context);
|
||||
return new TimestampFieldMapper(fieldType, defaultFieldType, enabledState, path, defaultTimestamp, ignoreMissing, context.indexSettings());
|
||||
return new TimestampFieldMapper(fieldType, defaultFieldType, enabledState, path, defaultTimestamp,
|
||||
ignoreMissing, context.indexSettings());
|
||||
}
|
||||
}
|
||||
|
||||
private static FormatDateTimeFormatter getDateTimeFormatter(Settings indexSettings) {
|
||||
Version indexCreated = Version.indexCreated(indexSettings);
|
||||
if (indexCreated.onOrAfter(Version.V_2_0_0)) {
|
||||
return Defaults.DATE_TIME_FORMATTER;
|
||||
} else {
|
||||
return Defaults.DATE_TIME_FORMATTER_BEFORE_2_0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +356,9 @@ public class TimestampFieldMapper extends MetadataFieldMapper {
|
||||
if (indexCreatedBefore2x && (includeDefaults || path != Defaults.PATH)) {
|
||||
builder.field("path", path);
|
||||
}
|
||||
if (includeDefaults || !fieldType().dateTimeFormatter().format().equals(Defaults.DATE_TIME_FORMATTER.format())) {
|
||||
// different format handling depending on index version
|
||||
String defaultDateFormat = indexCreatedBefore2x ? Defaults.DATE_TIME_FORMATTER_BEFORE_2_0.format() : Defaults.DATE_TIME_FORMATTER.format();
|
||||
if (includeDefaults || !fieldType().dateTimeFormatter().format().equals(defaultDateFormat)) {
|
||||
builder.field("format", fieldType().dateTimeFormatter().format());
|
||||
}
|
||||
if (includeDefaults || !Defaults.DEFAULT_TIMESTAMP.equals(defaultTimestamp)) {
|
||||
|
@ -49,7 +49,7 @@ public class RootObjectMapper extends ObjectMapper {
|
||||
public static final FormatDateTimeFormatter[] DYNAMIC_DATE_TIME_FORMATTERS =
|
||||
new FormatDateTimeFormatter[]{
|
||||
DateFieldMapper.Defaults.DATE_TIME_FORMATTER,
|
||||
Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd")
|
||||
Joda.getStrictStandardDateFormatter()
|
||||
};
|
||||
public static final boolean DATE_DETECTION = true;
|
||||
public static final boolean NUMERIC_DETECTION = false;
|
||||
|
@ -38,7 +38,7 @@ import com.google.common.collect.ImmutableList;
|
||||
*/
|
||||
public class SnapshotInfo implements ToXContent, Streamable {
|
||||
|
||||
private static final FormatDateTimeFormatter DATE_TIME_FORMATTER = Joda.forPattern("dateOptionalTime");
|
||||
private static final FormatDateTimeFormatter DATE_TIME_FORMATTER = Joda.forPattern("strictDateOptionalTime");
|
||||
|
||||
private String name;
|
||||
|
||||
|
2028
core/src/main/java/org/joda/time/format/StrictISODateTimeFormat.java
Normal file
2028
core/src/main/java/org/joda/time/format/StrictISODateTimeFormat.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -22,8 +22,11 @@ package org.elasticsearch.deps.joda;
|
||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||
import org.elasticsearch.common.joda.Joda;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.index.mapper.core.DateFieldMapper;
|
||||
import org.elasticsearch.index.mapper.object.RootObjectMapper;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeFieldType;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.joda.time.MutableDateTime;
|
||||
@ -361,6 +364,368 @@ public class SimpleJodaTests extends ElasticsearchTestCase {
|
||||
assertThat(secondsDateTime.getMillis(), is(1234567890000l));
|
||||
}
|
||||
|
||||
public void testThatDefaultFormatterChecksForCorrectYearLength() throws Exception {
|
||||
// if no strict version is tested, this means the date format is already strict by itself
|
||||
// yyyyMMdd
|
||||
assertValidDateFormatParsing("basicDate", "20140303");
|
||||
assertDateFormatParsingThrowingException("basicDate", "2010303");
|
||||
|
||||
// yyyyMMdd’T'HHmmss.SSSZ
|
||||
assertValidDateFormatParsing("basicDateTime", "20140303T124343.123Z");
|
||||
assertValidDateFormatParsing("basicDateTime", "00050303T124343.123Z");
|
||||
assertDateFormatParsingThrowingException("basicDateTime", "50303T124343.123Z");
|
||||
|
||||
// yyyyMMdd’T'HHmmssZ
|
||||
assertValidDateFormatParsing("basicDateTimeNoMillis", "20140303T124343Z");
|
||||
assertValidDateFormatParsing("basicDateTimeNoMillis", "00050303T124343Z");
|
||||
assertDateFormatParsingThrowingException("basicDateTimeNoMillis", "50303T124343Z");
|
||||
|
||||
// yyyyDDD
|
||||
assertValidDateFormatParsing("basicOrdinalDate", "0005165");
|
||||
assertDateFormatParsingThrowingException("basicOrdinalDate", "5165");
|
||||
|
||||
// yyyyDDD’T'HHmmss.SSSZ
|
||||
assertValidDateFormatParsing("basicOrdinalDateTime", "0005165T124343.123Z");
|
||||
assertValidDateFormatParsing("basicOrdinalDateTime", "0005165T124343.123Z");
|
||||
assertDateFormatParsingThrowingException("basicOrdinalDateTime", "5165T124343.123Z");
|
||||
|
||||
// yyyyDDD’T'HHmmssZ
|
||||
assertValidDateFormatParsing("basicOrdinalDateTimeNoMillis", "0005165T124343Z");
|
||||
assertValidDateFormatParsing("basicOrdinalDateTimeNoMillis", "0005165T124343Z");
|
||||
assertDateFormatParsingThrowingException("basicOrdinalDateTimeNoMillis", "5165T124343Z");
|
||||
|
||||
// HHmmss.SSSZ
|
||||
assertValidDateFormatParsing("basicTime", "090909.123Z");
|
||||
assertDateFormatParsingThrowingException("basicTime", "90909.123Z");
|
||||
|
||||
// HHmmssZ
|
||||
assertValidDateFormatParsing("basicTimeNoMillis", "090909Z");
|
||||
assertDateFormatParsingThrowingException("basicTimeNoMillis", "90909Z");
|
||||
|
||||
// 'T’HHmmss.SSSZ
|
||||
assertValidDateFormatParsing("basicTTime", "T090909.123Z");
|
||||
assertDateFormatParsingThrowingException("basicTTime", "T90909.123Z");
|
||||
|
||||
// T’HHmmssZ
|
||||
assertValidDateFormatParsing("basicTTimeNoMillis", "T090909Z");
|
||||
assertDateFormatParsingThrowingException("basicTTimeNoMillis", "T90909Z");
|
||||
|
||||
// xxxx’W'wwe
|
||||
assertValidDateFormatParsing("basicWeekDate", "0005W414");
|
||||
assertValidDateFormatParsing("basicWeekDate", "5W414", "0005W414");
|
||||
assertDateFormatParsingThrowingException("basicWeekDate", "5W14");
|
||||
|
||||
assertValidDateFormatParsing("strictBasicWeekDate", "0005W414");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDate", "0005W47");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDate", "5W414");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDate", "5W14");
|
||||
|
||||
// xxxx’W'wwe’T'HHmmss.SSSZ
|
||||
assertValidDateFormatParsing("basicWeekDateTime", "0005W414T124343.123Z");
|
||||
assertValidDateFormatParsing("basicWeekDateTime", "5W414T124343.123Z", "0005W414T124343.123Z");
|
||||
assertDateFormatParsingThrowingException("basicWeekDateTime", "5W14T124343.123Z");
|
||||
|
||||
assertValidDateFormatParsing("strictBasicWeekDateTime", "0005W414T124343.123Z");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDateTime", "0005W47T124343.123Z");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDateTime", "5W414T124343.123Z");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDateTime", "5W14T124343.123Z");
|
||||
|
||||
// xxxx’W'wwe’T'HHmmssZ
|
||||
assertValidDateFormatParsing("basicWeekDateTimeNoMillis", "0005W414T124343Z");
|
||||
assertValidDateFormatParsing("basicWeekDateTimeNoMillis", "5W414T124343Z", "0005W414T124343Z");
|
||||
assertDateFormatParsingThrowingException("basicWeekDateTimeNoMillis", "5W14T124343Z");
|
||||
|
||||
assertValidDateFormatParsing("strictBasicWeekDateTimeNoMillis", "0005W414T124343Z");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDateTimeNoMillis", "0005W47T124343Z");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDateTimeNoMillis", "5W414T124343Z");
|
||||
assertDateFormatParsingThrowingException("strictBasicWeekDateTimeNoMillis", "5W14T124343Z");
|
||||
|
||||
// yyyy-MM-dd
|
||||
assertValidDateFormatParsing("date", "0005-06-03");
|
||||
assertValidDateFormatParsing("date", "5-6-3", "0005-06-03");
|
||||
|
||||
assertValidDateFormatParsing("strictDate", "0005-06-03");
|
||||
assertDateFormatParsingThrowingException("strictDate", "5-6-3");
|
||||
assertDateFormatParsingThrowingException("strictDate", "0005-06-3");
|
||||
assertDateFormatParsingThrowingException("strictDate", "0005-6-03");
|
||||
assertDateFormatParsingThrowingException("strictDate", "5-06-03");
|
||||
|
||||
// yyyy-MM-dd'T'HH
|
||||
assertValidDateFormatParsing("dateHour", "0005-06-03T12");
|
||||
assertValidDateFormatParsing("dateHour", "5-6-3T1", "0005-06-03T01");
|
||||
|
||||
assertValidDateFormatParsing("strictDateHour", "0005-06-03T12");
|
||||
assertDateFormatParsingThrowingException("strictDateHour", "5-6-3T1");
|
||||
|
||||
// yyyy-MM-dd'T'HH:mm
|
||||
assertValidDateFormatParsing("dateHourMinute", "0005-06-03T12:12");
|
||||
assertValidDateFormatParsing("dateHourMinute", "5-6-3T12:1", "0005-06-03T12:01");
|
||||
|
||||
assertValidDateFormatParsing("strictDateHourMinute", "0005-06-03T12:12");
|
||||
assertDateFormatParsingThrowingException("strictDateHourMinute", "5-6-3T12:1");
|
||||
|
||||
// yyyy-MM-dd'T'HH:mm:ss
|
||||
assertValidDateFormatParsing("dateHourMinuteSecond", "0005-06-03T12:12:12");
|
||||
assertValidDateFormatParsing("dateHourMinuteSecond", "5-6-3T12:12:1", "0005-06-03T12:12:01");
|
||||
|
||||
assertValidDateFormatParsing("strictDateHourMinuteSecond", "0005-06-03T12:12:12");
|
||||
assertDateFormatParsingThrowingException("strictDateHourMinuteSecond", "5-6-3T12:12:1");
|
||||
|
||||
// yyyy-MM-dd’T'HH:mm:ss.SSS
|
||||
assertValidDateFormatParsing("dateHourMinuteSecondFraction", "0005-06-03T12:12:12.123");
|
||||
assertValidDateFormatParsing("dateHourMinuteSecondFraction", "5-6-3T12:12:1.123", "0005-06-03T12:12:01.123");
|
||||
assertValidDateFormatParsing("dateHourMinuteSecondFraction", "5-6-3T12:12:1.1", "0005-06-03T12:12:01.100");
|
||||
|
||||
assertValidDateFormatParsing("strictDateHourMinuteSecondFraction", "0005-06-03T12:12:12.123");
|
||||
assertDateFormatParsingThrowingException("strictDateHourMinuteSecondFraction", "5-6-3T12:12:12.1");
|
||||
assertDateFormatParsingThrowingException("strictDateHourMinuteSecondFraction", "5-6-3T12:12:12.12");
|
||||
|
||||
assertValidDateFormatParsing("dateHourMinuteSecondMillis", "0005-06-03T12:12:12.123");
|
||||
assertValidDateFormatParsing("dateHourMinuteSecondMillis", "5-6-3T12:12:1.123", "0005-06-03T12:12:01.123");
|
||||
assertValidDateFormatParsing("dateHourMinuteSecondMillis", "5-6-3T12:12:1.1", "0005-06-03T12:12:01.100");
|
||||
|
||||
assertValidDateFormatParsing("strictDateHourMinuteSecondMillis", "0005-06-03T12:12:12.123");
|
||||
assertDateFormatParsingThrowingException("strictDateHourMinuteSecondMillis", "5-6-3T12:12:12.1");
|
||||
assertDateFormatParsingThrowingException("strictDateHourMinuteSecondMillis", "5-6-3T12:12:12.12");
|
||||
|
||||
// yyyy-MM-dd'T'HH:mm:ss.SSSZ
|
||||
assertValidDateFormatParsing("dateOptionalTime", "2014-03-03", "2014-03-03T00:00:00.000Z");
|
||||
assertValidDateFormatParsing("dateOptionalTime", "1257-3-03", "1257-03-03T00:00:00.000Z");
|
||||
assertValidDateFormatParsing("dateOptionalTime", "0005-03-3", "0005-03-03T00:00:00.000Z");
|
||||
assertValidDateFormatParsing("dateOptionalTime", "5-03-03", "0005-03-03T00:00:00.000Z");
|
||||
assertValidDateFormatParsing("dateOptionalTime", "5-03-03T1:1:1.1", "0005-03-03T01:01:01.100Z");
|
||||
assertValidDateFormatParsing("strictDateOptionalTime", "2014-03-03", "2014-03-03T00:00:00.000Z");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "0005-3-03");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "0005-03-3");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T1:1:1.1");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T01:01:01.1");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T01:01:1.100");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T01:1:01.100");
|
||||
assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T1:01:01.100");
|
||||
|
||||
// yyyy-MM-dd’T'HH:mm:ss.SSSZZ
|
||||
assertValidDateFormatParsing("dateTime", "5-03-03T1:1:1.1Z", "0005-03-03T01:01:01.100Z");
|
||||
assertValidDateFormatParsing("strictDateTime", "2014-03-03T11:11:11.100Z", "2014-03-03T11:11:11.100Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T1:1:1.1Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T01:01:1.100Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T01:1:01.100Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T1:01:01.100Z");
|
||||
|
||||
// yyyy-MM-dd’T'HH:mm:ssZZ
|
||||
assertValidDateFormatParsing("dateTimeNoMillis", "5-03-03T1:1:1Z", "0005-03-03T01:01:01Z");
|
||||
assertValidDateFormatParsing("strictDateTimeNoMillis", "2014-03-03T11:11:11Z", "2014-03-03T11:11:11Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T1:1:1Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T01:01:1Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T01:1:01Z");
|
||||
assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T1:01:01Z");
|
||||
|
||||
// HH
|
||||
assertValidDateFormatParsing("hour", "12");
|
||||
assertValidDateFormatParsing("hour", "1", "01");
|
||||
assertValidDateFormatParsing("strictHour", "12");
|
||||
assertValidDateFormatParsing("strictHour", "01");
|
||||
assertDateFormatParsingThrowingException("strictHour", "1");
|
||||
|
||||
// HH:mm
|
||||
assertValidDateFormatParsing("hourMinute", "12:12");
|
||||
assertValidDateFormatParsing("hourMinute", "12:1", "12:01");
|
||||
assertValidDateFormatParsing("strictHourMinute", "12:12");
|
||||
assertValidDateFormatParsing("strictHourMinute", "12:01");
|
||||
assertDateFormatParsingThrowingException("strictHourMinute", "12:1");
|
||||
|
||||
// HH:mm:ss
|
||||
assertValidDateFormatParsing("hourMinuteSecond", "12:12:12");
|
||||
assertValidDateFormatParsing("hourMinuteSecond", "12:12:1", "12:12:01");
|
||||
assertValidDateFormatParsing("strictHourMinuteSecond", "12:12:12");
|
||||
assertValidDateFormatParsing("strictHourMinuteSecond", "12:12:01");
|
||||
assertDateFormatParsingThrowingException("strictHourMinuteSecond", "12:12:1");
|
||||
|
||||
// HH:mm:ss.SSS
|
||||
assertValidDateFormatParsing("hourMinuteSecondFraction", "12:12:12.123");
|
||||
assertValidDateFormatParsing("hourMinuteSecondFraction", "12:12:12.1", "12:12:12.100");
|
||||
assertValidDateFormatParsing("strictHourMinuteSecondFraction", "12:12:12.123");
|
||||
assertValidDateFormatParsing("strictHourMinuteSecondFraction", "12:12:12.1", "12:12:12.100");
|
||||
|
||||
assertValidDateFormatParsing("hourMinuteSecondMillis", "12:12:12.123");
|
||||
assertValidDateFormatParsing("hourMinuteSecondMillis", "12:12:12.1", "12:12:12.100");
|
||||
assertValidDateFormatParsing("strictHourMinuteSecondMillis", "12:12:12.123");
|
||||
assertValidDateFormatParsing("strictHourMinuteSecondMillis", "12:12:12.1", "12:12:12.100");
|
||||
|
||||
// yyyy-DDD
|
||||
assertValidDateFormatParsing("ordinalDate", "5-3", "0005-003");
|
||||
assertValidDateFormatParsing("strictOrdinalDate", "0005-003");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDate", "5-3");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDate", "0005-3");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDate", "5-003");
|
||||
|
||||
// yyyy-DDD’T'HH:mm:ss.SSSZZ
|
||||
assertValidDateFormatParsing("ordinalDateTime", "5-3T12:12:12.100Z", "0005-003T12:12:12.100Z");
|
||||
assertValidDateFormatParsing("strictOrdinalDateTime", "0005-003T12:12:12.100Z");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDateTime", "5-3T1:12:12.123Z");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDateTime", "5-3T12:1:12.123Z");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDateTime", "5-3T12:12:1.123Z");
|
||||
|
||||
// yyyy-DDD’T'HH:mm:ssZZ
|
||||
assertValidDateFormatParsing("ordinalDateTimeNoMillis", "5-3T12:12:12Z", "0005-003T12:12:12Z");
|
||||
assertValidDateFormatParsing("strictOrdinalDateTimeNoMillis", "0005-003T12:12:12Z");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDateTimeNoMillis", "5-3T1:12:12Z");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDateTimeNoMillis", "5-3T12:1:12Z");
|
||||
assertDateFormatParsingThrowingException("strictOrdinalDateTimeNoMillis", "5-3T12:12:1Z");
|
||||
|
||||
|
||||
// HH:mm:ss.SSSZZ
|
||||
assertValidDateFormatParsing("time", "12:12:12.100Z");
|
||||
assertValidDateFormatParsing("time", "01:01:01.1Z", "01:01:01.100Z");
|
||||
assertValidDateFormatParsing("time", "1:1:1.1Z", "01:01:01.100Z");
|
||||
assertValidDateFormatParsing("strictTime", "12:12:12.100Z");
|
||||
assertDateFormatParsingThrowingException("strictTime", "12:12:1.100Z");
|
||||
assertDateFormatParsingThrowingException("strictTime", "12:1:12.100Z");
|
||||
assertDateFormatParsingThrowingException("strictTime", "1:12:12.100Z");
|
||||
|
||||
// HH:mm:ssZZ
|
||||
assertValidDateFormatParsing("timeNoMillis", "12:12:12Z");
|
||||
assertValidDateFormatParsing("timeNoMillis", "01:01:01Z", "01:01:01Z");
|
||||
assertValidDateFormatParsing("timeNoMillis", "1:1:1Z", "01:01:01Z");
|
||||
assertValidDateFormatParsing("strictTimeNoMillis", "12:12:12Z");
|
||||
assertDateFormatParsingThrowingException("strictTimeNoMillis", "12:12:1Z");
|
||||
assertDateFormatParsingThrowingException("strictTimeNoMillis", "12:1:12Z");
|
||||
assertDateFormatParsingThrowingException("strictTimeNoMillis", "1:12:12Z");
|
||||
|
||||
// 'T’HH:mm:ss.SSSZZ
|
||||
assertValidDateFormatParsing("tTime", "T12:12:12.100Z");
|
||||
assertValidDateFormatParsing("tTime", "T01:01:01.1Z", "T01:01:01.100Z");
|
||||
assertValidDateFormatParsing("tTime", "T1:1:1.1Z", "T01:01:01.100Z");
|
||||
assertValidDateFormatParsing("strictTTime", "T12:12:12.100Z");
|
||||
assertDateFormatParsingThrowingException("strictTTime", "T12:12:1.100Z");
|
||||
assertDateFormatParsingThrowingException("strictTTime", "T12:1:12.100Z");
|
||||
assertDateFormatParsingThrowingException("strictTTime", "T1:12:12.100Z");
|
||||
|
||||
// 'T’HH:mm:ssZZ
|
||||
assertValidDateFormatParsing("tTimeNoMillis", "T12:12:12Z");
|
||||
assertValidDateFormatParsing("tTimeNoMillis", "T01:01:01Z", "T01:01:01Z");
|
||||
assertValidDateFormatParsing("tTimeNoMillis", "T1:1:1Z", "T01:01:01Z");
|
||||
assertValidDateFormatParsing("strictTTimeNoMillis", "T12:12:12Z");
|
||||
assertDateFormatParsingThrowingException("strictTTimeNoMillis", "T12:12:1Z");
|
||||
assertDateFormatParsingThrowingException("strictTTimeNoMillis", "T12:1:12Z");
|
||||
assertDateFormatParsingThrowingException("strictTTimeNoMillis", "T1:12:12Z");
|
||||
|
||||
// xxxx-'W’ww-e
|
||||
assertValidDateFormatParsing("weekDate", "0005-W4-1", "0005-W04-1");
|
||||
assertValidDateFormatParsing("strictWeekDate", "0005-W04-1");
|
||||
assertDateFormatParsingThrowingException("strictWeekDate", "0005-W4-1");
|
||||
|
||||
// xxxx-'W’ww-e’T'HH:mm:ss.SSSZZ
|
||||
assertValidDateFormatParsing("weekDateTime", "0005-W41-4T12:43:43.123Z");
|
||||
assertValidDateFormatParsing("weekDateTime", "5-W41-4T12:43:43.123Z", "0005-W41-4T12:43:43.123Z");
|
||||
assertValidDateFormatParsing("strictWeekDateTime", "0005-W41-4T12:43:43.123Z");
|
||||
assertValidDateFormatParsing("strictWeekDateTime", "0005-W06-4T12:43:43.123Z");
|
||||
assertDateFormatParsingThrowingException("strictWeekDateTime", "0005-W4-7T12:43:43.123Z");
|
||||
assertDateFormatParsingThrowingException("strictWeekDateTime", "5-W41-4T12:43:43.123Z");
|
||||
assertDateFormatParsingThrowingException("strictWeekDateTime", "5-W1-4T12:43:43.123Z");
|
||||
|
||||
// xxxx-'W’ww-e’T'HH:mm:ssZZ
|
||||
assertValidDateFormatParsing("weekDateTimeNoMillis", "0005-W41-4T12:43:43Z");
|
||||
assertValidDateFormatParsing("weekDateTimeNoMillis", "5-W41-4T12:43:43Z", "0005-W41-4T12:43:43Z");
|
||||
assertValidDateFormatParsing("strictWeekDateTimeNoMillis", "0005-W41-4T12:43:43Z");
|
||||
assertValidDateFormatParsing("strictWeekDateTimeNoMillis", "0005-W06-4T12:43:43Z");
|
||||
assertDateFormatParsingThrowingException("strictWeekDateTimeNoMillis", "0005-W4-7T12:43:43Z");
|
||||
assertDateFormatParsingThrowingException("strictWeekDateTimeNoMillis", "5-W41-4T12:43:43Z");
|
||||
assertDateFormatParsingThrowingException("strictWeekDateTimeNoMillis", "5-W1-4T12:43:43Z");
|
||||
|
||||
// yyyy
|
||||
assertValidDateFormatParsing("weekyear", "2014");
|
||||
assertValidDateFormatParsing("weekyear", "5", "0005");
|
||||
assertValidDateFormatParsing("weekyear", "0005");
|
||||
assertValidDateFormatParsing("strictWeekyear", "2014");
|
||||
assertValidDateFormatParsing("strictWeekyear", "0005");
|
||||
assertDateFormatParsingThrowingException("strictWeekyear", "5");
|
||||
|
||||
// yyyy-'W'ee
|
||||
assertValidDateFormatParsing("weekyearWeek", "2014-W41");
|
||||
assertValidDateFormatParsing("weekyearWeek", "2014-W1", "2014-W01");
|
||||
assertValidDateFormatParsing("strictWeekyearWeek", "2014-W41");
|
||||
assertDateFormatParsingThrowingException("strictWeekyearWeek", "2014-W1");
|
||||
|
||||
// weekyearWeekDay
|
||||
assertValidDateFormatParsing("weekyearWeekDay", "2014-W41-1");
|
||||
assertValidDateFormatParsing("weekyearWeekDay", "2014-W1-1", "2014-W01-1");
|
||||
assertValidDateFormatParsing("strictWeekyearWeekDay", "2014-W41-1");
|
||||
assertDateFormatParsingThrowingException("strictWeekyearWeekDay", "2014-W1-1");
|
||||
|
||||
// yyyy
|
||||
assertValidDateFormatParsing("year", "2014");
|
||||
assertValidDateFormatParsing("year", "5", "0005");
|
||||
assertValidDateFormatParsing("strictYear", "2014");
|
||||
assertDateFormatParsingThrowingException("strictYear", "5");
|
||||
|
||||
// yyyy-mm
|
||||
assertValidDateFormatParsing("yearMonth", "2014-12");
|
||||
assertValidDateFormatParsing("yearMonth", "2014-5", "2014-05");
|
||||
assertValidDateFormatParsing("strictYearMonth", "2014-12");
|
||||
assertDateFormatParsingThrowingException("strictYearMonth", "2014-5");
|
||||
|
||||
// yyyy-mm-dd
|
||||
assertValidDateFormatParsing("yearMonthDay", "2014-12-12");
|
||||
assertValidDateFormatParsing("yearMonthDay", "2014-05-5", "2014-05-05");
|
||||
assertValidDateFormatParsing("strictYearMonthDay", "2014-12-12");
|
||||
assertDateFormatParsingThrowingException("strictYearMonthDay", "2014-05-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatRootObjectParsingIsStrict() throws Exception {
|
||||
String[] datesThatWork = new String[] { "2014/10/10", "2014/10/10 12:12:12", "2014-05-05", "2014-05-05T12:12:12.123Z" };
|
||||
String[] datesThatShouldNotWork = new String[]{ "5-05-05", "2014-5-05", "2014-05-5",
|
||||
"2014-05-05T1:12:12.123Z", "2014-05-05T12:1:12.123Z", "2014-05-05T12:12:1.123Z",
|
||||
"4/10/10", "2014/1/10", "2014/10/1",
|
||||
"2014/10/10 1:12:12", "2014/10/10 12:1:12", "2014/10/10 12:12:1"
|
||||
};
|
||||
|
||||
// good case
|
||||
for (String date : datesThatWork) {
|
||||
boolean dateParsingSuccessful = false;
|
||||
for (FormatDateTimeFormatter dateTimeFormatter : RootObjectMapper.Defaults.DYNAMIC_DATE_TIME_FORMATTERS) {
|
||||
try {
|
||||
dateTimeFormatter.parser().parseMillis(date);
|
||||
dateParsingSuccessful = true;
|
||||
break;
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
if (!dateParsingSuccessful) {
|
||||
fail("Parsing for date " + date + " in root object mapper failed, but shouldnt");
|
||||
}
|
||||
}
|
||||
|
||||
// bad case
|
||||
for (String date : datesThatShouldNotWork) {
|
||||
for (FormatDateTimeFormatter dateTimeFormatter : RootObjectMapper.Defaults.DYNAMIC_DATE_TIME_FORMATTERS) {
|
||||
try {
|
||||
dateTimeFormatter.parser().parseMillis(date);
|
||||
fail(String.format(Locale.ROOT, "Expected exception when parsing date %s in root mapper", date));
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertValidDateFormatParsing(String pattern, String dateToParse) {
|
||||
assertValidDateFormatParsing(pattern, dateToParse, dateToParse);
|
||||
}
|
||||
|
||||
private void assertValidDateFormatParsing(String pattern, String dateToParse, String expectedDate) {
|
||||
FormatDateTimeFormatter formatter = Joda.forPattern(pattern);
|
||||
assertThat(formatter.printer().print(formatter.parser().parseMillis(dateToParse)), is(expectedDate));
|
||||
}
|
||||
|
||||
private void assertDateFormatParsingThrowingException(String pattern, String invalidDate) {
|
||||
try {
|
||||
FormatDateTimeFormatter formatter = Joda.forPattern(pattern);
|
||||
DateTimeFormatter parser = formatter.parser();
|
||||
parser.parseMillis(invalidDate);
|
||||
fail(String.format(Locale.ROOT, "Expected parsing exception for pattern [%s] with date [%s], but did not happen", pattern, invalidDate));
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private long utcTimeInMillis(String time) {
|
||||
return ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC).parseMillis(time);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.search.NumericRangeQuery;
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
@ -45,6 +47,7 @@ import org.elasticsearch.index.mapper.core.StringFieldMapper;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
|
||||
import org.elasticsearch.test.TestSearchContext;
|
||||
import org.elasticsearch.test.VersionUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.junit.Before;
|
||||
@ -55,7 +58,6 @@ import java.util.*;
|
||||
import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAsBoolean;
|
||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.elasticsearch.index.mapper.string.SimpleStringMappingTests.docValuesType;
|
||||
import static org.elasticsearch.test.VersionUtils.randomVersionBetween;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
|
||||
@ -482,4 +484,94 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
|
||||
indexResponse = client().prepareIndex("test", "test").setSource(document).get();
|
||||
assertThat(indexResponse.isCreated(), is(true));
|
||||
}
|
||||
|
||||
public void testThatOlderIndicesAllowNonStrictDates() throws Exception {
|
||||
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||
.startObject("properties").startObject("date_field").field("type", "date").endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
Version randomVersion = VersionUtils.randomVersionBetween(getRandom(), Version.V_0_90_0, Version.V_1_6_1);
|
||||
IndexService index = createIndex("test", settingsBuilder().put(IndexMetaData.SETTING_VERSION_CREATED, randomVersion).build());
|
||||
client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping).get();
|
||||
assertDateFormat("epoch_millis||dateOptionalTime");
|
||||
DocumentMapper defaultMapper = index.mapperService().documentMapper("type");
|
||||
|
||||
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
|
||||
.startObject()
|
||||
.field("date_field", "1-1-1T00:00:44.000Z")
|
||||
.endObject()
|
||||
.bytes());
|
||||
|
||||
// also test normal date
|
||||
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
|
||||
.startObject()
|
||||
.field("date_field", "2015-06-06T00:00:44.000Z")
|
||||
.endObject()
|
||||
.bytes());
|
||||
}
|
||||
|
||||
public void testThatNewIndicesOnlyAllowStrictDates() throws Exception {
|
||||
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||
.startObject("properties").startObject("date_field").field("type", "date").endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
IndexService index = createIndex("test");
|
||||
client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping).get();
|
||||
assertDateFormat(DateFieldMapper.Defaults.DATE_TIME_FORMATTER.format());
|
||||
DocumentMapper defaultMapper = index.mapperService().documentMapper("type");
|
||||
|
||||
// also test normal date
|
||||
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
|
||||
.startObject()
|
||||
.field("date_field", "2015-06-06T00:00:44.000Z")
|
||||
.endObject()
|
||||
.bytes());
|
||||
|
||||
try {
|
||||
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
|
||||
.startObject()
|
||||
.field("date_field", "1-1-1T00:00:44.000Z")
|
||||
.endObject()
|
||||
.bytes());
|
||||
fail("non strict date indexing should have been failed");
|
||||
} catch (MapperParsingException e) {
|
||||
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
|
||||
}
|
||||
}
|
||||
|
||||
public void testThatUpgradingAnOlderIndexToStrictDateWorks() throws Exception {
|
||||
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||
.startObject("properties").startObject("date_field").field("type", "date").field("format", "dateOptionalTime").endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
Version randomVersion = VersionUtils.randomVersionBetween(getRandom(), Version.V_0_90_0, Version.V_1_6_1);
|
||||
createIndex("test", settingsBuilder().put(IndexMetaData.SETTING_VERSION_CREATED, randomVersion).build());
|
||||
client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping).get();
|
||||
assertDateFormat("epoch_millis||dateOptionalTime");
|
||||
|
||||
// index doc
|
||||
client().prepareIndex("test", "type", "1").setSource(XContentFactory.jsonBuilder()
|
||||
.startObject()
|
||||
.field("date_field", "2015-06-06T00:00:44.000Z")
|
||||
.endObject()).get();
|
||||
|
||||
// update mapping
|
||||
String newMapping = XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||
.startObject("properties").startObject("date_field")
|
||||
.field("type", "date")
|
||||
.field("format", "strictDateOptionalTime||epoch_millis")
|
||||
.endObject().endObject().endObject().endObject().string();
|
||||
PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("type").setSource(newMapping).get();
|
||||
assertThat(putMappingResponse.isAcknowledged(), is(true));
|
||||
|
||||
assertDateFormat("strictDateOptionalTime||epoch_millis");
|
||||
}
|
||||
|
||||
private void assertDateFormat(String expectedFormat) throws IOException {
|
||||
GetMappingsResponse response = client().admin().indices().prepareGetMappings("test").setTypes("type").get();
|
||||
Map<String, Object> mappingMap = response.getMappings().get("test").get("type").getSourceAsMap();
|
||||
Map<String, Object> properties = (Map<String, Object>) mappingMap.get("properties");
|
||||
Map<String, Object> dateField = (Map<String, Object>) properties.get("date_field");
|
||||
assertThat((String) dateField.get("format"), is(expectedFormat));
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.mapper.*;
|
||||
import org.elasticsearch.index.mapper.internal.TimestampFieldMapper;
|
||||
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
|
||||
@ -56,14 +55,7 @@ import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.elasticsearch.test.VersionUtils.randomVersion;
|
||||
import static org.elasticsearch.test.VersionUtils.randomVersionBetween;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasKey;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isIn;
|
||||
import static org.hamcrest.Matchers.lessThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
*/
|
||||
@ -113,8 +105,10 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
|
||||
assertThat(docMapper.timestampFieldMapper().fieldType().stored(), equalTo(version.onOrAfter(Version.V_2_0_0)));
|
||||
assertThat(docMapper.timestampFieldMapper().fieldType().indexOptions(), equalTo(TimestampFieldMapper.Defaults.FIELD_TYPE.indexOptions()));
|
||||
assertThat(docMapper.timestampFieldMapper().path(), equalTo(TimestampFieldMapper.Defaults.PATH));
|
||||
assertThat(docMapper.timestampFieldMapper().fieldType().dateTimeFormatter().format(), equalTo(TimestampFieldMapper.DEFAULT_DATE_TIME_FORMAT));
|
||||
assertThat(docMapper.timestampFieldMapper().fieldType().hasDocValues(), equalTo(version.onOrAfter(Version.V_2_0_0)));
|
||||
String expectedFormat = version.onOrAfter(Version.V_2_0_0) ? TimestampFieldMapper.DEFAULT_DATE_TIME_FORMAT :
|
||||
TimestampFieldMapper.Defaults.DATE_TIME_FORMATTER_BEFORE_2_0.format();
|
||||
assertThat(docMapper.timestampFieldMapper().fieldType().dateTimeFormatter().format(), equalTo(expectedFormat));
|
||||
assertAcked(client().admin().indices().prepareDelete("test").execute().get());
|
||||
}
|
||||
}
|
||||
@ -755,7 +749,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
|
||||
IndexRequest request = new IndexRequest("test", "type", "1").source(doc);
|
||||
request.process(metaData, mappingMetaData, true, "test");
|
||||
|
||||
assertEquals(request.timestamp(), "1");
|
||||
assertThat(request.timestamp(), is("1"));
|
||||
}
|
||||
|
||||
public void testIncludeInObjectBackcompat() throws Exception {
|
||||
|
@ -1281,9 +1281,9 @@ public class DateHistogramTests extends ElasticsearchIntegrationTest {
|
||||
public void testIssue8209() throws InterruptedException, ExecutionException {
|
||||
assertAcked(client().admin().indices().prepareCreate("test8209").addMapping("type", "d", "type=date").get());
|
||||
indexRandom(true,
|
||||
client().prepareIndex("test8209", "type").setSource("d", "2014-01-01T0:00:00Z"),
|
||||
client().prepareIndex("test8209", "type").setSource("d", "2014-04-01T0:00:00Z"),
|
||||
client().prepareIndex("test8209", "type").setSource("d", "2014-04-30T0:00:00Z"));
|
||||
client().prepareIndex("test8209", "type").setSource("d", "2014-01-01T00:00:00Z"),
|
||||
client().prepareIndex("test8209", "type").setSource("d", "2014-04-01T00:00:00Z"),
|
||||
client().prepareIndex("test8209", "type").setSource("d", "2014-04-30T00:00:00Z"));
|
||||
ensureSearchable("test8209");
|
||||
SearchResponse response = client().prepareSearch("test8209")
|
||||
.addAggregation(dateHistogram("histo").field("d").interval(DateHistogramInterval.MONTH).timeZone("CET")
|
||||
|
@ -42,6 +42,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.client.Requests.indexRequest;
|
||||
import static org.elasticsearch.client.Requests.searchRequest;
|
||||
@ -530,17 +531,17 @@ public class DecayFunctionScoreTests extends ElasticsearchIntegrationTest {
|
||||
ensureYellow();
|
||||
|
||||
DateTime docDate = dt.minusDays(1);
|
||||
String docDateString = docDate.getYear() + "-" + docDate.getMonthOfYear() + "-" + docDate.getDayOfMonth();
|
||||
String docDateString = docDate.getYear() + "-" + String.format(Locale.ROOT, "%02d", docDate.getMonthOfYear()) + "-" + String.format(Locale.ROOT, "%02d", docDate.getDayOfMonth());
|
||||
client().index(
|
||||
indexRequest("test").type("type1").id("1")
|
||||
.source(jsonBuilder().startObject().field("test", "value").field("num1", docDateString).endObject())).actionGet();
|
||||
docDate = dt.minusDays(2);
|
||||
docDateString = docDate.getYear() + "-" + docDate.getMonthOfYear() + "-" + docDate.getDayOfMonth();
|
||||
docDateString = docDate.getYear() + "-" + String.format(Locale.ROOT, "%02d", docDate.getMonthOfYear()) + "-" + String.format(Locale.ROOT, "%02d", docDate.getDayOfMonth());
|
||||
client().index(
|
||||
indexRequest("test").type("type1").id("2")
|
||||
.source(jsonBuilder().startObject().field("test", "value").field("num1", docDateString).endObject())).actionGet();
|
||||
docDate = dt.minusDays(3);
|
||||
docDateString = docDate.getYear() + "-" + docDate.getMonthOfYear() + "-" + docDate.getDayOfMonth();
|
||||
docDateString = docDate.getYear() + "-" + String.format(Locale.ROOT, "%02d", docDate.getMonthOfYear()) + "-" + String.format(Locale.ROOT, "%02d", docDate.getDayOfMonth());
|
||||
client().index(
|
||||
indexRequest("test").type("type1").id("3")
|
||||
.source(jsonBuilder().startObject().field("test", "value").field("num1", docDateString).endObject())).actionGet();
|
||||
|
@ -49,6 +49,13 @@ first millisecond of the rounding scope. The semantics work as follows:
|
||||
[[built-in]]
|
||||
=== Built In Formats
|
||||
|
||||
Most of the below dates have a `strict` companion dates, which means, that
|
||||
year, month and day parts of the week must have prepending zeros in order
|
||||
to be valid. This means, that a date like `5/11/1` would not be valid, but
|
||||
you would need to specify the full date, which would be `2005/11/01` in this
|
||||
example. So instead of `date_optional_time` you would need to specify
|
||||
`strict_date_optional_time`.
|
||||
|
||||
The following tables lists all the defaults ISO formats supported:
|
||||
|
||||
[cols="<,<",options="header",]
|
||||
@ -92,112 +99,125 @@ offset prefixed by 'T' ('T'HHmmssZ).
|
||||
|
||||
|`basic_week_date`|A basic formatter for a full date as four digit
|
||||
weekyear, two digit week of weekyear, and one digit day of week
|
||||
(xxxx'W'wwe).
|
||||
(xxxx'W'wwe). `strict_basic_week_date` is supported.
|
||||
|
||||
|`basic_week_date_time`|A basic formatter that combines a basic weekyear
|
||||
date and time, separated by a 'T' (xxxx'W'wwe'T'HHmmss.SSSZ).
|
||||
`strict_basic_week_date_time` is supported.
|
||||
|
||||
|`basic_week_date_time_no_millis`|A basic formatter that combines a basic
|
||||
weekyear date and time without millis, separated by a 'T'
|
||||
(xxxx'W'wwe'T'HHmmssZ).
|
||||
(xxxx'W'wwe'T'HHmmssZ). `strict_week_date_time` is supported.
|
||||
|
||||
|`date`|A formatter for a full date as four digit year, two digit month
|
||||
of year, and two digit day of month (yyyy-MM-dd).
|
||||
|
||||
of year, and two digit day of month (yyyy-MM-dd). `strict_date` is supported.
|
||||
_
|
||||
|`date_hour`|A formatter that combines a full date and two digit hour of
|
||||
day.
|
||||
day. strict_date_hour` is supported.
|
||||
|
||||
|
||||
|`date_hour_minute`|A formatter that combines a full date, two digit hour
|
||||
of day, and two digit minute of hour.
|
||||
of day, and two digit minute of hour. strict_date_hour_minute` is supported.
|
||||
|
||||
|`date_hour_minute_second`|A formatter that combines a full date, two
|
||||
digit hour of day, two digit minute of hour, and two digit second of
|
||||
minute.
|
||||
minute. `strict_date_hour_minute_second` is supported.
|
||||
|
||||
|`date_hour_minute_second_fraction`|A formatter that combines a full
|
||||
date, two digit hour of day, two digit minute of hour, two digit second
|
||||
of minute, and three digit fraction of second
|
||||
(yyyy-MM-dd'T'HH:mm:ss.SSS).
|
||||
(yyyy-MM-dd'T'HH:mm:ss.SSS). `strict_date_hour_minute_second_fraction` is supported.
|
||||
|
||||
|`date_hour_minute_second_millis`|A formatter that combines a full date,
|
||||
two digit hour of day, two digit minute of hour, two digit second of
|
||||
minute, and three digit fraction of second (yyyy-MM-dd'T'HH:mm:ss.SSS).
|
||||
`strict_date_hour_minute_second_millis` is supported.
|
||||
|
||||
|`date_optional_time`|a generic ISO datetime parser where the date is
|
||||
mandatory and the time is optional.
|
||||
mandatory and the time is optional. `strict_date_optional_time` is supported.
|
||||
|
||||
|`date_time`|A formatter that combines a full date and time, separated by
|
||||
a 'T' (yyyy-MM-dd'T'HH:mm:ss.SSSZZ).
|
||||
a 'T' (yyyy-MM-dd'T'HH:mm:ss.SSSZZ). `strict_date_time` is supported.
|
||||
|
||||
|`date_time_no_millis`|A formatter that combines a full date and time
|
||||
without millis, separated by a 'T' (yyyy-MM-dd'T'HH:mm:ssZZ).
|
||||
`strict_date_time_no_millis` is supported.
|
||||
|
||||
|`hour`|A formatter for a two digit hour of day.
|
||||
|`hour`|A formatter for a two digit hour of day. `strict_hour` is supported.
|
||||
|
||||
|`hour_minute`|A formatter for a two digit hour of day and two digit
|
||||
minute of hour.
|
||||
minute of hour. `strict_hour_minute` is supported.
|
||||
|
||||
|`hour_minute_second`|A formatter for a two digit hour of day, two digit
|
||||
minute of hour, and two digit second of minute.
|
||||
`strict_hour_minute_second` is supported.
|
||||
|
||||
|`hour_minute_second_fraction`|A formatter for a two digit hour of day,
|
||||
two digit minute of hour, two digit second of minute, and three digit
|
||||
fraction of second (HH:mm:ss.SSS).
|
||||
`strict_hour_minute_second_fraction` is supported.
|
||||
|
||||
|`hour_minute_second_millis`|A formatter for a two digit hour of day, two
|
||||
digit minute of hour, two digit second of minute, and three digit
|
||||
fraction of second (HH:mm:ss.SSS).
|
||||
`strict_hour_minute_second_millis` is supported.
|
||||
|
||||
|`ordinal_date`|A formatter for a full ordinal date, using a four digit
|
||||
year and three digit dayOfYear (yyyy-DDD).
|
||||
year and three digit dayOfYear (yyyy-DDD). `strict_ordinal_date` is supported.
|
||||
|
||||
|`ordinal_date_time`|A formatter for a full ordinal date and time, using
|
||||
a four digit year and three digit dayOfYear (yyyy-DDD'T'HH:mm:ss.SSSZZ).
|
||||
`strict_ordinal_date_time` is supported.
|
||||
|
||||
|`ordinal_date_time_no_millis`|A formatter for a full ordinal date and
|
||||
time without millis, using a four digit year and three digit dayOfYear
|
||||
(yyyy-DDD'T'HH:mm:ssZZ).
|
||||
`strict_ordinal_date_time_no_millis` is supported.
|
||||
|
||||
|`time`|A formatter for a two digit hour of day, two digit minute of
|
||||
hour, two digit second of minute, three digit fraction of second, and
|
||||
time zone offset (HH:mm:ss.SSSZZ).
|
||||
time zone offset (HH:mm:ss.SSSZZ). `strict_time` is supported.
|
||||
|
||||
|`time_no_millis`|A formatter for a two digit hour of day, two digit
|
||||
minute of hour, two digit second of minute, and time zone offset
|
||||
(HH:mm:ssZZ).
|
||||
(HH:mm:ssZZ). `strict_time_no_millis` is supported.
|
||||
|
||||
|`t_time`|A formatter for a two digit hour of day, two digit minute of
|
||||
hour, two digit second of minute, three digit fraction of second, and
|
||||
time zone offset prefixed by 'T' ('T'HH:mm:ss.SSSZZ).
|
||||
`strict_t_time` is supported.
|
||||
|
||||
|`t_time_no_millis`|A formatter for a two digit hour of day, two digit
|
||||
minute of hour, two digit second of minute, and time zone offset
|
||||
prefixed by 'T' ('T'HH:mm:ssZZ).
|
||||
prefixed by 'T' ('T'HH:mm:ssZZ). `strict_t_time_no_millis` is supported.
|
||||
|
||||
|`week_date`|A formatter for a full date as four digit weekyear, two
|
||||
digit week of weekyear, and one digit day of week (xxxx-'W'ww-e).
|
||||
`strict_week_date` is supported.
|
||||
|
||||
|`week_date_time`|A formatter that combines a full weekyear date and
|
||||
time, separated by a 'T' (xxxx-'W'ww-e'T'HH:mm:ss.SSSZZ).
|
||||
`strict_week_date_time` is supported.
|
||||
|
||||
|`weekDateTimeNoMillis`|A formatter that combines a full weekyear date
|
||||
|`week_date_time_no_millis`|A formatter that combines a full weekyear date
|
||||
and time without millis, separated by a 'T' (xxxx-'W'ww-e'T'HH:mm:ssZZ).
|
||||
`strict_week_date_time` is supported.
|
||||
|
||||
|`week_year`|A formatter for a four digit weekyear.
|
||||
|`weekyear`|A formatter for a four digit weekyear. `strict_week_year` is supported.
|
||||
|
||||
|`weekyearWeek`|A formatter for a four digit weekyear and two digit week
|
||||
of weekyear.
|
||||
|`weekyear_week`|A formatter for a four digit weekyear and two digit week
|
||||
of weekyear. `strict_weekyear_week` is supported.
|
||||
|
||||
|`weekyearWeekDay`|A formatter for a four digit weekyear, two digit week
|
||||
of weekyear, and one digit day of week.
|
||||
|`weekyear_week_day`|A formatter for a four digit weekyear, two digit week
|
||||
of weekyear, and one digit day of week. `strict_weekyear_week_day` is supported.
|
||||
|
||||
|`year`|A formatter for a four digit year.
|
||||
|`year`|A formatter for a four digit year. `strict_year` is supported.
|
||||
|
||||
|`year_month`|A formatter for a four digit year and two digit month of
|
||||
year.
|
||||
year. `strict_year_month` is supported.
|
||||
|
||||
|`year_month_day`|A formatter for a four digit year, two digit month of
|
||||
year, and two digit day of month.
|
||||
year, and two digit day of month. `strict_year_month_day` is supported.
|
||||
|
||||
|`epoch_second`|A formatter for the number of seconds since the epoch.
|
||||
Note, that this timestamp allows a max length of 10 chars, so dates
|
||||
|
@ -40,7 +40,7 @@ format>> used to parse the provided timestamp value. For example:
|
||||
}
|
||||
--------------------------------------------------
|
||||
|
||||
Note, the default format is `epoch_millis||dateOptionalTime`. The timestamp value will
|
||||
Note, the default format is `epoch_millis||strictDateOptionalTime`. The timestamp value will
|
||||
first be parsed as a number and if it fails the format will be tried.
|
||||
|
||||
[float]
|
||||
|
@ -349,7 +349,7 @@ date type:
|
||||
Defaults to the property/field name.
|
||||
|
||||
|`format` |The <<mapping-date-format,date
|
||||
format>>. Defaults to `epoch_millis||dateOptionalTime`.
|
||||
format>>. Defaults to `epoch_millis||strictDateOptionalTime`.
|
||||
|
||||
|`store` |Set to `true` to store actual field in the index, `false` to not
|
||||
store it. Defaults to `false` (note, the JSON document itself is stored,
|
||||
|
@ -42,7 +42,7 @@ and will use the matching format as its format attribute. The date
|
||||
format itself is explained
|
||||
<<mapping-date-format,here>>.
|
||||
|
||||
The default formats are: `dateOptionalTime` (ISO),
|
||||
The default formats are: `strictDateOptionalTime` (ISO) and
|
||||
`yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z` and `epoch_millis`.
|
||||
|
||||
*Note:* `dynamic_date_formats` are used *only* for dynamically added
|
||||
|
@ -302,6 +302,13 @@ Meta fields can no longer be specified within a document. They should be specifi
|
||||
via the API. For example, instead of adding a field `_parent` within a document,
|
||||
use the `parent` url parameter when indexing that document.
|
||||
|
||||
==== Default date format now is `strictDateOptionalDate`
|
||||
|
||||
Instead of `dateOptionalTime` the new default date format now is `strictDateOptionalTime`,
|
||||
which is more strict in parsing dates. This means, that dates now need to have a four digit year,
|
||||
a two-digit month, day, hour, minute and second. This means, you may need to preprend a part of the date
|
||||
with a zero to make it conform or switch back to the old `dateOptionalTime` format.
|
||||
|
||||
==== Date format does not support unix timestamps by default
|
||||
|
||||
In earlier versions of elasticsearch, every timestamp was always tried to be parsed as
|
||||
@ -723,4 +730,4 @@ to prevent clashes with the watcher plugin
|
||||
|
||||
=== Percolator stats
|
||||
|
||||
Changed the `percolate.getTime` stat (total time spent on percolating) to `percolate.time` state.
|
||||
Changed the `percolate.getTime` stat (total time spent on percolating) to `percolate.time` state.
|
||||
|
Loading…
x
Reference in New Issue
Block a user