| 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();
|
| }
|
|
|