summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtchang%redhat.com <devnull@localhost>2007-01-16 00:31:10 +0000
committerwtchang%redhat.com <devnull@localhost>2007-01-16 00:31:10 +0000
commitd406e99cfb78cebbc9f30290b4dbf3c26536dd1a (patch)
tree12d8130372f8b910d0cfd4e7972aefcaabd972e8
parent55710b6bf0454204ae2991f0ce72f77963b0d212 (diff)
downloadnspr-hg-d406e99cfb78cebbc9f30290b4dbf3c26536dd1a.tar.gz
Bug 365997: updated PR_USPacificTimeParameters with the new US Daylight
Saving Time rule. By Nelson Bolyard of Sun Microsystems. r=wtc. Tag: NSPR_4_6_BRANCH
-rw-r--r--pr/src/misc/prtime.c130
1 files changed, 82 insertions, 48 deletions
diff --git a/pr/src/misc/prtime.c b/pr/src/misc/prtime.c
index 17d13bcd..3736d699 100644
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -789,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;
@@ -821,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;