Fix serious DST issue with non-DST time zones
* When finding a match for an EAS time zone without DST, we were
checking the offset, but NOT the DST status; therefore, we could
match the wrong time zone (depending on the order of items in the
TZ database)
* All users with events set up in non-DST timezones would have their
events show up at the wrong time after a DST transition
* The fix is to first check against the default time zone, and use
that if it's a match; otherwise, to use the first time zone that
matches both offset and DST availability
Bug: 4337360
Change-Id: I21d59673d2f3b0bb3e513976455071d5ea67d595
diff --git a/src/com/android/exchange/utility/CalendarUtilities.java b/src/com/android/exchange/utility/CalendarUtilities.java
index 92453b8..edf3b65 100644
--- a/src/com/android/exchange/utility/CalendarUtilities.java
+++ b/src/com/android/exchange/utility/CalendarUtilities.java
@@ -30,6 +30,7 @@
import com.android.exchange.R;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
+import com.android.internal.util.ArrayUtils;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -699,7 +700,7 @@
TimeZone timeZone = sTimeZoneCache.get(timeZoneString);
if (timeZone != null) {
if (Eas.USER_LOG) {
- ExchangeService.log(TAG, " Using cached TimeZone " + timeZone.getDisplayName());
+ ExchangeService.log(TAG, " Using cached TimeZone " + timeZone.getID());
}
} else {
timeZone = tziStringToTimeZoneImpl(timeZoneString);
@@ -740,14 +741,31 @@
TimeZoneDate dstEnd =
getTimeZoneDateFromSystemTime(timeZoneBytes, MSFT_TIME_ZONE_STANDARD_DATE_OFFSET);
if (dstEnd == null) {
- // In this case, there is no daylight savings time, so the only interesting data
- // is the offset, and we know that all of the zoneId's match; we'll take the first
- timeZone = TimeZone.getTimeZone(zoneIds[0]);
- if (Eas.USER_LOG) {
- ExchangeService.log(TAG, "TimeZone without DST found by offset: " +
- timeZone.getDisplayName());
+ // If the default time zone is a match
+ TimeZone defaultTimeZone = TimeZone.getDefault();
+ if (!defaultTimeZone.useDaylightTime() &&
+ ArrayUtils.contains(zoneIds, defaultTimeZone.getID())) {
+ if (Eas.USER_LOG) {
+ ExchangeService.log(TAG, "TimeZone without DST found to be default: " +
+ defaultTimeZone.getID());
+ }
+ return defaultTimeZone;
}
- return timeZone;
+ // In this case, there is no daylight savings time, so the only interesting data
+ // for possible matches is the offset and DST availability; we'll take the first
+ // match for those
+ for (String zoneId: zoneIds) {
+ timeZone = TimeZone.getTimeZone(zoneId);
+ if (!timeZone.useDaylightTime()) {
+ if (Eas.USER_LOG) {
+ ExchangeService.log(TAG, "TimeZone without DST found by offset: " +
+ timeZone.getID());
+ }
+ return timeZone;
+ }
+ }
+ // None found, return null
+ return null;
} else {
TimeZoneDate dstStart = getTimeZoneDateFromSystemTime(timeZoneBytes,
MSFT_TIME_ZONE_DAYLIGHT_DATE_OFFSET);
@@ -793,7 +811,7 @@
if (Eas.USER_LOG) {
ExchangeService.log(TAG,
"No TimeZone with correct DST settings; using first: " +
- timeZone.getDisplayName());
+ timeZone.getID());
}
return timeZone;
}
diff --git a/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java b/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
index c5ffd8d..9512bfd 100644
--- a/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
+++ b/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
@@ -98,6 +98,12 @@
"AAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAACgARwBNAFQAKwAwADAAOgAwADAAKQAgAFQAaQBtAGUAIABaAG8A" +
"bgBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAEAAAAAAAAAxP///w==";
+ // This time zone has no DST, but earlier, buggy code retrieved a TZ WITH DST
+ private static final String ARIZONA_TIME =
+ "pAEAAFUAUwAgAE0AbwB1AG4AdABhAGkAbgAgAFMAdABhAG4AZABhAHIAZAAgAFQAaQBtAGUAAAAAAAAAAAAA" +
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUAUwAgAE0AbwB1AG4AdABhAGkAbgAgAEQAYQB5AGwAaQBnAGgA" +
+ "dAAgAFQAaQBtAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
+
private static final String ORGANIZER = "organizer@server.com";
private static final String ATTENDEE = "attendee@server.com";
@@ -132,6 +138,9 @@
tz = CalendarUtilities.tziStringToTimeZone(GMT_UNKNOWN_DAYLIGHT_TIME);
int bias = tz.getOffset(System.currentTimeMillis());
assertEquals(0, bias);
+ // Make sure non-DST TZ's work properly
+ tz = CalendarUtilities.tziStringToTimeZone(ARIZONA_TIME);
+ assertEquals("America/Phoenix", tz.getID());
}
public void testGenerateEasDayOfWeek() {