From 5b2854e8bb8ecbd240429a751bf3b95b86146c17 Mon Sep 17 00:00:00 2001 From: Shay Banon Date: Mon, 9 Jan 2012 21:28:56 +0200 Subject: [PATCH] Date Histogram Facet: Add `pre_offset` and `post_offset` options, closes #1599. --- .../common/joda/TimeZoneRounding.java | 39 ++++++++++++++++++- .../DateHistogramFacetProcessor.java | 19 ++++++++- .../unit/deps/joda/TimeZoneRoundingTests.java | 6 +++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/joda/TimeZoneRounding.java b/src/main/java/org/elasticsearch/common/joda/TimeZoneRounding.java index ac4cbe3d2f0..feb9d8fdf21 100644 --- a/src/main/java/org/elasticsearch/common/joda/TimeZoneRounding.java +++ b/src/main/java/org/elasticsearch/common/joda/TimeZoneRounding.java @@ -48,6 +48,9 @@ public abstract class TimeZoneRounding { private float factor = 1.0f; + private long preOffset; + private long postOffset; + public Builder(DateTimeField field) { this.field = field; this.interval = -1; @@ -68,6 +71,16 @@ public abstract class TimeZoneRounding { return this; } + public Builder preOffset(long preOffset) { + this.preOffset = preOffset; + return this; + } + + public Builder postOffset(long postOffset) { + this.postOffset = postOffset; + return this; + } + public Builder factor(float factor) { this.factor = factor; return this; @@ -77,7 +90,7 @@ public abstract class TimeZoneRounding { TimeZoneRounding timeZoneRounding; if (field != null) { if (preTz.equals(DateTimeZone.UTC) && postTz.equals(DateTimeZone.UTC)) { - return new UTCTimeZoneRoundingFloor(field); + timeZoneRounding = new UTCTimeZoneRoundingFloor(field); } else if (field.getDurationField().getUnitMillis() < DateTimeConstants.MILLIS_PER_HOUR * 12) { timeZoneRounding = new TimeTimeZoneRoundingFloor(field, preTz, postTz); } else { @@ -85,13 +98,16 @@ public abstract class TimeZoneRounding { } } else { if (preTz.equals(DateTimeZone.UTC) && postTz.equals(DateTimeZone.UTC)) { - return new UTCIntervalTimeZoneRounding(interval); + timeZoneRounding = new UTCIntervalTimeZoneRounding(interval); } else if (interval < DateTimeConstants.MILLIS_PER_HOUR * 12) { timeZoneRounding = new TimeIntervalTimeZoneRounding(interval, preTz, postTz); } else { timeZoneRounding = new DayIntervalTimeZoneRounding(interval, preTz, postTz); } } + if (preOffset != 0 || postOffset != 0) { + timeZoneRounding = new PrePostTimeZoneRounding(timeZoneRounding, preOffset, postOffset); + } if (factor != 1.0f) { timeZoneRounding = new FactorTimeZoneRounding(timeZoneRounding, factor); } @@ -237,4 +253,23 @@ public abstract class TimeZoneRounding { return timeZoneRounding.calc((long) (factor * utcMillis)); } } + + static class PrePostTimeZoneRounding extends TimeZoneRounding { + + private final TimeZoneRounding timeZoneRounding; + + private final long preOffset; + private final long postOffset; + + PrePostTimeZoneRounding(TimeZoneRounding timeZoneRounding, long preOffset, long postOffset) { + this.timeZoneRounding = timeZoneRounding; + this.preOffset = preOffset; + this.postOffset = postOffset; + } + + @Override + public long calc(long utcMillis) { + return postOffset + timeZoneRounding.calc(utcMillis + preOffset); + } + } } diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacetProcessor.java index 54199862da0..d656debc744 100644 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacetProcessor.java @@ -88,6 +88,8 @@ public class DateHistogramFacetProcessor extends AbstractComponent implements Fa String interval = null; DateTimeZone preZone = DateTimeZone.UTC; DateTimeZone postZone = DateTimeZone.UTC; + long preOffset = 0; + long postOffset = 0; float factor = 1.0f; Chronology chronology = ISOChronology.getInstanceUTC(); DateHistogramFacet.ComparatorType comparatorType = DateHistogramFacet.ComparatorType.TIME; @@ -115,6 +117,10 @@ public class DateHistogramFacetProcessor extends AbstractComponent implements Fa preZone = parseZone(parser, token); } else if ("post_zone".equals(fieldName) || "postZone".equals(fieldName)) { postZone = parseZone(parser, token); + } else if ("pre_offset".equals(fieldName) || "preOffset".equals(fieldName)) { + preOffset = parseOffset(parser.text()); + } else if ("post_offset".equals(fieldName) || "postOffset".equals(fieldName)) { + postOffset = parseOffset(parser.text()); } else if ("factor".equals(fieldName)) { factor = parser.floatValue(); } else if ("value_script".equals(fieldName) || "valueScript".equals(fieldName)) { @@ -152,7 +158,11 @@ public class DateHistogramFacetProcessor extends AbstractComponent implements Fa tzRoundingBuilder = TimeZoneRounding.builder(TimeValue.parseTimeValue(interval, null)); } - TimeZoneRounding tzRounding = tzRoundingBuilder.preZone(preZone).postZone(postZone).factor(factor).build(); + TimeZoneRounding tzRounding = tzRoundingBuilder + .preZone(preZone).postZone(postZone) + .preOffset(preOffset).postOffset(postOffset) + .factor(factor) + .build(); if (valueScript != null) { return new ValueScriptDateHistogramFacetCollector(facetName, keyField, scriptLang, valueScript, params, tzRounding, comparatorType, context); @@ -163,6 +173,13 @@ public class DateHistogramFacetProcessor extends AbstractComponent implements Fa } } + private long parseOffset(String offset) throws IOException { + if (offset.charAt(0) == '-') { + return -TimeValue.parseTimeValue(offset.substring(1), null).millis(); + } + return TimeValue.parseTimeValue(offset, null).millis(); + } + private DateTimeZone parseZone(XContentParser parser, XContentParser.Token token) throws IOException { if (token == XContentParser.Token.VALUE_NUMBER) { return DateTimeZone.forOffsetHours(parser.intValue()); diff --git a/src/test/java/org/elasticsearch/test/unit/deps/joda/TimeZoneRoundingTests.java b/src/test/java/org/elasticsearch/test/unit/deps/joda/TimeZoneRoundingTests.java index 9d59516f1b5..524c488b9da 100644 --- a/src/test/java/org/elasticsearch/test/unit/deps/joda/TimeZoneRoundingTests.java +++ b/src/test/java/org/elasticsearch/test/unit/deps/joda/TimeZoneRoundingTests.java @@ -39,6 +39,12 @@ public class TimeZoneRoundingTests { public void testUTCMonthRounding() { TimeZoneRounding tzRounding = TimeZoneRounding.builder(chronology().monthOfYear()).build(); assertThat(tzRounding.calc(utc("2009-02-03T01:01:01")), equalTo(utc("2009-02-01T00:00:00.000Z"))); + + tzRounding = TimeZoneRounding.builder(chronology().weekOfWeekyear()).build(); + assertThat(tzRounding.calc(utc("2012-01-10T01:01:01")), equalTo(utc("2012-01-09T00:00:00.000Z"))); + + tzRounding = TimeZoneRounding.builder(chronology().weekOfWeekyear()).postOffset(-TimeValue.timeValueHours(24).millis()).build(); + assertThat(tzRounding.calc(utc("2012-01-10T01:01:01")), equalTo(utc("2012-01-08T00:00:00.000Z"))); } @Test