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
This commit is contained in:
Christoph Büscher 2015-03-08 11:11:40 -07:00
parent 9bf4afd88e
commit ab5e020114
2 changed files with 21 additions and 4 deletions

View File

@ -125,7 +125,7 @@ public abstract class TimeZoneRounding extends Rounding {
long timeLocal = utcMillis; long timeLocal = utcMillis;
timeLocal = timeZone.convertUTCToLocal(utcMillis); timeLocal = timeZone.convertUTCToLocal(utcMillis);
long rounded = field.roundFloor(timeLocal); long rounded = field.roundFloor(timeLocal);
return timeZone.convertLocalToUTC(rounded, true, utcMillis); return timeZone.convertLocalToUTC(rounded, false, utcMillis);
} }
@Override @Override
@ -139,7 +139,7 @@ public abstract class TimeZoneRounding extends Rounding {
long timeLocal = time; long timeLocal = time;
timeLocal = timeZone.convertUTCToLocal(time); timeLocal = timeZone.convertUTCToLocal(time);
long nextInLocalTime = durationField.add(timeLocal, 1); long nextInLocalTime = durationField.add(timeLocal, 1);
return timeZone.convertLocalToUTC(nextInLocalTime, true); return timeZone.convertLocalToUTC(nextInLocalTime, false);
} }
@Override @Override
@ -184,7 +184,7 @@ public abstract class TimeZoneRounding extends Rounding {
long timeLocal = utcMillis; long timeLocal = utcMillis;
timeLocal = timeZone.convertUTCToLocal(utcMillis); timeLocal = timeZone.convertUTCToLocal(utcMillis);
long rounded = Rounding.Interval.roundValue(Rounding.Interval.roundKey(timeLocal, interval), interval); long rounded = Rounding.Interval.roundValue(Rounding.Interval.roundKey(timeLocal, interval), interval);
return timeZone.convertLocalToUTC(rounded, true); return timeZone.convertLocalToUTC(rounded, false);
} }
@Override @Override
@ -198,7 +198,7 @@ public abstract class TimeZoneRounding extends Rounding {
long timeLocal = time; long timeLocal = time;
timeLocal = timeZone.convertUTCToLocal(time); timeLocal = timeZone.convertUTCToLocal(time);
long next = timeLocal + interval; long next = timeLocal + interval;
return timeZone.convertLocalToUTC(next, true); return timeZone.convertLocalToUTC(next, false);
} }
@Override @Override

View File

@ -280,6 +280,23 @@ public class TimeZoneRoundingTests extends ElasticsearchTestCase {
equalTo(tzRounding.round(time("2014-08-11T17:00:00", JERUSALEM_TIMEZONE)))); equalTo(tzRounding.round(time("2014-08-11T17:00:00", JERUSALEM_TIMEZONE))));
} }
/**
* 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.TimeUnitRounding(DateTimeUnit.MINUTES_OF_HOUR, tz);
Rounding dayTzRounding = new TimeZoneRounding.TimeIntervalRounding(60000, tz);
for (long time = start; time < end; time = time + 60000) {
assertThat(tzRounding.nextRoundingValue(time), greaterThan(time));
assertThat(dayTzRounding.nextRoundingValue(time), greaterThan(time));
}
}
private DateTimeUnit randomTimeUnit() { private DateTimeUnit randomTimeUnit() {
byte id = (byte) randomIntBetween(1, 8); byte id = (byte) randomIntBetween(1, 8);
return DateTimeUnit.resolve(id); return DateTimeUnit.resolve(id);