Simplify mock scripts

This commit is contained in:
Christoph Büscher 2016-03-04 19:34:56 +01:00
parent 6b0f63e1a6
commit ff46303f15
6 changed files with 198 additions and 333 deletions

View File

@ -28,6 +28,7 @@ import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.search.aggregations.bucket.DateScriptMocks.DateScriptsMockPlugin;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.ExtendedBounds;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
@ -44,7 +45,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@ -128,8 +131,7 @@ public class DateHistogramIT extends ESIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(
ScriptMocks.ExtractFieldScriptPlugin.class,
ScriptMocks.FieldValueScriptPlugin.class);
DateScriptsMockPlugin.class);
}
@After
@ -452,10 +454,12 @@ public class DateHistogramIT extends ESIntegTestCase {
}
public void testSingleValuedFieldWithValueScript() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "date");
SearchResponse response = client().prepareSearch("idx")
.addAggregation(dateHistogram("histo")
.field("date")
.script(new Script("", ScriptType.INLINE, ScriptMocks.FieldValueScriptEngine.NAME, null))
.script(new Script(DateScriptMocks.PlusOneMonthScript.NAME, ScriptType.INLINE, "native", params))
.dateHistogramInterval(DateHistogramInterval.MONTH)).execute().actionGet();
assertSearchResponse(response);
@ -586,10 +590,12 @@ public class DateHistogramIT extends ESIntegTestCase {
* doc 6: [ Apr 23, May 24]
*/
public void testMultiValuedFieldWithValueScript() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "dates");
SearchResponse response = client().prepareSearch("idx")
.addAggregation(dateHistogram("histo")
.field("dates")
.script(new Script("", ScriptType.INLINE, ScriptMocks.FieldValueScriptEngine.NAME, null))
.script(new Script(DateScriptMocks.PlusOneMonthScript.NAME, ScriptType.INLINE, "native", params))
.dateHistogramInterval(DateHistogramInterval.MONTH)).execute().actionGet();
assertSearchResponse(response);
@ -638,8 +644,11 @@ public class DateHistogramIT extends ESIntegTestCase {
* Mar 23
*/
public void testScriptSingleValue() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "date");
SearchResponse response = client().prepareSearch("idx")
.addAggregation(dateHistogram("histo").script(new Script("date", ScriptType.INLINE, ScriptMocks.ExtractFieldScriptEngine.NAME, null)).dateHistogramInterval(DateHistogramInterval.MONTH))
.addAggregation(dateHistogram("histo").script(new Script(DateScriptMocks.ExtractFieldScript.NAME,
ScriptType.INLINE, "native", params)).dateHistogramInterval(DateHistogramInterval.MONTH))
.execute().actionGet();
assertSearchResponse(response);
@ -673,8 +682,11 @@ public class DateHistogramIT extends ESIntegTestCase {
}
public void testScriptMultiValued() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "dates");
SearchResponse response = client().prepareSearch("idx")
.addAggregation(dateHistogram("histo").script(new Script("dates", ScriptType.INLINE, ScriptMocks.ExtractFieldScriptEngine.NAME, null)).dateHistogramInterval(DateHistogramInterval.MONTH))
.addAggregation(dateHistogram("histo").script(new Script(DateScriptMocks.ExtractFieldScript.NAME,
ScriptType.INLINE, "native", params)).dateHistogramInterval(DateHistogramInterval.MONTH))
.execute().actionGet();
assertSearchResponse(response);

View File

