blob: 14b5503f0600ae3bd4e49fe5edfeb64823f08376 [file] [log] [blame]
--- 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;
}