Skip to content

Commit d14ed34

Browse files
committed
Explicitly test rewrite of date histogram's time zones on date_nanos (#54402)
This commit adds an explicit test of time zone rewrite on date nanos field. Today this is working but we need tests to ensure that we don't break it unintentionally.
1 parent da976d2 commit d14ed34

File tree

1 file changed

+85
-72
lines changed

1 file changed

+85
-72
lines changed

server/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/DateHistogramTests.java

Lines changed: 85 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.lucene.store.Directory;
3030
import org.elasticsearch.common.time.DateFormatter;
3131
import org.elasticsearch.common.time.DateFormatters;
32+
import org.elasticsearch.common.time.DateUtils;
3233
import org.elasticsearch.index.query.QueryShardContext;
3334
import org.elasticsearch.search.aggregations.BaseAggregationTestCase;
3435
import org.elasticsearch.search.aggregations.BucketOrder;
@@ -130,85 +131,97 @@ private List<BucketOrder> randomOrder() {
130131

131132
private static Document documentForDate(String field, long millis) {
132133
Document doc = new Document();
133-
doc.add(new LongPoint(field, millis));
134-
doc.add(new SortedNumericDocValuesField(field, millis));
134+
final long value;
135+
switch (field) {
136+
case DATE_FIELD_NAME:
137+
value = millis;
138+
break;
139+
140+
case DATE_NANOS_FIELD_NAME:
141+
value = DateUtils.toNanoSeconds(millis);
142+
break;
143+
default:
144+
throw new AssertionError();
145+
}
146+
doc.add(new LongPoint(field, value));
147+
doc.add(new SortedNumericDocValuesField(field, value));
135148
return doc;
136149
}
137150

138151
public void testRewriteTimeZone() throws IOException {
139152
DateFormatter format = DateFormatter.forPattern("strict_date_optional_time");
140-
141-
try (Directory dir = newDirectory();
142-
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig())) {
143-
144-
long millis1 = DateFormatters.from(format.parse("2018-03-11T11:55:00")).toInstant().toEpochMilli();
145-
w.addDocument(documentForDate(DATE_FIELD_NAME, millis1));
146-
long millis2 = DateFormatters.from(format.parse("2017-10-30T18:13:00")).toInstant().toEpochMilli();
147-
w.addDocument(documentForDate(DATE_FIELD_NAME, millis2));
148-
149-
try (IndexReader readerThatDoesntCross = DirectoryReader.open(w)) {
150-
151-
long millis3 = DateFormatters.from(format.parse("2018-03-25T02:44:00")).toInstant().toEpochMilli();
152-
w.addDocument(documentForDate(DATE_FIELD_NAME, millis3));
153-
154-
try (IndexReader readerThatCrosses = DirectoryReader.open(w)) {
155-
156-
QueryShardContext shardContextThatDoesntCross = createShardContext(new IndexSearcher(readerThatDoesntCross));
157-
QueryShardContext shardContextThatCrosses = createShardContext(new IndexSearcher(readerThatCrosses));
158-
159-
DateHistogramAggregationBuilder builder = new DateHistogramAggregationBuilder("my_date_histo");
160-
builder.field(DATE_FIELD_NAME);
161-
builder.calendarInterval(DateHistogramInterval.DAY);
162-
163-
// no timeZone => no rewrite
164-
assertNull(builder.rewriteTimeZone(shardContextThatDoesntCross));
165-
assertNull(builder.rewriteTimeZone(shardContextThatCrosses));
166-
167-
// fixed timeZone => no rewrite
168-
ZoneId tz = ZoneOffset.ofHours(1);
169-
builder.timeZone(tz);
170-
assertSame(tz, builder.rewriteTimeZone(shardContextThatDoesntCross));
171-
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
172-
173-
// timeZone without DST => always rewrite
174-
tz = ZoneId.of("Australia/Brisbane");
175-
builder.timeZone(tz);
176-
assertSame(ZoneOffset.ofHours(10), builder.rewriteTimeZone(shardContextThatDoesntCross));
177-
assertSame(ZoneOffset.ofHours(10), builder.rewriteTimeZone(shardContextThatCrosses));
178-
179-
// another timeZone without DST => always rewrite
180-
tz = ZoneId.of("Asia/Katmandu");
181-
builder.timeZone(tz);
182-
assertSame(ZoneOffset.ofHoursMinutes(5, 45), builder.rewriteTimeZone(shardContextThatDoesntCross));
183-
assertSame(ZoneOffset.ofHoursMinutes(5, 45), builder.rewriteTimeZone(shardContextThatCrosses));
184-
185-
// daylight-saving-times => rewrite if doesn't cross
186-
tz = ZoneId.of("Europe/Paris");
187-
builder.timeZone(tz);
188-
assertEquals(ZoneOffset.ofHours(1), builder.rewriteTimeZone(shardContextThatDoesntCross));
189-
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
190-
191-
// Rounded values are no longer all within the same transitions => no rewrite
192-
builder.calendarInterval(DateHistogramInterval.MONTH);
193-
assertSame(tz, builder.rewriteTimeZone(shardContextThatDoesntCross));
194-
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
195-
196-
builder = new DateHistogramAggregationBuilder("my_date_histo");
197-
builder.field(DATE_FIELD_NAME);
198-
builder.timeZone(tz);
199-
200-
builder.fixedInterval(new DateHistogramInterval(1000L * 60 * 60 * 24 + "ms")); // ~ 1 day
201-
assertEquals(ZoneOffset.ofHours(1), builder.rewriteTimeZone(shardContextThatDoesntCross));
202-
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
203-
204-
// Because the interval is large, rounded values are not
205-
// within the same transitions as the values => no rewrite
206-
builder.fixedInterval(new DateHistogramInterval(1000L * 60 * 60 * 24 * 30 + "ms")); // ~ 1 month
207-
assertSame(tz, builder.rewriteTimeZone(shardContextThatDoesntCross));
208-
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
153+
for (String fieldName : new String[]{DATE_FIELD_NAME, DATE_NANOS_FIELD_NAME}) {
154+
try (Directory dir = newDirectory();
155+
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig())) {
156+
157+
long millis1 = DateFormatters.from(format.parse("2018-03-11T11:55:00")).toInstant().toEpochMilli();
158+
w.addDocument(documentForDate(fieldName, millis1));
159+
long millis2 = DateFormatters.from(format.parse("2017-10-30T18:13:00")).toInstant().toEpochMilli();
160+
w.addDocument(documentForDate(fieldName, millis2));
161+
162+
try (IndexReader readerThatDoesntCross = DirectoryReader.open(w)) {
163+
164+
long millis3 = DateFormatters.from(format.parse("2018-03-25T02:44:00")).toInstant().toEpochMilli();
165+
w.addDocument(documentForDate(fieldName, millis3));
166+
167+
try (IndexReader readerThatCrosses = DirectoryReader.open(w)) {
168+
169+
QueryShardContext shardContextThatDoesntCross = createShardContext(new IndexSearcher(readerThatDoesntCross));
170+
QueryShardContext shardContextThatCrosses = createShardContext(new IndexSearcher(readerThatCrosses));
171+
172+
DateHistogramAggregationBuilder builder = new DateHistogramAggregationBuilder("my_date_histo");
173+
builder.field(fieldName);
174+
builder.calendarInterval(DateHistogramInterval.DAY);
175+
176+
// no timeZone => no rewrite
177+
assertNull(builder.rewriteTimeZone(shardContextThatDoesntCross));
178+
assertNull(builder.rewriteTimeZone(shardContextThatCrosses));
179+
180+
// fixed timeZone => no rewrite
181+
ZoneId tz = ZoneOffset.ofHours(1);
182+
builder.timeZone(tz);
183+
assertSame(tz, builder.rewriteTimeZone(shardContextThatDoesntCross));
184+
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
185+
186+
// timeZone without DST => always rewrite
187+
tz = ZoneId.of("Australia/Brisbane");
188+
builder.timeZone(tz);
189+
assertSame(ZoneOffset.ofHours(10), builder.rewriteTimeZone(shardContextThatDoesntCross));
190+
assertSame(ZoneOffset.ofHours(10), builder.rewriteTimeZone(shardContextThatCrosses));
191+
192+
// another timeZone without DST => always rewrite
193+
tz = ZoneId.of("Asia/Katmandu");
194+
builder.timeZone(tz);
195+
assertSame(ZoneOffset.ofHoursMinutes(5, 45), builder.rewriteTimeZone(shardContextThatDoesntCross));
196+
assertSame(ZoneOffset.ofHoursMinutes(5, 45), builder.rewriteTimeZone(shardContextThatCrosses));
197+
198+
// daylight-saving-times => rewrite if doesn't cross
199+
tz = ZoneId.of("Europe/Paris");
200+
builder.timeZone(tz);
201+
assertEquals(ZoneOffset.ofHours(1), builder.rewriteTimeZone(shardContextThatDoesntCross));
202+
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
203+
204+
// Rounded values are no longer all within the same transitions => no rewrite
205+
builder.calendarInterval(DateHistogramInterval.MONTH);
206+
assertSame(tz, builder.rewriteTimeZone(shardContextThatDoesntCross));
207+
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
208+
209+
builder = new DateHistogramAggregationBuilder("my_date_histo");
210+
builder.field(fieldName);
211+
builder.timeZone(tz);
212+
213+
builder.fixedInterval(new DateHistogramInterval(1000L * 60 * 60 * 24 + "ms")); // ~ 1 day
214+
assertEquals(ZoneOffset.ofHours(1), builder.rewriteTimeZone(shardContextThatDoesntCross));
215+
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
216+
217+
// Because the interval is large, rounded values are not
218+
// within the same transitions as the values => no rewrite
219+
builder.fixedInterval(new DateHistogramInterval(1000L * 60 * 60 * 24 * 30 + "ms")); // ~ 1 month
220+
assertSame(tz, builder.rewriteTimeZone(shardContextThatDoesntCross));
221+
assertSame(tz, builder.rewriteTimeZone(shardContextThatCrosses));
222+
}
209223
}
210224
}
211225
}
212226
}
213-
214227
}

0 commit comments

Comments
 (0)