# HG changeset patch # User André Bargull # Date 1510140221 28800 # Wed Nov 08 03:23:41 2017 -0800 # Node ID 8bf5e7460a7c5ba3430b501d1659c469a862a929 # Parent 60fd4a5b01ec70ded9ddfd560fd5be191b1c74b9 Bug 1415202: Always use the equivalent year to determine the time zone offset and name. r=Waldo diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -2348,22 +2348,26 @@ static PRMJTime ToPRMJTime(double localT prtm.tm_isdst = (DaylightSavingTA(utcTime) != 0); return prtm; } static size_t FormatTime(char* buf, int buflen, const char* fmt, double utcTime, double localTime) { PRMJTime prtm = ToPRMJTime(localTime, utcTime); - int eqivalentYear = IsRepresentableAsTime32(utcTime) + + // If an equivalent year was used to compute the date/time components, use + // the same equivalent year to determine the time zone name and offset in + // PRMJ_FormatTime(...). + int timeZoneYear = IsRepresentableAsTime32(utcTime) ? prtm.tm_year : EquivalentYearForDST(prtm.tm_year); int offsetInSeconds = (int)floor((localTime - utcTime) / msPerSecond); - return PRMJ_FormatTime(buf, buflen, fmt, &prtm, eqivalentYear, + return PRMJ_FormatTime(buf, buflen, fmt, &prtm, timeZoneYear, offsetInSeconds); } enum class FormatSpec { DateTime, Date, Time }; static bool FormatDate(JSContext* cx, double utcTime, FormatSpec format, MutableHandleValue rval) { JSString* str; diff --git a/js/src/vm/Time.cpp b/js/src/vm/Time.cpp --- a/js/src/vm/Time.cpp +++ b/js/src/vm/Time.cpp @@ -242,17 +242,17 @@ static void PRMJ_InvalidParameterHandler const wchar_t* file, unsigned int line, uintptr_t pReserved) { /* empty */ } #endif /* Format a time value into a buffer. Same semantics as strftime() */ size_t PRMJ_FormatTime(char* buf, int buflen, const char* fmt, - const PRMJTime* prtm, int equivalentYear, + const PRMJTime* prtm, int timeZoneYear, int offsetInSeconds) { size_t result = 0; #if defined(XP_UNIX) || defined(XP_WIN) struct tm a; #ifdef XP_WIN _invalid_parameter_handler oldHandler; #ifndef __MINGW32__ int oldReportMode; @@ -275,39 +275,33 @@ size_t PRMJ_FormatTime(char* buf, int bu */ #if defined(HAVE_LOCALTIME_R) && defined(HAVE_TM_ZONE_TM_GMTOFF) char emptyTimeZoneId[] = ""; { /* * Fill out |td| to the time represented by |prtm|, leaving the * timezone fields zeroed out. localtime_r will then fill in the * timezone fields for that local time according to the system's - * timezone parameters. + * timezone parameters. Use |timeZoneYear| for the year to ensure the + * time zone name matches the time zone offset used by the caller. */ struct tm td; memset(&td, 0, sizeof(td)); td.tm_sec = prtm->tm_sec; td.tm_min = prtm->tm_min; td.tm_hour = prtm->tm_hour; td.tm_mday = prtm->tm_mday; td.tm_mon = prtm->tm_mon; td.tm_wday = prtm->tm_wday; - td.tm_year = prtm->tm_year - 1900; + td.tm_year = timeZoneYear - 1900; td.tm_yday = prtm->tm_yday; td.tm_isdst = prtm->tm_isdst; time_t t = mktime(&td); - // If |prtm| cannot be represented in |time_t| the year is probably - // out of range, try again with the DST equivalent year. - if (t == static_cast(-1)) { - td.tm_year = equivalentYear - 1900; - t = mktime(&td); - } - // If either mktime or localtime_r failed, fill in the fallback time // zone offset |offsetInSeconds| and set the time zone identifier to // the empty string. if (t != static_cast(-1) && localtime_r(&t, &td)) { a.tm_gmtoff = td.tm_gmtoff; a.tm_zone = td.tm_zone; } else { a.tm_gmtoff = offsetInSeconds; diff --git a/js/src/vm/Time.h b/js/src/vm/Time.h --- a/js/src/vm/Time.h +++ b/js/src/vm/Time.h @@ -44,17 +44,17 @@ inline void PRMJ_NowInit() {} #ifdef XP_WIN extern void PRMJ_NowShutdown(); #else inline void PRMJ_NowShutdown() {} #endif /* Format a time value into a buffer. Same semantics as strftime() */ extern size_t PRMJ_FormatTime(char* buf, int buflen, const char* fmt, - const PRMJTime* tm, int equivalentYear, + const PRMJTime* tm, int timeZoneYear, int offsetInSeconds); /** * Requesting the number of cycles from the CPU. * * `rdtsc`, or Read TimeStamp Cycle, is an instruction provided by * x86-compatible CPUs that lets processes request the number of * cycles spent by the CPU executing instructions since the CPU was