cherrypick: Try to use names from time zone strings if all else fails...
Fixes b/7232823 Use time zone name when all else fails...
Change-Id: Idc2633041641db43559d32185c6bd0e2a90f4765
diff --git a/exchange2/src/com/android/exchange/utility/CalendarUtilities.java b/exchange2/src/com/android/exchange/utility/CalendarUtilities.java
index a0ac47d..2872e80 100644
--- a/exchange2/src/com/android/exchange/utility/CalendarUtilities.java
+++ b/exchange2/src/com/android/exchange/utility/CalendarUtilities.java
@@ -107,17 +107,19 @@
// The following constants relate to Microsoft's TIME_ZONE_INFORMATION structure
// For documentation, see http://msdn.microsoft.com/en-us/library/ms725481(VS.85).aspx
+ static final int MSFT_TIME_ZONE_STRING_SIZE = 32;
+
static final int MSFT_TIME_ZONE_BIAS_OFFSET = 0;
static final int MSFT_TIME_ZONE_STANDARD_NAME_OFFSET =
MSFT_TIME_ZONE_BIAS_OFFSET + MSFT_LONG_SIZE;
static final int MSFT_TIME_ZONE_STANDARD_DATE_OFFSET =
- MSFT_TIME_ZONE_STANDARD_NAME_OFFSET + (MSFT_WCHAR_SIZE*32);
+ MSFT_TIME_ZONE_STANDARD_NAME_OFFSET + (MSFT_WCHAR_SIZE*MSFT_TIME_ZONE_STRING_SIZE);
static final int MSFT_TIME_ZONE_STANDARD_BIAS_OFFSET =
MSFT_TIME_ZONE_STANDARD_DATE_OFFSET + MSFT_SYSTEMTIME_SIZE;
static final int MSFT_TIME_ZONE_DAYLIGHT_NAME_OFFSET =
MSFT_TIME_ZONE_STANDARD_BIAS_OFFSET + MSFT_LONG_SIZE;
static final int MSFT_TIME_ZONE_DAYLIGHT_DATE_OFFSET =
- MSFT_TIME_ZONE_DAYLIGHT_NAME_OFFSET + (MSFT_WCHAR_SIZE*32);
+ MSFT_TIME_ZONE_DAYLIGHT_NAME_OFFSET + (MSFT_WCHAR_SIZE*MSFT_TIME_ZONE_STRING_SIZE);
static final int MSFT_TIME_ZONE_DAYLIGHT_BIAS_OFFSET =
MSFT_TIME_ZONE_DAYLIGHT_DATE_OFFSET + MSFT_SYSTEMTIME_SIZE;
static final int MSFT_TIME_ZONE_SIZE =
@@ -216,6 +218,19 @@
bytes[offset] = (byte) ((value >> 8) & 0xFF);
}
+ static String getString(byte[] bytes, int offset, int size) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < size; i++) {
+ int ch = bytes[offset + i];
+ if (ch == 0) {
+ break;
+ } else {
+ sb.append((char)ch);
+ }
+ }
+ return sb.toString();
+ }
+
// Internal structure for storing a time zone date from a SYSTEMTIME structure
// This date represents either the start or the end time for DST
static class TimeZoneDate {
@@ -861,19 +876,34 @@
if (dstSavings != timeZone.getDSTSavings()) continue;
return timeZone;
}
- // 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
boolean lenient = false;
+ boolean name = false;
if ((dstStart.hour != dstEnd.hour) && (precision == STANDARD_DST_PRECISION)) {
timeZone = tziStringToTimeZoneImpl(timeZoneString, LENIENT_DST_PRECISION);
lenient = true;
} else {
- timeZone = TimeZone.getTimeZone(zoneIds[0]);
+ // We can't find a time zone match, so our last attempt is to see if there's
+ // a valid time zone name in the TZI; if not we'll just take the first TZ with
+ // a matching offset (which is likely wrong, but ... what else is there to do)
+ String tzName = getString(timeZoneBytes, MSFT_TIME_ZONE_STANDARD_NAME_OFFSET,
+ MSFT_TIME_ZONE_STRING_SIZE);
+ if (!tzName.isEmpty()) {
+ TimeZone tz = TimeZone.getTimeZone(tzName);
+ if (tz != null) {
+ timeZone = tz;
+ name = true;
+ } else {
+ timeZone = TimeZone.getTimeZone(zoneIds[0]);
+ }
+ } else {
+ timeZone = TimeZone.getTimeZone(zoneIds[0]);
+ }
}
if (Eas.USER_LOG) {
ExchangeService.log(TAG,
"No TimeZone with correct DST settings; using " +
- (lenient ? "lenient" : "first") + ": " + timeZone.getID());
+ (name ? "name" : (lenient ? "lenient" : "first")) + ": " +
+ 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 0ecdb8f..77820a5 100644
--- a/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
+++ b/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
@@ -110,6 +110,13 @@
"AAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAAAAAAAAAAAxP///w==";
+ // This string specifies "Europe/London" in the name, but otherwise is somewhat bogus
+ // in that it has unknown time zone dates with a 0 bias (GMT). (From a Zimbra server user)
+ private static final String EUROPE_LONDON_TIME_BY_NAME =
+ "AAAAAEV1cm9wZS9Mb25kb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
+ "AAAAAAAAAAoAAQAFAAIAAAAAAAAAAAAAAEV1cm9wZS9Mb25kb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAQAFAAEAAAAAAAAAxP///w==";
+
private static final String ORGANIZER = "organizer@server.com";
private static final String ATTENDEE = "attendee@server.com";
@@ -140,6 +147,9 @@
tz = CalendarUtilities.tziStringToTimeZone(AUSTRALIA_ACT_TIME);
assertEquals("Australia/ACT", tz.getID());
+ tz = CalendarUtilities.tziStringToTimeZone(EUROPE_LONDON_TIME_BY_NAME);
+ assertEquals("Europe/London", tz.getID());
+
// Test peculiar MS sent EST data with and without lenient precision; send standard
// precision + 1 (i.e. 1ms) to make sure the code doesn't automatically flip to lenient
// when the tz isn't found