summaryrefslogtreecommitdiff
path: root/pr/src/misc/prtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'pr/src/misc/prtime.c')
-rw-r--r--pr/src/misc/prtime.c162
1 files changed, 103 insertions, 59 deletions
diff --git a/pr/src/misc/prtime.c b/pr/src/misc/prtime.c
index a3cd1c6e..3736d699 100644
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -569,6 +569,8 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params)
extern struct tm *Maclocaltime(const time_t * t);
#endif
+#define HAVE_LOCALTIME_MONITOR 1 /* We use 'monitor' to serialize our calls
+ * to localtime(). */
static PRLock *monitor = NULL;
static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result)
@@ -578,12 +580,7 @@ static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result)
* against NSPR threads only when the
* NSPR thread system is activated. */
- if (needLock) {
- if (monitor == NULL) {
- monitor = PR_NewLock();
- }
- PR_Lock(monitor);
- }
+ if (needLock) PR_Lock(monitor);
/*
* Microsoft (all flavors) localtime() returns a NULL pointer if 'clock'
@@ -628,6 +625,23 @@ static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result)
#endif /* definition of MT_safe_localtime() */
+void _PR_InitTime(void)
+{
+#ifdef HAVE_LOCALTIME_MONITOR
+ monitor = PR_NewLock();
+#endif
+}
+
+void _PR_CleanupTime(void)
+{
+#ifdef HAVE_LOCALTIME_MONITOR
+ if (monitor) {
+ PR_DestroyLock(monitor);
+ monitor = NULL;
+ }
+#endif
+}
+
#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS)
PR_IMPLEMENT(PRTimeParameters)
@@ -775,9 +789,53 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt)
*------------------------------------------------------------------------
*/
+/*
+ * Returns the mday of the first sunday of the month, where
+ * mday and wday are for a given day in the month.
+ * mdays start with 1 (e.g. 1..31).
+ * wdays start with 0 and are in the range 0..6. 0 = Sunday.
+ */
+#define firstSunday(mday, wday) (((mday - wday + 7 - 1) % 7) + 1)
+
+/*
+ * Returns the mday for the N'th Sunday of the month, where
+ * mday and wday are for a given day in the month.
+ * mdays start with 1 (e.g. 1..31).
+ * wdays start with 0 and are in the range 0..6. 0 = Sunday.
+ * N has the following values: 0 = first, 1 = second (etc), -1 = last.
+ * ndays is the number of days in that month, the same value as the
+ * mday of the last day of the month.
+ */
+static PRInt32
+NthSunday(PRInt32 mday, PRInt32 wday, PRInt32 N, PRInt32 ndays)
+{
+ PRInt32 firstSun = firstSunday(mday, wday);
+
+ if (N < 0)
+ N = (ndays - firstSun) / 7;
+ return firstSun + (7 * N);
+}
+
+typedef struct DSTParams {
+ PRInt8 dst_start_month; /* 0 = January */
+ PRInt8 dst_start_Nth_Sunday; /* N as defined above */
+ PRInt8 dst_start_month_ndays; /* ndays as defined above */
+ PRInt8 dst_end_month; /* 0 = January */
+ PRInt8 dst_end_Nth_Sunday; /* N as defined above */
+ PRInt8 dst_end_month_ndays; /* ndays as defined above */
+} DSTParams;
+
+static const DSTParams dstParams[2] = {
+ /* year < 2007: First April Sunday - Last October Sunday */
+ { 3, 0, 30, 9, -1, 31 },
+ /* year >= 2007: Second March Sunday - First November Sunday */
+ { 2, 1, 31, 10, 0, 30 }
+};
+
PR_IMPLEMENT(PRTimeParameters)
PR_USPacificTimeParameters(const PRExplodedTime *gmt)
{
+ const DSTParams *dst;
PRTimeParameters retVal;
PRExplodedTime st;
@@ -807,61 +865,51 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
/* Apply the offset to GMT to obtain the local standard time */
ApplySecOffset(&st, retVal.tp_gmt_offset);
+ if (st.tm_year < 2007) { /* first April Sunday - Last October Sunday */
+ dst = &dstParams[0];
+ } else { /* Second March Sunday - First November Sunday */
+ dst = &dstParams[1];
+ }
+
/*
* Apply the rules on standard time or GMT to obtain daylight saving
* time offset. In this implementation, we use the US DST rule.
*/
- if (st.tm_month < 3) {
+ if (st.tm_month < dst->dst_start_month) {
retVal.tp_dst_offset = 0L;
- } else if (st.tm_month == 3) {
- if (st.tm_wday == 0) {
- /* A Sunday */
- if (st.tm_mday <= 7) {
- /* First Sunday */
- /* 01:59:59 PST -> 03:00:00 PDT */
- if (st.tm_hour < 2) {
- retVal.tp_dst_offset = 0L;
- } else {
- retVal.tp_dst_offset = 3600L;
- }
- } else {
- /* Not first Sunday */
- retVal.tp_dst_offset = 3600L;
- }
- } else {
- /* Not a Sunday. See if before first Sunday or after */
- if (st.tm_wday + 1 <= st.tm_mday) {
- /* After first Sunday */
- retVal.tp_dst_offset = 3600L;
- } else {
- /* Before first Sunday */
- retVal.tp_dst_offset = 0L;
- }
+ } else if (st.tm_month == dst->dst_start_month) {
+ int NthSun = NthSunday(st.tm_mday, st.tm_wday,
+ dst->dst_start_Nth_Sunday,
+ dst->dst_start_month_ndays);
+ if (st.tm_mday < NthSun) { /* Before starting Sunday */
+ retVal.tp_dst_offset = 0L;
+ } else if (st.tm_mday == NthSun) { /* Starting Sunday */
+ /* 01:59:59 PST -> 03:00:00 PDT */
+ if (st.tm_hour < 2) {
+ retVal.tp_dst_offset = 0L;
+ } else {
+ retVal.tp_dst_offset = 3600L;
+ }
+ } else { /* After starting Sunday */
+ retVal.tp_dst_offset = 3600L;
}
- } else if (st.tm_month < 9) {
+ } else if (st.tm_month < dst->dst_end_month) {
retVal.tp_dst_offset = 3600L;
- } else if (st.tm_month == 9) {
- if (st.tm_wday == 0) {
- if (31 - st.tm_mday < 7) {
- /* Last Sunday */
- /* 01:59:59 PDT -> 01:00:00 PST */
- if (st.tm_hour < 1) {
- retVal.tp_dst_offset = 3600L;
- } else {
- retVal.tp_dst_offset = 0L;
- }
- } else {
- /* Not last Sunday */
- retVal.tp_dst_offset = 3600L;
- }
- } else {
- /* See if before or after last Sunday */
- if (7 - st.tm_wday <= 31 - st.tm_mday) {
- /* before last Sunday */
- retVal.tp_dst_offset = 3600L;
- } else {
- retVal.tp_dst_offset = 0L;
- }
+ } else if (st.tm_month == dst->dst_end_month) {
+ int NthSun = NthSunday(st.tm_mday, st.tm_wday,
+ dst->dst_end_Nth_Sunday,
+ dst->dst_end_month_ndays);
+ if (st.tm_mday < NthSun) { /* Before ending Sunday */
+ retVal.tp_dst_offset = 3600L;
+ } else if (st.tm_mday == NthSun) { /* Ending Sunday */
+ /* 01:59:59 PDT -> 01:00:00 PST */
+ if (st.tm_hour < 1) {
+ retVal.tp_dst_offset = 3600L;
+ } else {
+ retVal.tp_dst_offset = 0L;
+ }
+ } else { /* After ending Sunday */
+ retVal.tp_dst_offset = 0L;
}
} else {
retVal.tp_dst_offset = 0L;
@@ -1242,13 +1290,9 @@ PR_ParseTimeString(
else
tmp_hour = (rest[0]-'0');
- while (*rest && *rest != ':')
- rest++;
- rest++;
-
/* move over the colon, and parse minutes */
- end = rest + 1;
+ rest = ++end;
while (*end >= '0' && *end <= '9')
end++;