From ee63e89e93718cf3c2b83265eac5f6f507aeaadb Mon Sep 17 00:00:00 2001 From: viacheslav-augment Date: Mon, 3 Aug 2026 21:45:26 -0700 Subject: [PATCH 1/2] Default partial date parsing to year 1970 When a date format omits the year, Joda defaults the missing year to 2000. Set the parsers' default year to 1970 so partial dates use the epoch base, consistent with the 1970-01-01 base already used for round-ceil parsing in DateMathParser and with how partial dates are indexed. --- src/main/java/org/elasticsearch/common/joda/Joda.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/joda/Joda.java b/src/main/java/org/elasticsearch/common/joda/Joda.java index 6f538ebc76597..587be110e8208 100644 --- a/src/main/java/org/elasticsearch/common/joda/Joda.java +++ b/src/main/java/org/elasticsearch/common/joda/Joda.java @@ -91,7 +91,7 @@ public static FormatDateTimeFormatter forPattern(String input, Locale locale) { // 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, - ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC), + ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC).withDefaultYear(1970), ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC), locale); } else if ("dateTime".equals(input) || "date_time".equals(input)) { formatter = ISODateTimeFormat.dateTime(); @@ -160,7 +160,7 @@ public static FormatDateTimeFormatter forPattern(String input, Locale locale) { } } - return new FormatDateTimeFormatter(input, formatter.withZone(DateTimeZone.UTC), locale); + return new FormatDateTimeFormatter(input, formatter.withZone(DateTimeZone.UTC).withDefaultYear(1970), locale); } From 794aa40259357c00053c048a23a7c79164f1683d Mon Sep 17 00:00:00 2001 From: viacheslav-augment Date: Mon, 3 Aug 2026 21:46:53 -0700 Subject: [PATCH 2/2] Test partial dates default to year 1970 Covers Joda.forPattern parsers defaulting the missing year to the 1970 epoch base rather than joda's default of 2000. --- .../common/joda/DateMathParserTests.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java b/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java index 0a0418a16d3f1..40588f615ebda 100644 --- a/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java +++ b/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java @@ -1,6 +1,8 @@ package org.elasticsearch.common.joda; import org.elasticsearch.test.ElasticsearchTestCase; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; import org.junit.Test; import java.util.concurrent.TimeUnit; @@ -44,4 +46,13 @@ public void actualDateTests() { assertThat(parser.parse("2013-03-03||/y", 0), equalTo(parser.parse("2013-01-01", 0))); assertThat(parser.parseRoundCeil("2013-03-03||/y", 0), equalTo(parser.parse("2014-01-01", 0))); } + + @Test + public void partialDatesDefaultToYear1970() { + // when the year is not part of the format, it must default to the 1970 epoch base + // (rather than joda's default of 2000), consistent with how partial dates are indexed + DateMathParser parser = new DateMathParser(Joda.forPattern("MM-dd"), TimeUnit.MILLISECONDS); + assertThat(parser.parse("01-01", 0), equalTo(0l)); + assertThat(parser.parse("06-15", 0), equalTo(new DateTime(1970, 6, 15, 0, 0, DateTimeZone.UTC).getMillis())); + } }