Skip to content

Commit dcf4c2a

Browse files
Fix TimeZone mappings for Windows Phone and Unity
This was causing installation saves to fail when not on english locale. For real, this time. Fixes #138.
1 parent b801a6e commit dcf4c2a

File tree

3 files changed

+59
-13
lines changed

3 files changed

+59
-13
lines changed

Parse/Internal/PlatformHooks/Phone/PlatformHooks.Phone.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,26 @@ public string DeviceType {
151151
public string DeviceTimeZone {
152152
get {
153153
// We need the system string to be in english so we'll have the proper key in our lookup table.
154-
var culture = Thread.CurrentThread.CurrentCulture;
155-
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
156-
string windowsName = TimeZoneInfo.Local.StandardName;
157-
Thread.CurrentThread.CurrentCulture = culture;
154+
// If it's not in english then we will attempt to fallback to the closest Time Zone we can find.
155+
TimeZoneInfo tzInfo = TimeZoneInfo.Local;
158156

159-
if (ParseInstallation.TimeZoneNameMap.ContainsKey(windowsName)) {
160-
return ParseInstallation.TimeZoneNameMap[windowsName];
161-
} else {
162-
return null;
157+
string deviceTimeZone = null;
158+
if (ParseInstallation.TimeZoneNameMap.TryGetValue(tzInfo.StandardName, out deviceTimeZone)) {
159+
return deviceTimeZone;
160+
}
161+
162+
TimeSpan utcOffset = tzInfo.BaseUtcOffset;
163+
164+
// If we have an offset that is not a round hour, then use our second map to see if we can
165+
// convert it or not.
166+
if (ParseInstallation.TimeZoneOffsetMap.TryGetValue(utcOffset, out deviceTimeZone)) {
167+
return deviceTimeZone;
163168
}
169+
170+
// NOTE: Etc/GMT{+/-} format is inverted from the UTC offset we use as normal people -
171+
// a negative value means ahead of UTC, a positive value means behind UTC.
172+
bool negativeOffset = utcOffset.Ticks < 0;
173+
return String.Format("Etc/GMT{0}{1}", negativeOffset ? "+" : "-", Math.Abs(utcOffset.Hours));
164174
}
165175
}
166176

Parse/Internal/PlatformHooks/Unity/PlatformHooks.Unity.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,27 @@ public string DeviceType {
8888
public string DeviceTimeZone {
8989
get {
9090
try {
91-
string windowsName = TimeZoneInfo.Local.StandardName;
92-
if (ParseInstallation.TimeZoneNameMap.ContainsKey(windowsName)) {
93-
return ParseInstallation.TimeZoneNameMap[windowsName];
94-
} else {
95-
return null;
91+
// We need the system string to be in english so we'll have the proper key in our lookup table.
92+
// If it's not in english then we will attempt to fallback to the closest Time Zone we can find.
93+
TimeZoneInfo tzInfo = TimeZoneInfo.Local;
94+
95+
string deviceTimeZone = null;
96+
if (ParseInstallation.TimeZoneNameMap.TryGetValue(tzInfo.StandardName, out deviceTimeZone)) {
97+
return deviceTimeZone;
9698
}
99+
100+
TimeSpan utcOffset = tzInfo.BaseUtcOffset;
101+
102+
// If we have an offset that is not a round hour, then use our second map to see if we can
103+
// convert it or not.
104+
if (ParseInstallation.TimeZoneOffsetMap.TryGetValue(utcOffset, out deviceTimeZone)) {
105+
return deviceTimeZone;
106+
}
107+
108+
// NOTE: Etc/GMT{+/-} format is inverted from the UTC offset we use as normal people -
109+
// a negative value means ahead of UTC, a positive value means behind UTC.
110+
bool negativeOffset = utcOffset.Ticks < 0;
111+
return String.Format("Etc/GMT{0}{1}", negativeOffset ? "+" : "-", Math.Abs(utcOffset.Hours));
97112
} catch (TimeZoneNotFoundException) {
98113
return null;
99114
}

Parse/Public/ParseInstallation.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,5 +352,26 @@ internal override Task SaveAsync(Task toAwait, CancellationToken cancellationTok
352352
{"Tonga Standard Time", "Pacific/Tongatapu"},
353353
{"Samoa Standard Time", "Pacific/Apia"}
354354
};
355+
356+
/// <summary>
357+
/// This is a mapping of odd TimeZone offsets to their respective IANA codes across the world.
358+
/// This list was compiled from painstakingly pouring over the information available at
359+
/// https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
360+
/// </summary>
361+
internal static readonly Dictionary<TimeSpan, String> TimeZoneOffsetMap = new Dictionary<TimeSpan, string>() {
362+
{ new TimeSpan(12, 45, 0), "Pacific/Chatham" },
363+
{ new TimeSpan(10, 30, 0), "Australia/Lord_Howe" },
364+
{ new TimeSpan(9, 30, 0), "Australia/Adelaide" },
365+
{ new TimeSpan(8, 45, 0), "Australia/Eucla" },
366+
{ new TimeSpan(8, 30, 0), "Asia/Pyongyang" }, // Parse in North Korea confirmed.
367+
{ new TimeSpan(6, 30, 0), "Asia/Rangoon" },
368+
{ new TimeSpan(5, 45, 0), "Asia/Kathmandu" },
369+
{ new TimeSpan(5, 30, 0), "Asia/Colombo" },
370+
{ new TimeSpan(4, 30, 0), "Asia/Kabul" },
371+
{ new TimeSpan(3, 30, 0), "Asia/Tehran" },
372+
{ new TimeSpan(-3, 30, 0), "America/St_Johns" },
373+
{ new TimeSpan(-4, 30, 0), "America/Caracas" },
374+
{ new TimeSpan(-9, 30, 0), "Pacific/Marquesas" },
375+
};
355376
}
356377
}

0 commit comments

Comments
 (0)