@ -23,6 +23,7 @@ import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.search.aggregations.bucket.DateScriptMocks.DateScriptsMockPlugin;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.range.Range;
import org.elasticsearch.search.aggregations.bucket.range.Range.Bucket;
@ -36,7 +37,9 @@ import org.joda.time.DateTimeZone;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
@ -66,7 +69,11 @@ public class DateRangeIT extends ESIntegTestCase {
}
private static DateTime date(int month, int day) {
return new DateTime(2012, month, day, 0, 0, DateTimeZone.UTC);
return date(month, day, DateTimeZone.UTC);
}
private static DateTime date(int month, int day, DateTimeZone timezone) {
return new DateTime(2012, month, day, 0, 0, timezone);
}
private static int numDocs;
@ -104,16 +111,17 @@ public class DateRangeIT extends ESIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(
ScriptMocks.ExtractFieldScriptPlugin.class,
ScriptMocks.FieldValueScriptPlugin.class);
DateScriptsMockPlugin.class);
}
public void testDateMath() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "date");
DateRangeAggregatorBuilder rangeBuilder = dateRange("range");
if (randomBoolean()) {
rangeBuilder.field("date");
} else {
rangeBuilder.script(new Script("date", ScriptType.INLINE, ScriptMocks.ExtractFieldScriptEngine.NAME, null));
rangeBuilder.script(new Script(DateScriptMocks.ExtractFieldScript.NAME, ScriptType.INLINE, "native", params));
}
SearchResponse response = client()
.prepareSearch("idx")
@ -287,9 +295,12 @@ public class DateRangeIT extends ESIntegTestCase {
}
public void testSingleValueFieldWithDateMath() throws Exception {
int timeZoneOffset = randomIntBetween(-12, 12);
DateTimeZone timezone = DateTimeZone.forOffsetHours(timeZoneOffset);
String timeZoneSuffix = (timeZoneOffset == 0) ? "Z" : DateTime.now(timezone).toString("ZZ");
String[] ids = DateTimeZone.getAvailableIDs().toArray(new String[DateTimeZone.getAvailableIDs().size()]);
DateTimeZone timezone = DateTimeZone.forID(randomFrom(ids));
int timeZoneOffset = timezone.getOffset(date(2, 15));
// if time zone is UTC (or equivalent), time zone suffix is "Z", else something like "+03:00", which we get with the "ZZ" format
String feb15Suffix = timeZoneOffset == 0 ? "Z" : date(2,15, timezone).toString("ZZ");
String mar15Suffix = timeZoneOffset == 0 ? "Z" : date(3,15, timezone).toString("ZZ");
long expectedFirstBucketCount = timeZoneOffset < 0 ? 3L : 2L;
SearchResponse response = client().prepareSearch("idx")
@ -311,29 +322,29 @@ public class DateRangeIT extends ESIntegTestCase {
Range.Bucket bucket = buckets.get(0);
assertThat(bucket, notNullValue());
assertThat((String) bucket.getKey(), equalTo("*-2012-02-15T00:00:00.000" + timeZoneSuffix));
assertThat((String) bucket.getKey(), equalTo("*-2012-02-15T00:00:00.000" + feb15Suffix));
assertThat(((DateTime) bucket.getFrom()), nullValue());
assertThat(((DateTime) bucket.getTo()), equalTo(date(2, 15).minusHours(timeZoneOffset)));
assertThat(((DateTime) bucket.getTo()), equalTo(date(2, 15, timezone).toDateTime(DateTimeZone.UTC)));
assertThat(bucket.getFromAsString(), nullValue());
assertThat(bucket.getToAsString(), equalTo("2012-02-15T00:00:00.000" + timeZoneSuffix));
assertThat(bucket.getToAsString(), equalTo("2012-02-15T00:00:00.000" + feb15Suffix));
assertThat(bucket.getDocCount(), equalTo(expectedFirstBucketCount));
bucket = buckets.get(1);
assertThat(bucket, notNullValue());
assertThat((String) bucket.getKey(), equalTo("2012-02-15T00:00:00.000" + timeZoneSuffix +
"-2012-03-15T00:00:00.000" + timeZoneSuffix));
assertThat(((DateTime) bucket.getFrom()), equalTo(date(2, 15).minusHours(timeZoneOffset)));
assertThat(((DateTime) bucket.getTo()), equalTo(date(3, 15).minusHours(timeZoneOffset)));
assertThat(bucket.getFromAsString(), equalTo("2012-02-15T00:00:00.000" + timeZoneSuffix));
assertThat(bucket.getToAsString(), equalTo("2012-03-15T00:00:00.000" + timeZoneSuffix));
assertThat((String) bucket.getKey(), equalTo("2012-02-15T00:00:00.000" + feb15Suffix +
"-2012-03-15T00:00:00.000" + mar15Suffix));
assertThat(((DateTime) bucket.getFrom()), equalTo(date(2, 15, timezone).toDateTime(DateTimeZone.UTC)));
assertThat(((DateTime) bucket.getTo()), equalTo(date(3, 15, timezone).toDateTime(DateTimeZone.UTC)));
assertThat(bucket.getFromAsString(), equalTo("2012-02-15T00:00:00.000" + feb15Suffix));
assertThat(bucket.getToAsString(), equalTo("2012-03-15T00:00:00.000" + mar15Suffix));
assertThat(bucket.getDocCount(), equalTo(2L));
bucket = buckets.get(2);
assertThat(bucket, notNullValue());
assertThat((String) bucket.getKey(), equalTo("2012-03-15T00:00:00.000" + timeZoneSuffix + "-*"));
assertThat(((DateTime) bucket.getFrom()), equalTo(date(3, 15).minusHours(timeZoneOffset)));
assertThat((String) bucket.getKey(), equalTo("2012-03-15T00:00:00.000" + mar15Suffix + "-*"));
assertThat(((DateTime) bucket.getFrom()), equalTo(date(3, 15, timezone).toDateTime(DateTimeZone.UTC)));
assertThat(((DateTime) bucket.getTo()), nullValue());
assertThat(bucket.getFromAsString(), equalTo("2012-03-15T00:00:00.000" + timeZoneSuffix));
assertThat(bucket.getFromAsString(), equalTo("2012-03-15T00:00:00.000" + mar15Suffix));
assertThat(bucket.getToAsString(), nullValue());
assertThat(bucket.getDocCount(), equalTo(numDocs - 2L - expectedFirstBucketCount));
}
@ -527,10 +538,12 @@ public class DateRangeIT extends ESIntegTestCase {
public void testMultiValuedFieldWithValueScript() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "dates");
SearchResponse response = client().prepareSearch("idx")
.addAggregation(dateRange("range")
.field("dates")
.script(new Script("", ScriptType.INLINE, ScriptMocks.FieldValueScriptEngine.NAME, null))
.script(new Script(DateScriptMocks.PlusOneMonthScript.NAME, ScriptType.INLINE, "native", params))
.addUnboundedTo(date(2, 15)).addRange(date(2, 15), date(3, 15)).addUnboundedFrom(date(3, 15))).execute()
.actionGet();
@ -582,9 +595,11 @@ public class DateRangeIT extends ESIntegTestCase {
*/
public void testScriptSingleValue() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "date");
SearchResponse response = client().prepareSearch("idx")
.addAggregation(dateRange("range")
.script(new Script("date", ScriptType.INLINE, ScriptMocks.ExtractFieldScriptEngine.NAME, null))
.script(new Script(DateScriptMocks.ExtractFieldScript.NAME, ScriptType.INLINE, "native", params))
.addUnboundedTo(date(2, 15))
.addRange(date(2, 15), date(3, 15))
.addUnboundedFrom(date(3, 15)))
@ -641,10 +656,12 @@ public class DateRangeIT extends ESIntegTestCase {
*/
public void testScriptMultiValued() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("fieldname", "dates");
SearchResponse response = client()
.prepareSearch("idx")
.addAggregation(
dateRange("range").script(new Script("dates", ScriptType.INLINE, ScriptMocks.ExtractFieldScriptEngine.NAME, null))
dateRange("range").script(new Script(DateScriptMocks.ExtractFieldScript.NAME, ScriptType.INLINE, "native", params))
.addUnboundedTo(date(2, 15)).addRange(date(2, 15), date(3, 15))
.addUnboundedFrom(date(3, 15))).execute().actionGet();

View File

@ -26,6 +26,8 @@ import org.joda.time.DateTimeZone;
public class DateRangeTests extends BaseAggregationTestCase<DateRangeAggregatorBuilder> {
private final static String[] timeZoneIds = DateTimeZone.getAvailableIDs().toArray(new String[DateTimeZone.getAvailableIDs().size()]);
@Override
protected DateRangeAggregatorBuilder createTestAggregatorBuilder() {
int numRanges = randomIntBetween(1, 10);
@ -58,7 +60,7 @@ public class DateRangeTests extends BaseAggregationTestCase<DateRangeAggregatorB
factory.missing(randomIntBetween(0, 10));
}
if (randomBoolean()) {
factory.timeZone(DateTimeZone.forOffsetHours(randomIntBetween(-23, 23)));
factory.timeZone(DateTimeZone.forID(randomFrom(timeZoneIds)));
}
return factory;
}

View File

@ -0,0 +1,133 @@
/*
* 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.search.aggregations.bucket;
import org.elasticsearch.common.inject.internal.Nullable;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.AbstractSearchScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.NativeScriptFactory;
import org.elasticsearch.script.ScriptModule;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import java.util.HashMap;
import java.util.Map;
/**
* Mock scripts shared by DateRangeIT and DateHistogramIT
*/
public class DateScriptMocks {
/**
* Mock plugin for the {@link DateScriptMocks.ExtractFieldScript} and {@link DateScriptMocks.PlusOneMonthScript}
*/
public static class DateScriptsMockPlugin extends Plugin {
@Override
public String name() {
return "DateScriptMocks";
}
@Override
public String description() {
return "A mock script plugin.";
}
public void onModule(ScriptModule module) {
module.registerScript(ExtractFieldScript.NAME, ExtractFieldScriptFactory.class);
module.registerScript(PlusOneMonthScript.NAME, PlusOneMonthScriptFactory.class);
}
}
public static class ExtractFieldScriptFactory implements NativeScriptFactory {
@Override
public ExecutableScript newScript(@Nullable Map<String, Object> params) {
return new ExtractFieldScript((String) params.get("fieldname"));
}
@Override
public boolean needsScores() {
return false;
}
}
public static class ExtractFieldScript extends AbstractSearchScript {
public static final String NAME = "extract_field";
private String fieldname;
public ExtractFieldScript(String fieldname) {
this.fieldname = fieldname;
}
@Override
public Object run() {
return doc().get(fieldname);
}
}
public static class PlusOneMonthScriptFactory implements NativeScriptFactory {
@Override
public ExecutableScript newScript(Map<String, Object> params) {
return new PlusOneMonthScript((String) params.get("fieldname"));
}
@Override
public boolean needsScores() {
return false;
}
}
/**
* This mock script takes date field value and adds one month to the returned date
*/
public static class PlusOneMonthScript extends AbstractSearchScript {
public static final String NAME = "date_plus_1_month";
private String fieldname;
private Map<String, Object> vars = new HashMap<>();
public PlusOneMonthScript(String fieldname) {
this.fieldname = fieldname;
}
@Override
public void setNextVar(String name, Object value) {
vars.put(name, value);
}
@Override
public long runAsLong() {
return new DateTime((long) vars.get("_value"), DateTimeZone.UTC).plusMonths(1).getMillis();
}
@Override
public double runAsDouble() {
return new DateTime(new Double((double) vars.get("_value")).longValue(), DateTimeZone.UTC).plusMonths(1).getMillis();
}
@Override
public Object run() {
return new UnsupportedOperationException();
}
}
}

View File

@ -1,303 +0,0 @@
/*
* 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.search.aggregations.bucket;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.Scorer;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.LeafSearchScript;
import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.SearchScript;
import org.elasticsearch.search.lookup.LeafSearchLookup;
import org.elasticsearch.search.lookup.SearchLookup;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Helper mocks for script plugins and engines
*/
public class ScriptMocks {
/**
* Mock plugin for the {@link ScriptMocks.ExtractFieldScriptEngine}
*/
public static class ExtractFieldScriptPlugin extends Plugin {
@Override
public String name() {
return ScriptMocks.ExtractFieldScriptEngine.NAME;
}
@Override
public String description() {
return "Mock script engine for " + DateHistogramIT.class;
}
public void onModule(ScriptModule module) {
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ScriptMocks.ExtractFieldScriptEngine.class,
ScriptMocks.ExtractFieldScriptEngine.TYPES));
}
}
/**
* This mock script returns the field that is specified by name in the script body
*/
public static class ExtractFieldScriptEngine implements ScriptEngineService {
public static final String NAME = "extract_field";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public List<String> getTypes() {
return TYPES;
}
@Override
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean isSandboxed() {
return true;
}
@Override
public Object compile(String script, Map<String, String> params) {
return script;
}
@Override
public ExecutableScript executable(CompiledScript compiledScript, Map<String, Object> params) {
throw new UnsupportedOperationException();
}
@Override
public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, Map<String, Object> vars) {
return new SearchScript() {
@Override
public LeafSearchScript getLeafSearchScript(LeafReaderContext context) throws IOException {
final LeafSearchLookup leafLookup = lookup.getLeafSearchLookup(context);
return new LeafSearchScript() {
@Override
public void setNextVar(String name, Object value) {
}
@Override
public Object run() {
String fieldName = (String) compiledScript.compiled();
return leafLookup.doc().get(fieldName);
}
@Override
public void setScorer(Scorer scorer) {
}
@Override
public void setSource(Map<String, Object> source) {
}
@Override
public void setDocument(int doc) {
if (leafLookup != null) {
leafLookup.setDocument(doc);
}
}
@Override
public long runAsLong() {
throw new UnsupportedOperationException();
}
@Override
public float runAsFloat() {
throw new UnsupportedOperationException();
}
@Override
public double runAsDouble() {
throw new UnsupportedOperationException();
}
};
}
@Override
public boolean needsScores() {
return false;
}
};
}
@Override
public void scriptRemoved(CompiledScript script) {
}
}
/**
* Mock plugin for the {@link ScriptMocks.FieldValueScriptEngine}
*/
public static class FieldValueScriptPlugin extends Plugin {
@Override
public String name() {
return ScriptMocks.FieldValueScriptEngine.NAME;
}
@Override
public String description() {
return "Mock script engine for " + DateHistogramIT.class;
}
public void onModule(ScriptModule module) {
module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ScriptMocks.FieldValueScriptEngine.class,
ScriptMocks.FieldValueScriptEngine.TYPES));
}
}
/**
* This mock script returns the field value and adds one month to the returned date
*/
public static class FieldValueScriptEngine implements ScriptEngineService {
public static final String NAME = "field_value";
public static final List<String> TYPES = Collections.singletonList(NAME);
@Override
public void close() throws IOException {
}
@Override
public List<String> getTypes() {
return TYPES;
}
@Override
public List<String> getExtensions() {
return TYPES;
}
@Override
public boolean isSandboxed() {
return true;
}
@Override
public Object compile(String script, Map<String, String> params) {
return script;
}
@Override
public ExecutableScript executable(CompiledScript compiledScript, Map<String, Object> params) {
throw new UnsupportedOperationException();
}
@Override
public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, Map<String, Object> vars) {
return new SearchScript() {
private Map<String, Object> vars = new HashMap<>(2);
@Override
public LeafSearchScript getLeafSearchScript(LeafReaderContext context) throws IOException {
final LeafSearchLookup leafLookup = lookup.getLeafSearchLookup(context);
return new LeafSearchScript() {
@Override
public Object unwrap(Object value) {
throw new UnsupportedOperationException();
}
@Override
public void setNextVar(String name, Object value) {
vars.put(name, value);
}
@Override
public Object run() {
throw new UnsupportedOperationException();
}
@Override
public void setScorer(Scorer scorer) {
}
@Override
public void setSource(Map<String, Object> source) {
}
@Override
public void setDocument(int doc) {
if (leafLookup != null) {
leafLookup.setDocument(doc);
}
}
@Override
public long runAsLong() {
return new DateTime((long) vars.get("_value"), DateTimeZone.UTC).plusMonths(1).getMillis();
}
@Override
public float runAsFloat() {
throw new UnsupportedOperationException();
}
@Override
public double runAsDouble() {
return new DateTime(new Double((double) vars.get("_value")).longValue(),
DateTimeZone.UTC).plusMonths(1).getMillis();
}
};
}
@Override
public boolean needsScores() {
return false;
}
};
}
@Override
public void scriptRemoved(CompiledScript script) {
}
}
}

View File

@ -116,6 +116,10 @@ Any characters in the pattern that are not in the ranges of ['a'..'z'] and ['A'.
==== Time zone in date range aggregations
Dates can be converted from another time zone to UTC by specifying the `time_zone` parameter.
Time zones may either be specified as an ISO 8601 UTC offset (e.g. +01:00 or -08:00) or as one of
the the http://joda-time.sourceforge.net/timezones.html[time zone ids] from the TZ database.
The `time_zone` parameter is also applied to rounding in date math expressions. As an example,
to round to the beginning of the day in the CET time zone, you can do the following:
@ -138,4 +142,4 @@ to round to the beginning of the day in the CET time zone, you can do the follow
}
--------------------------------------------------
<1> This date will be converted to `2016-02-15T00:00:00.000+01:00`.
<2> `now\d` will be rounded to the beginning of the day in the CET time zone.
<2> `now/d` will be rounded to the beginning of the day in the CET time zone.