From 6cfd811666e8efff316170c168da5ea77ceb18b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Sun, 8 Mar 2015 09:47:12 -0700 Subject: [PATCH] Aggregations: Be lenient when converting local to utc time in time zone roundings This solves a problem in the time zone rounding classes where time dates that fall into a DST gap will cause joda time library to throw an exception. Changing the conversion methods 'strict' option to false prevents this. Closes #10025 --- .../common/rounding/TimeZoneRounding.java | 10 +++++----- .../rounding/TimeZoneRoundingTests.java | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/rounding/TimeZoneRounding.java b/src/main/java/org/elasticsearch/common/rounding/TimeZoneRounding.java index 2c25b036c0c0f..af999b244707c 100644 --- a/src/main/java/org/elasticsearch/common/rounding/TimeZoneRounding.java +++ b/src/main/java/org/elasticsearch/common/rounding/TimeZoneRounding.java @@ -157,7 +157,7 @@ public byte id() { @Override public long roundKey(long utcMillis) { long local = preTz.convertUTCToLocal(utcMillis); - return preTz.convertLocalToUTC(field.roundFloor(local), true, utcMillis); + return preTz.convertLocalToUTC(field.roundFloor(local), false, utcMillis); } @Override @@ -168,11 +168,11 @@ public long valueForKey(long time) { @Override public long nextRoundingValue(long time) { - long currentWithoutPostZone = postTz.convertLocalToUTC(time, true); + long currentWithoutPostZone = postTz.convertLocalToUTC(time, false); // we also need to correct for preTz because rounding takes place in local time zone long local = preTz.convertUTCToLocal(currentWithoutPostZone); long nextLocal = durationField.add(local, 1); - return postTz.convertUTCToLocal(preTz.convertLocalToUTC((nextLocal), true)); + return postTz.convertUTCToLocal(preTz.convertLocalToUTC((nextLocal), false)); } @Override @@ -283,7 +283,7 @@ public long valueForKey(long time) { @Override public long nextRoundingValue(long currentWithPostZone) { - long currentWithoutPostZone = postTz.convertLocalToUTC(currentWithPostZone, true); + long currentWithoutPostZone = postTz.convertLocalToUTC(currentWithPostZone, false); long nextWithoutPostZone = durationField.add(currentWithoutPostZone, 1); return postTz.convertUTCToLocal(nextWithoutPostZone); } @@ -386,7 +386,7 @@ public long roundKey(long utcMillis) { public long valueForKey(long key) { long time = Rounding.Interval.roundValue(key, interval); // now, time is still in local, move it to UTC - time = preTz.convertLocalToUTC(time, true); + time = preTz.convertLocalToUTC(time, false); // now apply post Tz time = postTz.convertUTCToLocal(time); return time; diff --git a/src/test/java/org/elasticsearch/common/rounding/TimeZoneRoundingTests.java b/src/test/java/org/elasticsearch/common/rounding/TimeZoneRoundingTests.java index e9bfe27ecbaf8..1accc7970a23d 100644 --- a/src/test/java/org/elasticsearch/common/rounding/TimeZoneRoundingTests.java +++ b/src/test/java/org/elasticsearch/common/rounding/TimeZoneRoundingTests.java @@ -178,6 +178,25 @@ public void testNextRoundingValueCornerCase8209() { assertThat(roundedValue, equalTo(time("2014-04-30T23:00:00.000Z", DateTimeZone.UTC))); } + /** + * test for #10025, strict local to UTC conversion can cause joda exceptions + * on DST start + */ + @Test + public void testLenientConversionDST() { + DateTimeZone tz = DateTimeZone.forID("America/Sao_Paulo"); + long start = time("2014-10-18T20:50:00.000", tz); + long end = time("2014-10-19T01:00:00.000", tz); + Rounding tzRounding = new TimeZoneRounding.TimeTimeZoneRoundingFloor(DateTimeUnit.MINUTES_OF_HOUR, tz, + DateTimeZone.UTC); + Rounding dayTzRounding = new TimeZoneRounding.DayTimeZoneRoundingFloor(DateTimeUnit.MINUTES_OF_HOUR, tz, + DateTimeZone.UTC); + for (long time = start; time < end; time = time + 60000) { + assertThat(tzRounding.nextRoundingValue(time), greaterThan(time)); + assertThat(dayTzRounding.nextRoundingValue(time), greaterThan(time)); + } + } + private long utc(String time) { return time(time, DateTimeZone.UTC); }