diff options
author | wtchang%redhat.com <devnull@localhost> | 2007-01-16 00:31:10 +0000 |
---|---|---|
committer | wtchang%redhat.com <devnull@localhost> | 2007-01-16 00:31:10 +0000 |
commit | d406e99cfb78cebbc9f30290b4dbf3c26536dd1a (patch) | |
tree | 12d8130372f8b910d0cfd4e7972aefcaabd972e8 | |
parent | 55710b6bf0454204ae2991f0ce72f77963b0d212 (diff) | |
download | nspr-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.c | 130 |
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; |