From 56b394170653ee590cf9908509be00fab690d918 Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Tue, 17 Dec 2013 21:13:14 -0500 Subject: [PATCH] Make partial dates without year to be 1970 based instead of 2000 Fixes #4451 Date fields without date (HH:mm:ss, for example) are parsed as time on Jan 1, 1970 UTC. However, before this change partial dates without year (MMM dd HH:mm:ss, for example) were parsed as as days of they year 2000. This change makes all partial dates to be treated based on year 1970. This is breaking change - before this change "Dec 15, 10:00:00" in most cases was parsed (and indexed) as "2000-12-15T10:00:00Z". After this change, it will be consistently parsed and indexed as "1970-12-15T10:00:00Z" --- .../common/joda/FormatDateTimeFormatter.java | 4 ++-- .../mapper/date/SimpleDateMappingTests.java | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/joda/FormatDateTimeFormatter.java b/src/main/java/org/elasticsearch/common/joda/FormatDateTimeFormatter.java index 942aca7663b61..7ec2981da3c0a 100644 --- a/src/main/java/org/elasticsearch/common/joda/FormatDateTimeFormatter.java +++ b/src/main/java/org/elasticsearch/common/joda/FormatDateTimeFormatter.java @@ -44,8 +44,8 @@ public FormatDateTimeFormatter(String format, DateTimeFormatter parser, Locale l public FormatDateTimeFormatter(String format, DateTimeFormatter parser, DateTimeFormatter printer, Locale locale) { this.format = format; this.locale = locale; - this.printer = locale == null ? printer : printer.withLocale(locale); - this.parser = locale == null ? parser : parser.withLocale(locale); + this.printer = locale == null ? printer.withDefaultYear(1970) : printer.withLocale(locale).withDefaultYear(1970); + this.parser = locale == null ? parser.withDefaultYear(1970) : parser.withLocale(locale).withDefaultYear(1970); } public String format() { diff --git a/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java index 95dff302ce312..c2a8319f441f8 100644 --- a/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java @@ -224,6 +224,30 @@ public void testHourFormat() throws Exception { assertThat(rangeFilter.getMin(), equalTo(new DateTime(TimeValue.timeValueHours(10).millis()).getMillis())); } + + @Test + public void testDayWithoutYearFormat() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .field("date_detection", false) + .startObject("properties").startObject("date_field").field("type", "date").field("format", "MMM dd HH:mm:ss").endObject().endObject() + .endObject().endObject().string(); + + DocumentMapper defaultMapper = mapper(mapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject() + .field("date_field", "Jan 02 10:00:00") + .endObject() + .bytes()); + assertThat(((LongFieldMapper.CustomLongNumericField) doc.rootDoc().getField("date_field")).numericAsString(), equalTo(Long.toString(new DateTime(TimeValue.timeValueHours(34).millis(), DateTimeZone.UTC).getMillis()))); + + Filter filter = defaultMapper.mappers().smartNameFieldMapper("date_field").rangeFilter("Jan 02 10:00:00", "Jan 02 11:00:00", true, true, null); + assertThat(filter, instanceOf(NumericRangeFilter.class)); + NumericRangeFilter rangeFilter = (NumericRangeFilter) filter; + assertThat(rangeFilter.getMax(), equalTo(new DateTime(TimeValue.timeValueHours(35).millis() + 999).getMillis())); // +999 to include the 00-01 minute + assertThat(rangeFilter.getMin(), equalTo(new DateTime(TimeValue.timeValueHours(34).millis()).getMillis())); + } + @Test public void testIgnoreMalformedOption() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")