| --- nspr-4.8.6/mozilla/nsprpub/pr/src/misc/prtime.c 2010-03-30 12:15:26.000000000 -0700 |
| +++ nspr-4.8.6.N/mozilla/nsprpub/pr/src/misc/prtime.c 2013-10-21 13:55:53.000000000 -0700 |
| @@ -102,6 +102,7 @@ |
| static void ComputeGMT(PRTime time, PRExplodedTime *gmt); |
| static int IsLeapYear(PRInt16 year); |
| static void ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset); |
| +static void AdjustDSTGMTOffsets(PRTime time, PRExplodedTime *exploded); |
| |
| /* |
| *------------------------------------------------------------------------ |
| @@ -244,6 +245,7 @@ |
| exploded->tm_params = params(exploded); |
| ApplySecOffset(exploded, exploded->tm_params.tp_gmt_offset |
| + exploded->tm_params.tp_dst_offset); |
| + AdjustDSTGMTOffsets(usecs, exploded); |
| } |
| |
| |
| @@ -581,11 +583,68 @@ |
| |
| #endif /* definition of MT_safe_localtime() */ |
| |
| +static PRBool ComputeLocalTime(time_t local, struct tm *ptm) |
| +{ |
| +#ifdef HAVE_LOCALTIME_R |
| + return localtime_r(&local, ptm); |
| + |
| +#elif HAVE_LOCALTIME_MONITOR |
| + |
| + if (MT_safe_localtime(&local, ptm) != NULL) |
| + return PR_TRUE; |
| + else |
| + return PR_FALSE; |
| +#else |
| + |
| + #error no ComputeLocalTime() |
| + |
| +#endif /* definition of ComputeLocalTime() */ |
| +} |
| + |
| +#ifndef HAVE_GMTIME_R |
| + |
| +#define HAVE_GMT_MONITOR 1 /* We use 'monitorgmt' to serialize our calls |
| + * to gmtime(). */ |
| + |
| +static PRLock *monitorgmt = NULL; |
| +#endif |
| + |
| +static PRBool ComputeUTCTime(time_t t, struct tm *ptm) |
| +{ |
| +#ifdef HAVE_GMTIME_R |
| + return gmtime_r(&t, ptm); |
| +#else |
| + PRBool retval = PR_TRUE; |
| + struct tm *otm = NULL; |
| + int needLock = PR_Initialized(); /* We need to use a lock to protect |
| + * against NSPR threads only when the |
| + * NSPR thread system is activated. */ |
| + if (needLock) PR_Lock(monitorgmt); |
| + |
| + otm = gmtime(&t); |
| + |
| + if (!otm) |
| + retval = PR_FALSE; |
| + else |
| + { |
| + *ptm = *otm; |
| + retval = PR_TRUE; |
| + } |
| + |
| + if (needLock) PR_Unlock(monitorgmt); |
| + |
| + return retval; |
| +#endif /* definition of ComputeUTCTime() */ |
| +} |
| + |
| void _PR_InitTime(void) |
| { |
| #ifdef HAVE_LOCALTIME_MONITOR |
| monitor = PR_NewLock(); |
| #endif |
| +#ifdef HAVE_GMT_MONITOR |
| + monitorgmt = PR_NewLock(); |
| +#endif |
| #ifdef WINCE |
| _MD_InitTime(); |
| #endif |
| @@ -599,11 +658,118 @@ |
| monitor = NULL; |
| } |
| #endif |
| +#ifdef HAVE_GMT_MONITOR |
| + if (monitorgmt) { |
| + PR_DestroyLock(monitorgmt); |
| + monitorgmt = NULL; |
| + } |
| +#endif |
| #ifdef WINCE |
| _MD_CleanupTime(); |
| #endif |
| } |
| |
| +/* |
| + * from https://mxr.mozilla.org/mozilla-central/source/js/src/vm/DateTime.cpp?rev=699228670afb |
| + * but slightly adjusted as the modzilla has an issue during the hours close to the dst-std change |
| + * Compute the offset in seconds from the current UTC time to the current local |
| + * time |
| + * |
| + * Examples: |
| + * |
| + * Suppose we are in California, USA on January 1, 2013 at 04:00 PST (UTC-8, no |
| + * DST in effect), corresponding to 12:00 UTC. This function would then return |
| + * -8 * SecondsPerHour, or -28800. |
| + * |
| + * Or suppose we are in Berlin, Germany on July 1, 2013 at 17:00 CEST (UTC+2, |
| + * DST in effect), corresponding to 15:00 UTC. This function would then return |
| + * +2 * SecondsPerHour, or +7200. |
| + */ |
| +static PRInt32 |
| +UTCToLocalTimeOffsetSeconds(time_t time) |
| +{ |
| + PRInt32 SecondsPerDay = 86400; |
| + PRInt32 SecondsPerHour = 3600; |
| + PRInt32 SecondsPerMinute = 60; |
| + struct tm local; |
| + struct tm utc; |
| + |
| + memset(&local, 0, sizeof(local)); |
| + memset(&utc, 0, sizeof(utc)); |
| + |
| + |
| +#if defined(XP_WIN) |
| + // Windows doesn't follow POSIX: updates to the TZ environment variable are |
| + // not reflected immediately on that platform as they are on other systems |
| + // without this call. |
| + _tzset(); |
| +#endif |
| + |
| + // Break down the current time into its components. |
| + if (!ComputeLocalTime(time, &local)) |
| + return 0; |
| + |
| + // Break down the local time into UTC-based components. |
| + memset(&utc, 0, sizeof(utc)); |
| + if (!ComputeUTCTime(time, &utc)) |
| + return 0; |
| + |
| + // Finally, compare the seconds-based components of the local |
| + // representation and the UTC representation to determine the actual |
| + // difference. |
| + PRInt32 utc_secs = utc.tm_hour * SecondsPerHour + utc.tm_min * SecondsPerMinute; |
| + PRInt32 local_secs = local.tm_hour * SecondsPerHour + local.tm_min * SecondsPerMinute; |
| + |
| + // Same-day? Just subtract the seconds counts. |
| + if (utc.tm_mday == local.tm_mday) |
| + return local_secs - utc_secs; |
| + |
| + // If we have more UTC seconds, move local seconds into the UTC seconds' |
| + // frame of reference and then subtract. |
| + if (utc_secs > local_secs) |
| + return (SecondsPerDay + local_secs) - utc_secs; |
| + |
| + // Otherwise we have more local seconds, so move the UTC seconds into the |
| + // local seconds' frame of reference and then subtract. |
| + return local_secs - (utc_secs + SecondsPerDay); |
| +} |
| + |
| +static void |
| +AdjustDSTGMTOffsets(PRTime time, PRExplodedTime *exploded) |
| +{ |
| + PRInt64 sec64; |
| + PRInt64 usecPerSec; |
| + PRInt32 overallOffsetFromUTC; |
| + PRInt32 dstoffset = 3600; |
| + struct tm localTime; |
| + time_t timetsecs; |
| + |
| + LL_I2L(usecPerSec, 1000000L); |
| + LL_DIV(sec64, time, usecPerSec); |
| + |
| + timetsecs = sec64; |
| + |
| + /* |
| + * overall_offset = gmt_offset + dst_offset |
| + */ |
| + overallOffsetFromUTC = UTCToLocalTimeOffsetSeconds(timetsecs); |
| + |
| + /* |
| + * used the passed time to calculate the right offsets based on |
| + * linux call to localtime |
| + */ |
| + (void) MT_safe_localtime(&timetsecs, &localTime); |
| + |
| + if (localTime.tm_isdst <= 0) { |
| + /* DST is not in effect */ |
| + exploded->tm_params.tp_gmt_offset = overallOffsetFromUTC; |
| + exploded->tm_params.tp_dst_offset = 0; |
| + } else { |
| + exploded->tm_params.tp_gmt_offset = overallOffsetFromUTC - dstoffset; |
| + exploded->tm_params.tp_dst_offset = dstoffset; |
| + } |
| +} |
| + |
| #if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) |
| |
| PR_IMPLEMENT(PRTimeParameters) |
| @@ -642,7 +808,7 @@ |
| |
| /* GMT is 00:00:00, 2nd of Jan. */ |
| |
| - offset2Jan1970 = (PRInt32)localTime.tm_sec |
| + offset2Jan1970 = (PRInt32)localTime.tm_sec |
| + 60L * (PRInt32)localTime.tm_min |
| + 3600L * (PRInt32)localTime.tm_hour |
| + 86400L * (PRInt32)((PRInt32)localTime.tm_mday - 2L); |
| @@ -696,7 +862,7 @@ |
| } |
| |
| /* |
| - * dayOffset is the offset between local time and GMT in |
| + * dayOffset is the offset between local time and GMT in |
| * the day component, which can only be -1, 0, or 1. We |
| * use the day of the week to compute dayOffset. |
| */ |
| @@ -745,7 +911,7 @@ |
| retVal.tp_dst_offset = 3600; |
| } |
| } |
| - |
| + |
| return retVal; |
| } |
| |