|
29 | 29 | import org.apache.lucene.store.Directory; |
30 | 30 | import org.elasticsearch.common.time.DateFormatter; |
31 | 31 | import org.elasticsearch.common.time.DateFormatters; |
| 32 | +import org.elasticsearch.common.time.DateUtils; |
32 | 33 | import org.elasticsearch.index.query.QueryShardContext; |
33 | 34 | import org.elasticsearch.search.aggregations.BaseAggregationTestCase; |
34 | 35 | import org.elasticsearch.search.aggregations.BucketOrder; |
@@ -130,85 +131,97 @@ private List<BucketOrder> randomOrder() { |
130 | 131 |
|
131 | 132 | private static Document documentForDate(String field, long millis) { |
132 | 133 | 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)); |
135 | 148 | return doc; |
136 | 149 | } |
137 | 150 |
|
138 | 151 | public void testRewriteTimeZone() throws IOException { |
139 | 152 | 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 | + } |
209 | 223 | } |
210 | 224 | } |
211 | 225 | } |
212 | 226 | } |
213 | | - |
214 | 227 | } |
0 commit comments