Index: src/platform-win32.cc |
diff --git a/src/platform-win32.cc b/src/platform-win32.cc |
index afcd82bcba5615e520095549686b9024d04a621f..f88a4ab3db5f33c13ec4590c57721c2d65b778b9 100644 |
--- a/src/platform-win32.cc |
+++ b/src/platform-win32.cc |
@@ -218,6 +218,97 @@ void MathSetup() { |
} |
+class TimezoneCache { |
+ public: |
+ TimezoneCache() : initialized_(false) { } |
+ |
+ void Clear() { |
+ initialized_ = false; |
+ } |
+ |
+ // Initialize timezone information. The timezone information is obtained from |
+ // windows. If we cannot get the timezone information we fall back to CET. |
+ void InitializeIfNeeded() { |
+ // Just return if timezone information has already been initialized. |
+ if (initialized_) return; |
+ |
+ // Initialize POSIX time zone data. |
+ _tzset(); |
+ // Obtain timezone information from operating system. |
+ memset(&tzinfo_, 0, sizeof(tzinfo_)); |
+ if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) { |
+ // If we cannot get timezone information we fall back to CET. |
+ tzinfo_.Bias = -60; |
+ tzinfo_.StandardDate.wMonth = 10; |
+ tzinfo_.StandardDate.wDay = 5; |
+ tzinfo_.StandardDate.wHour = 3; |
+ tzinfo_.StandardBias = 0; |
+ tzinfo_.DaylightDate.wMonth = 3; |
+ tzinfo_.DaylightDate.wDay = 5; |
+ tzinfo_.DaylightDate.wHour = 2; |
+ tzinfo_.DaylightBias = -60; |
+ } |
+ |
+ // Make standard and DST timezone names. |
+ WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1, |
+ std_tz_name_, kTzNameSize, NULL, NULL); |
+ std_tz_name_[kTzNameSize - 1] = '\0'; |
+ WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1, |
+ dst_tz_name_, kTzNameSize, NULL, NULL); |
+ dst_tz_name_[kTzNameSize - 1] = '\0'; |
+ |
+ // If OS returned empty string or resource id (like "@tzres.dll,-211") |
+ // simply guess the name from the UTC bias of the timezone. |
+ // To properly resolve the resource identifier requires a library load, |
+ // which is not possible in a sandbox. |
+ if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') { |
+ OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1), |
+ "%s Standard Time", |
+ GuessTimezoneNameFromBias(tzinfo_.Bias)); |
+ } |
+ if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') { |
+ OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1), |
+ "%s Daylight Time", |
+ GuessTimezoneNameFromBias(tzinfo_.Bias)); |
+ } |
+ // Timezone information initialized. |
+ initialized_ = true; |
+ } |
+ |
+ // Guess the name of the timezone from the bias. |
+ // The guess is very biased towards the northern hemisphere. |
+ const char* GuessTimezoneNameFromBias(int bias) { |
+ static const int kHour = 60; |
+ switch (-bias) { |
+ case -9*kHour: return "Alaska"; |
+ case -8*kHour: return "Pacific"; |
+ case -7*kHour: return "Mountain"; |
+ case -6*kHour: return "Central"; |
+ case -5*kHour: return "Eastern"; |
+ case -4*kHour: return "Atlantic"; |
+ case 0*kHour: return "GMT"; |
+ case +1*kHour: return "Central Europe"; |
+ case +2*kHour: return "Eastern Europe"; |
+ case +3*kHour: return "Russia"; |
+ case +5*kHour + 30: return "India"; |
+ case +8*kHour: return "China"; |
+ case +9*kHour: return "Japan"; |
+ case +12*kHour: return "New Zealand"; |
+ default: return "Local"; |
+ } |
+ } |
+ |
+ |
+ private: |
+ static const int kTzNameSize = 128; |
+ bool initialized_; |
+ char std_tz_name_[kTzNameSize]; |
+ char dst_tz_name_[kTzNameSize]; |
+ TIME_ZONE_INFORMATION tzinfo_; |
+ friend class Win32Time; |
+}; |
+ |
+ |
// ---------------------------------------------------------------------------- |
// The Time class represents time on win32. A timestamp is represented as |
// a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript |
@@ -242,16 +333,14 @@ class Win32Time { |
// LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This |
// routine also takes into account whether daylight saving is effect |
// at the time. |
- int64_t LocalOffset(); |
+ int64_t LocalOffset(TimezoneCache* cache); |
// Returns the daylight savings time offset for the time in milliseconds. |
- int64_t DaylightSavingsOffset(); |
+ int64_t DaylightSavingsOffset(TimezoneCache* cache); |
// Returns a string identifying the current timezone for the |
// timestamp taking into account daylight saving. |
- char* LocalTimezone(); |
- |
- static void TimeZoneChanged() { tz_initialized_ = false; } |
+ char* LocalTimezone(TimezoneCache* cache); |
private: |
// Constants for time conversion. |
@@ -260,25 +349,10 @@ class Win32Time { |
static const int64_t kMsPerMinute = 60000; |
// Constants for timezone information. |
- static const int kTzNameSize = 128; |
static const bool kShortTzNames = false; |
- // Timezone information. We need to have static buffers for the |
- // timezone names because we return pointers to these in |
- // LocalTimezone(). |
- static bool tz_initialized_; |
- static TIME_ZONE_INFORMATION tzinfo_; |
- static char std_tz_name_[kTzNameSize]; |
- static char dst_tz_name_[kTzNameSize]; |
- |
- // Initialize the timezone information (if not already done). |
- static void TzSet(); |
- |
- // Guess the name of the timezone from the bias. |
- static const char* GuessTimezoneNameFromBias(int bias); |
- |
// Return whether or not daylight savings time is in effect at this time. |
- bool InDST(); |
+ bool InDST(TimezoneCache* cache); |
// Accessor for FILETIME representation. |
FILETIME& ft() { return time_.ft_; } |
@@ -300,13 +374,6 @@ class Win32Time { |
}; |
-// Static variables. |
-bool Win32Time::tz_initialized_ = false; |
-TIME_ZONE_INFORMATION Win32Time::tzinfo_; |
-char Win32Time::std_tz_name_[kTzNameSize]; |
-char Win32Time::dst_tz_name_[kTzNameSize]; |
- |
- |
// Initialize timestamp to start of epoc. |
Win32Time::Win32Time() { |
t() = 0; |
@@ -395,90 +462,13 @@ void Win32Time::SetToCurrentTime() { |
} |
-// Guess the name of the timezone from the bias. |
-// The guess is very biased towards the northern hemisphere. |
-const char* Win32Time::GuessTimezoneNameFromBias(int bias) { |
- static const int kHour = 60; |
- switch (-bias) { |
- case -9*kHour: return "Alaska"; |
- case -8*kHour: return "Pacific"; |
- case -7*kHour: return "Mountain"; |
- case -6*kHour: return "Central"; |
- case -5*kHour: return "Eastern"; |
- case -4*kHour: return "Atlantic"; |
- case 0*kHour: return "GMT"; |
- case +1*kHour: return "Central Europe"; |
- case +2*kHour: return "Eastern Europe"; |
- case +3*kHour: return "Russia"; |
- case +5*kHour + 30: return "India"; |
- case +8*kHour: return "China"; |
- case +9*kHour: return "Japan"; |
- case +12*kHour: return "New Zealand"; |
- default: return "Local"; |
- } |
-} |
- |
- |
-// Initialize timezone information. The timezone information is obtained from |
-// windows. If we cannot get the timezone information we fall back to CET. |
-// Please notice that this code is not thread-safe. |
-void Win32Time::TzSet() { |
- // Just return if timezone information has already been initialized. |
- if (tz_initialized_) return; |
- |
- // Initialize POSIX time zone data. |
- _tzset(); |
- // Obtain timezone information from operating system. |
- memset(&tzinfo_, 0, sizeof(tzinfo_)); |
- if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) { |
- // If we cannot get timezone information we fall back to CET. |
- tzinfo_.Bias = -60; |
- tzinfo_.StandardDate.wMonth = 10; |
- tzinfo_.StandardDate.wDay = 5; |
- tzinfo_.StandardDate.wHour = 3; |
- tzinfo_.StandardBias = 0; |
- tzinfo_.DaylightDate.wMonth = 3; |
- tzinfo_.DaylightDate.wDay = 5; |
- tzinfo_.DaylightDate.wHour = 2; |
- tzinfo_.DaylightBias = -60; |
- } |
- |
- // Make standard and DST timezone names. |
- WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1, |
- std_tz_name_, kTzNameSize, NULL, NULL); |
- std_tz_name_[kTzNameSize - 1] = '\0'; |
- WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1, |
- dst_tz_name_, kTzNameSize, NULL, NULL); |
- dst_tz_name_[kTzNameSize - 1] = '\0'; |
- |
- // If OS returned empty string or resource id (like "@tzres.dll,-211") |
- // simply guess the name from the UTC bias of the timezone. |
- // To properly resolve the resource identifier requires a library load, |
- // which is not possible in a sandbox. |
- if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') { |
- OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1), |
- "%s Standard Time", |
- GuessTimezoneNameFromBias(tzinfo_.Bias)); |
- } |
- if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') { |
- OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1), |
- "%s Daylight Time", |
- GuessTimezoneNameFromBias(tzinfo_.Bias)); |
- } |
- |
- // Timezone information initialized. |
- tz_initialized_ = true; |
-} |
- |
- |
// Return the local timezone offset in milliseconds east of UTC. This |
// takes into account whether daylight saving is in effect at the time. |
// Only times in the 32-bit Unix range may be passed to this function. |
// Also, adding the time-zone offset to the input must not overflow. |
// The function EquivalentTime() in date.js guarantees this. |
-int64_t Win32Time::LocalOffset() { |
- // Initialize timezone information, if needed. |
- TzSet(); |
+int64_t Win32Time::LocalOffset(TimezoneCache* cache) { |
+ cache->InitializeIfNeeded(); |
Win32Time rounded_to_second(*this); |
rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * |
@@ -501,29 +491,30 @@ int64_t Win32Time::LocalOffset() { |
if (localtime_s(&posix_local_time_struct, &posix_time)) return 0; |
if (posix_local_time_struct.tm_isdst > 0) { |
- return (tzinfo_.Bias + tzinfo_.DaylightBias) * -kMsPerMinute; |
+ return (cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * -kMsPerMinute; |
} else if (posix_local_time_struct.tm_isdst == 0) { |
- return (tzinfo_.Bias + tzinfo_.StandardBias) * -kMsPerMinute; |
+ return (cache->tzinfo_.Bias + cache->tzinfo_.StandardBias) * -kMsPerMinute; |
} else { |
- return tzinfo_.Bias * -kMsPerMinute; |
+ return cache->tzinfo_.Bias * -kMsPerMinute; |
} |
} |
// Return whether or not daylight savings time is in effect at this time. |
-bool Win32Time::InDST() { |
- // Initialize timezone information, if needed. |
- TzSet(); |
+bool Win32Time::InDST(TimezoneCache* cache) { |
+ cache->InitializeIfNeeded(); |
// Determine if DST is in effect at the specified time. |
bool in_dst = false; |
- if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) { |
+ if (cache->tzinfo_.StandardDate.wMonth != 0 || |
+ cache->tzinfo_.DaylightDate.wMonth != 0) { |
// Get the local timezone offset for the timestamp in milliseconds. |
int64_t offset = LocalOffset(); |
// Compute the offset for DST. The bias parameters in the timezone info |
// are specified in minutes. These must be converted to milliseconds. |
- int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute; |
+ int64_t dstofs = |
+ -(cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * kMsPerMinute; |
// If the local time offset equals the timezone bias plus the daylight |
// bias then DST is in effect. |
@@ -535,17 +526,17 @@ bool Win32Time::InDST() { |
// Return the daylight savings time offset for this time. |
-int64_t Win32Time::DaylightSavingsOffset() { |
- return InDST() ? 60 * kMsPerMinute : 0; |
+int64_t Win32Time::DaylightSavingsOffset(TimezoneCache* cache) { |
+ return InDST(cache) ? 60 * kMsPerMinute : 0; |
} |
// Returns a string identifying the current timezone for the |
// timestamp taking into account daylight saving. |
-char* Win32Time::LocalTimezone() { |
+char* Win32Time::LocalTimezone(TimezoneCache* cache) { |
// Return the standard or DST time zone name based on whether daylight |
// saving is in effect at the given time. |
- return InDST() ? dst_tz_name_ : std_tz_name_; |
+ return InDST(cache) ? cache->dst_tz_name_ : cache->std_tz_name_; |
} |
@@ -588,36 +579,47 @@ double OS::TimeCurrentMillis() { |
} |
+TimezoneCache* OS::CreateTimezoneCache() { |
+ return new TimezoneCache(); |
+} |
+ |
+ |
+void OS::DisposeTimezoneCache(TimezoneCache* cache) { |
+ delete cache; |
+} |
+ |
+ |
+void OS::ClearTimezoneCache(TimezoneCache* cache) { |
+ cache->Clear(); |
+} |
+ |
+ |
// Returns a string identifying the current timezone taking into |
// account daylight saving. |
-const char* OS::LocalTimezone(double time) { |
- return Win32Time(time).LocalTimezone(); |
+const char* OS::LocalTimezone(double time, TimezoneCache* cache) { |
+ return Win32Time(time).LocalTimezone(cache); |
} |
// Returns the local time offset in milliseconds east of UTC without |
// taking daylight savings time into account. |
-double OS::LocalTimeOffset() { |
+double OS::LocalTimeOffset(TimezoneCache* cache) { |
// Use current time, rounded to the millisecond. |
Win32Time t(TimeCurrentMillis()); |
// Time::LocalOffset inlcudes any daylight savings offset, so subtract it. |
- return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset()); |
+ return static_cast<double>(t.LocalOffset(cache) - |
+ t.DaylightSavingsOffset(cache)); |
} |
// Returns the daylight savings offset in milliseconds for the given |
// time. |
-double OS::DaylightSavingsOffset(double time) { |
- int64_t offset = Win32Time(time).DaylightSavingsOffset(); |
+double OS::DaylightSavingsOffset(double time, TimezoneCache* cache) { |
+ int64_t offset = Win32Time(time).DaylightSavingsOffset(cache); |
return static_cast<double>(offset); |
} |
-void OS::TimeZoneChanged() { |
- Win32Time::TimeZoneChanged(); |
-} |
- |
- |
int OS::GetLastError() { |
return ::GetLastError(); |
} |