diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cfcd4e6dfbd1..89616a8977e5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Support prefix list for remote repository attributes([#16271](https://github.com/opensearch-project/OpenSearch/pull/16271)) - Add new configuration setting `synonym_analyzer`, to the `synonym` and `synonym_graph` filters, enabling the specification of a custom analyzer for reading the synonym file ([#16488](https://github.com/opensearch-project/OpenSearch/pull/16488)). - Add stats for remote publication failure and move download failure stats to remote methods([#16682](https://github.com/opensearch-project/OpenSearch/pull/16682/)) +- Make timezone optional for strict_date_time format ([#16701](https://github.com/opensearch-project/OpenSearch/pull/16701)) ### Dependencies - Bump `com.google.cloud:google-cloud-core-http` from 2.23.0 to 2.47.0 ([#16504](https://github.com/opensearch-project/OpenSearch/pull/16504)) diff --git a/server/src/main/java/org/opensearch/common/time/DateFormatters.java b/server/src/main/java/org/opensearch/common/time/DateFormatters.java index 527dce7677dd8..f84d8a31decd7 100644 --- a/server/src/main/java/org/opensearch/common/time/DateFormatters.java +++ b/server/src/main/java/org/opensearch/common/time/DateFormatters.java @@ -732,6 +732,8 @@ public class DateFormatters { /* * Returns a formatter that combines a full date and time, separated by a 'T' * (uuuu-MM-dd'T'HH:mm:ss.SSSZZ). + * Timezone is optional and defaults to UTC, + * as Python's isoformat() can outputs ISO 8601-compliant dates that lack a timezone. */ private static final DateFormatter STRICT_DATE_TIME = new JavaDateFormatter( "strict_date_time", @@ -741,7 +743,9 @@ public class DateFormatters { .toFormatter(Locale.ROOT) .withResolverStyle(ResolverStyle.STRICT), new DateTimeFormatterBuilder().append(STRICT_DATE_FORMATTER) + .optionalStart() .append(TIME_ZONE_FORMATTER_NO_COLON) + .optionalEnd() .toFormatter(Locale.ROOT) .withResolverStyle(ResolverStyle.STRICT) ); diff --git a/server/src/test/java/org/opensearch/common/time/DateFormattersTests.java b/server/src/test/java/org/opensearch/common/time/DateFormattersTests.java index 2ccee197686ec..bb69ebd6c16c3 100644 --- a/server/src/test/java/org/opensearch/common/time/DateFormattersTests.java +++ b/server/src/test/java/org/opensearch/common/time/DateFormattersTests.java @@ -828,6 +828,22 @@ public void testCamelCaseDeprecation() { } } + public void testStrictDateTimeDefaultsToUTC() { + DateFormatter dateFormatter = DateFormatter.forPattern("strict_date_time"); + // "strict_date_time" formatter should be able to parse with and without a timezone specified, as both are valid in ISO 8601 + // See https://github.com/opensearch-project/OpenSearch/issues/16673 + assertEquals( + ZonedDateTime.of(2024, 11, 21, 0, 0, 0, 0, ZoneOffset.UTC), + DateFormatters.from(dateFormatter.parse("2024-11-21T00:00:00Z")) + ); + + // Should default to UTC without a timezone specified + assertEquals( + ZonedDateTime.of(2024, 11, 21, 0, 0, 0, 0, ZoneOffset.UTC), + DateFormatters.from(dateFormatter.parse("2024-11-21T00:00:00")) + ); + } + void assertDateTimeEquals(String toTest, DateFormatter candidateParser, DateFormatter baselineParser) { Instant gotInstant = DateFormatters.from(candidateParser.parse(toTest)).toInstant(); Instant expectedInstant = DateFormatters.from(baselineParser.parse(toTest)).toInstant();