diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy index b303ba5f38895..01b01998f905e 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy @@ -836,6 +836,12 @@ class BuildPlugin implements Plugin { if ((ext.get('runtimeJavaVersion') as JavaVersion) >= JavaVersion.VERSION_1_9) { test.jvmArgs '--illegal-access=warn' } + if ((ext.get('runtimeJavaVersion') as JavaVersion) == JavaVersion.VERSION_1_8) { + test.systemProperty ('java.locale.providers','SPI,JRE') + } else if ((ext.get('runtimeJavaVersion') as JavaVersion) >= JavaVersion.VERSION_1_9) { + test.systemProperty ('java.locale.providers','SPI,COMPAT') + } + } test.jvmArgumentProviders.add(nonInputProperties) diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy index 4617968949ce8..9130792421852 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy @@ -24,6 +24,7 @@ import org.elasticsearch.gradle.testclusters.RestTestRunnerTask import org.elasticsearch.gradle.testclusters.TestClustersPlugin import org.elasticsearch.gradle.tool.ClasspathUtils import org.gradle.api.DefaultTask +import org.gradle.api.JavaVersion import org.gradle.api.Task import org.gradle.api.execution.TaskExecutionAdapter import org.gradle.api.logging.Logger diff --git a/distribution/src/config/jvm.options b/distribution/src/config/jvm.options index 58fe4721723a6..c02f1ffa31e99 100644 --- a/distribution/src/config/jvm.options +++ b/distribution/src/config/jvm.options @@ -114,6 +114,9 @@ ${error.file} # JDK 9+ GC logging 9-:-Xlog:gc*,gc+age=trace,safepoint:file=${loggc}:utctime,pid,tags:filecount=32,filesize=64m + +# CalendarDataProvider is being customized to ISO standard, SPI has to be first provider. +8:-Djava.locale.providers=SPI,JRE # due to internationalization enhancements in JDK 9 Elasticsearch need to set the provider to COMPAT otherwise # time/date parsing will break in an incompatible way for some date patterns and locals -9-:-Djava.locale.providers=COMPAT +9-:-Djava.locale.providers=SPI,COMPAT diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/310_date_agg_per_day_of_week.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/310_date_agg_per_day_of_week.yml new file mode 100644 index 0000000000000..d71402d0c9017 --- /dev/null +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/310_date_agg_per_day_of_week.yml @@ -0,0 +1,47 @@ +--- +setup: + - skip: + version: " - 7.3.99" + reason: "only backported to 7.4 (7x)" + + - do: + indices.create: + index: test + body: + mappings: + properties: + date: + type: date + + - do: + index: + index: test + id: 1 + body: { "date": "2009-11-15T14:12:12" } + + - do: + indices.refresh: + index: [test] + +--- +# The inserted document has a field date=2009-11-15T14:12:12 which is Sunday. +# When aggregating per day of the week this should be considered as last day of the week (7) +# and this value should be used in 'key_as_string' +"Date aggregartion per day of week": + - do: + search: + rest_total_hits_as_int: true + index: test + body: + aggregations: + test: + "date_histogram": { + "field": "date", + "calendar_interval": "day", + "format": "e", + "offset": 0 + } + + - match: {hits.total: 1} + - length: { aggregations.test.buckets: 1 } + - match: { aggregations.test.buckets.0.key_as_string: "7" } diff --git a/server/src/main/java/org/elasticsearch/common/time/IsoCalendarDataProvider.java b/server/src/main/java/org/elasticsearch/common/time/IsoCalendarDataProvider.java new file mode 100644 index 0000000000000..36a93049adeb8 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/common/time/IsoCalendarDataProvider.java @@ -0,0 +1,41 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.elasticsearch.common.time; + +import java.util.Calendar; +import java.util.Locale; +import java.util.spi.CalendarDataProvider; + +public class IsoCalendarDataProvider extends CalendarDataProvider { + + @Override + public int getFirstDayOfWeek(Locale locale) { + return Calendar.MONDAY; + } + + @Override + public int getMinimalDaysInFirstWeek(Locale locale) { + return 4; + } + + @Override + public Locale[] getAvailableLocales() { + return new Locale[]{Locale.ROOT}; + } +} diff --git a/server/src/main/resources/META-INF/services/java.util.spi.CalendarDataProvider b/server/src/main/resources/META-INF/services/java.util.spi.CalendarDataProvider new file mode 100644 index 0000000000000..6e006ccf815f8 --- /dev/null +++ b/server/src/main/resources/META-INF/services/java.util.spi.CalendarDataProvider @@ -0,0 +1 @@ +org.elasticsearch.common.time.IsoCalendarDataProvider \ No newline at end of file diff --git a/server/src/test/java/org/elasticsearch/common/joda/JavaJodaTimeDuellingTests.java b/server/src/test/java/org/elasticsearch/common/joda/JavaJodaTimeDuellingTests.java index 9e2a6de5b641d..e8db28f517623 100644 --- a/server/src/test/java/org/elasticsearch/common/joda/JavaJodaTimeDuellingTests.java +++ b/server/src/test/java/org/elasticsearch/common/joda/JavaJodaTimeDuellingTests.java @@ -28,6 +28,7 @@ import org.joda.time.format.ISODateTimeFormat; import org.joda.time.format.DateTimeFormat; +import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -39,6 +40,28 @@ import static org.hamcrest.Matchers.is; public class JavaJodaTimeDuellingTests extends ESTestCase { + @Override + protected boolean enableWarningsCheck() { + return false; + } + + public void testDayOfWeek() { + //7 (ok joda) vs 1 (java by default) but 7 with customized org.elasticsearch.common.time.IsoLocale.ISO8601 + ZonedDateTime now = LocalDateTime.of(2009,11,15,1,32,8,328402) + .atZone(ZoneOffset.UTC); //Sunday + DateFormatter jodaFormatter = Joda.forPattern("e").withLocale(Locale.ROOT).withZone(ZoneOffset.UTC); + DateFormatter javaFormatter = DateFormatter.forPattern("8e").withZone(ZoneOffset.UTC); + assertThat(jodaFormatter.format(now), equalTo(javaFormatter.format(now))); + } + + public void testStartOfWeek() { + //2019-21 (ok joda) vs 2019-22 (java by default) but 2019-21 with customized org.elasticsearch.common.time.IsoLocale.ISO8601 + ZonedDateTime now = LocalDateTime.of(2019,5,26,1,32,8,328402) + .atZone(ZoneOffset.UTC); + DateFormatter jodaFormatter = Joda.forPattern("xxxx-ww").withLocale(Locale.ROOT).withZone(ZoneOffset.UTC); + DateFormatter javaFormatter = DateFormatter.forPattern("8YYYY-ww").withZone(ZoneOffset.UTC); + assertThat(jodaFormatter.format(now), equalTo(javaFormatter.format(now))); + } //these parsers should allow both ',' and '.' as a decimal point public void testDecimalPointParsing(){