Index: runtime/vm/os_win.cc |
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc |
index 2ea8c1dd6755c44e65c6361a9b3ef89d4e0e2136..7236a9164959810a6bf96c85f5786aed3f8adc1a 100644 |
--- a/runtime/vm/os_win.cc |
+++ b/runtime/vm/os_win.cc |
@@ -34,7 +34,9 @@ intptr_t OS::ProcessId() { |
// As a side-effect sets the globals _timezone, _daylight and _tzname. |
static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { |
time_t seconds = static_cast<time_t>(seconds_since_epoch); |
- if (seconds != seconds_since_epoch) return false; |
+ if (seconds != seconds_since_epoch) { |
+ return false; |
+ } |
// localtime_s implicitly sets _timezone, _daylight and _tzname. |
errno_t error_code = localtime_s(tm_result, &seconds); |
return error_code == 0; |
@@ -54,17 +56,38 @@ static int GetDaylightSavingBiasInSeconds() { |
const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) { |
- tm decomposed; |
- // LocalTime will set _tzname. |
- bool succeeded = LocalTime(seconds_since_epoch, &decomposed); |
- if (succeeded) { |
- int inDaylightSavingsTime = decomposed.tm_isdst; |
- ASSERT(inDaylightSavingsTime == 0 || inDaylightSavingsTime == 1); |
- return _tzname[inDaylightSavingsTime]; |
- } else { |
- // Return an empty string like V8 does. |
+ TIME_ZONE_INFORMATION zone_information; |
+ memset(&zone_information, 0, sizeof(zone_information)); |
+ |
+ // Initialize and grab the time zone data. |
+ _tzset(); |
+ DWORD status = GetTimeZoneInformation(&zone_information); |
+ if (GetTimeZoneInformation(&zone_information) == TIME_ZONE_ID_INVALID) { |
+ // If we can't get the time zone data, the Windows docs indicate that we |
+ // are probably out of memory. Return an empty string. |
return ""; |
} |
+ |
+ // Figure out whether we're in standard or daylight. |
+ bool daylight_savings = (status == TIME_ZONE_ID_DAYLIGHT); |
+ if (status == TIME_ZONE_ID_UNKNOWN) { |
+ tm local_time; |
+ if (LocalTime(seconds_since_epoch, &local_time)) { |
+ daylight_savings = (local_time.tm_isdst == 1); |
+ } |
+ } |
+ |
+ // Convert the wchar string to a null-terminated utf8 string. |
+ wchar_t* wchar_name = daylight_savings |
+ ? zone_information.DaylightName |
+ : zone_information.StandardName; |
+ intptr_t utf8_len = WideCharToMultiByte( |
+ CP_UTF8, 0, wchar_name, -1, NULL, 0, NULL, NULL); |
+ char* name = Thread::Current()->zone()->Alloc<char>(utf8_len + 1); |
+ WideCharToMultiByte( |
+ CP_UTF8, 0, wchar_name, -1, name, utf8_len, NULL, NULL); |
+ name[utf8_len] = '\0'; |
+ return name; |
} |