// ECMA 262 - 15.9.1.9
function EquivalentYear(year) {
- // Returns an equivalent year in the range [1956-2000] matching
+ // Returns an equivalent year in the range [2008-2035] matching
// - leap year.
// - week day of first day.
var time = TimeFromYear(year);
- return (InLeapYear(time) == 0 ? 1967 : 1956) + (WeekDay(time) * 12) % 28;
+ var recent_year = (InLeapYear(time) == 0 ? 1967 : 1956) +
+ (WeekDay(time) * 12) % 28;
+ // Find the year in the range 2008..2037 that is equivalent mod 28.
+ // Add 3*28 to give a positive argument to the modulus operator.
+ return 2008 + (recent_year + 3*28 - 2008) % 28;
}
function EquivalentTime(t) {
// The issue here is that some library calls don't work right for dates
- // that cannot be represented using a signed 32 bit integer (measured in
- // whole seconds based on the 1970 epoch).
+ // that cannot be represented using a non-negative signed 32 bit integer
+ // (measured in whole seconds based on the 1970 epoch).
// We solve this by mapping the time to a year with same leap-year-ness
- // and same starting day for the year.
- // As an optimization we avoid finding an equivalent year in the common
- // case. We are measuring in ms here so the 32 bit signed integer range
- // is +-(1<<30)*1000 ie approximately +-2.1e20.
- if (t >= -2.1e12 && t <= 2.1e12) return t;
+ // and same starting day for the year. The ECMAscript specification says
+ // we must do this, but for compatability with other browsers, we use
+ // the actual year if it is in the range 1970..2037
+ if (t >= 0 && t <= 2.1e12) return t;
var day = MakeDay(EquivalentYear(YearFromTime(t)), MonthFromTime(t), DateFromTime(t));
return TimeClip(MakeDate(day, TimeWithinDay(t)));
}
#include <windows.h>
+#include <time.h> // For LocalOffset() implementation.
#include <mmsystem.h> // For timeGetTime().
#include <dbghelp.h> // For SymLoadModule64 and al.
#include <tlhelp32.h> // For Module32First and al.
// 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) {
static bool initialized = false;
static TimeStamp init_time;
static DWORD init_ticks;
- static const int kHundredNanosecondsPerSecond = 10000;
- static const int kMaxClockElapsedTime =
- 60*60*24*kHundredNanosecondsPerSecond; // 1 day
+ static const int64_t kHundredNanosecondsPerSecond = 10000000;
+ static const int64_t kMaxClockElapsedTime =
+ 60*kHundredNanosecondsPerSecond; // 1 minute
// If we are uninitialized, we need to resync the clock.
bool needs_resync = !initialized;
// 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-delay.js guarantees this.
int64_t Time::LocalOffset() {
// Initialize timezone information, if needed.
TzSet();
- // Convert timestamp to date/time components. These are now in UTC
- // format. NB: Please do not replace the following three calls with one
- // call to FileTimeToLocalFileTime(), because it does not handle
- // daylight saving correctly.
- SYSTEMTIME utc;
- FileTimeToSystemTime(&ft(), &utc);
-
- // Convert to local time, using timezone information.
- SYSTEMTIME local;
- SystemTimeToTzSpecificLocalTime(&tzinfo_, &utc, &local);
-
- // Convert local time back to a timestamp. This timestamp now
- // has a bias similar to the local timezone bias in effect
- // at the time of the original timestamp.
- Time localtime;
- SystemTimeToFileTime(&local, &localtime.ft());
-
- // The difference between the new local timestamp and the original
- // timestamp and is the local timezone offset.
- return localtime.Diff(this);
+ Time rounded_to_second(*this);
+ rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler *
+ 1000 * kTimeScaler;
+ // Convert to local time using POSIX localtime function.
+ // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime()
+ // very slow. Other browsers use localtime().
+
+ // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to
+ // POSIX seconds past 1/1/1970 0:00:00.
+ double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000;
+ if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) {
+ return 0;
+ }
+ // Because _USE_32BIT_TIME_T is defined, time_t is a 32-bit int.
+ time_t posix_time = static_cast<time_t>(unchecked_posix_time);
+
+ // Convert to local time, as struct with fields for day, hour, year, etc.
+ tm posix_local_time_struct;
+ if (localtime_s(&posix_local_time_struct, &posix_time)) return 0;
+ // Convert local time in struct to POSIX time as if it were a UTC time.
+ time_t local_posix_time = _mkgmtime(&posix_local_time_struct);
+ Time localtime(1000.0 * local_posix_time);
+
+ return localtime.Diff(&rounded_to_second);
}