diff options
author | wolfbeast <mcwerewolf@wolfbeast.com> | 2020-01-02 21:01:38 +0100 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2020-01-02 21:01:38 +0100 |
commit | f7d30133221896638f7bf4f66c504255c4b14f48 (patch) | |
tree | 5f3e07a049f388a3a309a615b8884318f6668a98 /nsprpub/pr/src/misc/prtime.c | |
parent | 26b297510a11758727438df4669357a2a2bc42ce (diff) | |
download | UXP-f7d30133221896638f7bf4f66c504255c4b14f48.tar UXP-f7d30133221896638f7bf4f66c504255c4b14f48.tar.gz UXP-f7d30133221896638f7bf4f66c504255c4b14f48.tar.lz UXP-f7d30133221896638f7bf4f66c504255c4b14f48.tar.xz UXP-f7d30133221896638f7bf4f66c504255c4b14f48.zip |
Issue #1338 - Part 1: Update NSPR to 4.24
Diffstat (limited to 'nsprpub/pr/src/misc/prtime.c')
-rw-r--r-- | nsprpub/pr/src/misc/prtime.c | 1978 |
1 files changed, 1047 insertions, 931 deletions
diff --git a/nsprpub/pr/src/misc/prtime.c b/nsprpub/pr/src/misc/prtime.c index f03786096..6d711a6b8 100644 --- a/nsprpub/pr/src/misc/prtime.c +++ b/nsprpub/pr/src/misc/prtime.c @@ -21,7 +21,7 @@ #include <errno.h> /* for EINVAL */ #include <time.h> -/* +/* * The COUNT_LEAPS macro counts the number of leap years passed by * till the start of the given year Y. At the start of the year 4 * A.D. the number of leap years passed by is 0, while at the start of @@ -204,14 +204,14 @@ ComputeGMT(PRTime time, PRExplodedTime *gmt) PR_IMPLEMENT(void) PR_ExplodeTime( - PRTime usecs, - PRTimeParamFn params, - PRExplodedTime *exploded) + PRTime usecs, + PRTimeParamFn params, + PRExplodedTime *exploded) { ComputeGMT(usecs, exploded); exploded->tm_params = params(exploded); ApplySecOffset(exploded, exploded->tm_params.tp_gmt_offset - + exploded->tm_params.tp_dst_offset); + + exploded->tm_params.tp_dst_offset); } @@ -241,9 +241,9 @@ PR_ImplodeTime(const PRExplodedTime *exploded) PR_NormalizeTime(©, PR_GMTParameters); numDays = DAYS_BETWEEN_YEARS(1970, copy.tm_year); - + numSecs = copy.tm_yday * 86400 + copy.tm_hour * 3600 - + copy.tm_min * 60 + copy.tm_sec; + + copy.tm_min * 60 + copy.tm_sec; LL_I2L(temp, numDays); LL_I2L(secPerDay, 86400); @@ -277,8 +277,9 @@ PR_ImplodeTime(const PRExplodedTime *exploded) static int IsLeapYear(PRInt16 year) { - if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) + if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { return 1; + } return 0; } @@ -321,23 +322,26 @@ ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset) if (time->tm_month < 0) { time->tm_month = 11; time->tm_year--; - if (IsLeapYear(time->tm_year)) + if (IsLeapYear(time->tm_year)) { time->tm_yday = 365; - else + } + else { time->tm_yday = 364; + } } time->tm_mday = nDays[IsLeapYear(time->tm_year)][time->tm_month]; } time->tm_wday--; - if (time->tm_wday < 0) + if (time->tm_wday < 0) { time->tm_wday = 6; + } } else if (time->tm_hour > 23) { /* Increment mday, yday, and wday */ time->tm_hour -= 24; time->tm_mday++; time->tm_yday++; if (time->tm_mday > - nDays[IsLeapYear(time->tm_year)][time->tm_month]) { + nDays[IsLeapYear(time->tm_year)][time->tm_month]) { time->tm_mday = 1; time->tm_month++; if (time->tm_month > 11) { @@ -347,8 +351,9 @@ ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset) } } time->tm_wday++; - if (time->tm_wday > 6) + if (time->tm_wday > 6) { time->tm_wday = 0; + } } } @@ -360,7 +365,7 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) /* Get back to GMT */ time->tm_sec -= time->tm_params.tp_gmt_offset - + time->tm_params.tp_dst_offset; + + time->tm_params.tp_dst_offset; time->tm_params.tp_gmt_offset = 0; time->tm_params.tp_dst_offset = 0; @@ -442,8 +447,8 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) /* Recompute yday and wday */ time->tm_yday = time->tm_mday + - lastDayOfMonth[IsLeapYear(time->tm_year)][time->tm_month]; - + lastDayOfMonth[IsLeapYear(time->tm_year)][time->tm_month]; + numDays = DAYS_BETWEEN_YEARS(1970, time->tm_year) + time->tm_yday; time->tm_wday = (numDays + 4) % 7; if (time->tm_wday < 0) { @@ -455,7 +460,7 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) time->tm_params = params(time); ApplySecOffset(time, time->tm_params.tp_gmt_offset - + time->tm_params.tp_dst_offset); + + time->tm_params.tp_dst_offset); } @@ -463,7 +468,7 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) *------------------------------------------------------------------------- * * PR_LocalTimeParameters -- - * + * * returns the time parameters for the local time zone * * The following uses localtime() from the standard C library. @@ -480,7 +485,7 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) * In this case we could define the macro as * #define MT_safe_localtime(timer, result) \ * (localtime_r(timer, result) == 0 ? result : NULL) - * I chose to compare the return value of localtime_r with -1 so + * I chose to compare the return value of localtime_r with -1 so * that I can catch the cases where localtime_r returns a pointer * to struct tm. The macro definition above would not be able to * detect such mistakes because it is legal to compare a pointer @@ -521,7 +526,9 @@ 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) PR_Lock(monitor); + if (needLock) { + PR_Lock(monitor); + } /* * Microsoft (all flavors) localtime() returns a NULL pointer if 'clock' @@ -538,15 +545,17 @@ static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result) * clock plus ULONG_MAX. So we also have to check for the invalid * structs returned for timezones west of Greenwich when clock == 0. */ - + tmPtr = localtime(clock); #if defined(WIN16) || defined(XP_OS2) if ( (PRInt32) *clock < 0 || - ( (PRInt32) *clock == 0 && tmPtr->tm_year != 70)) + ( (PRInt32) *clock == 0 && tmPtr->tm_year != 70)) { result = NULL; - else + } + else { *result = *tmPtr; + } #else if (tmPtr) { *result = *tmPtr; @@ -555,7 +564,9 @@ static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result) } #endif /* WIN16 */ - if (needLock) PR_Unlock(monitor); + if (needLock) { + PR_Unlock(monitor); + } return result; } @@ -585,7 +596,7 @@ void _PR_CleanupTime(void) #endif } -#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) +#if defined(XP_UNIX) || defined(XP_PC) PR_IMPLEMENT(PRTimeParameters) PR_LocalTimeParameters(const PRExplodedTime *gmt) @@ -629,10 +640,10 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) /* GMT is 00:00:00, 2nd of Jan. */ - offset2Jan1970 = (PRInt32)localTime.tm_sec - + 60L * (PRInt32)localTime.tm_min - + 3600L * (PRInt32)localTime.tm_hour - + 86400L * (PRInt32)((PRInt32)localTime.tm_mday - 2L); + offset2Jan1970 = (PRInt32)localTime.tm_sec + + 60L * (PRInt32)localTime.tm_min + + 3600L * (PRInt32)localTime.tm_hour + + 86400L * (PRInt32)((PRInt32)localTime.tm_mday - 2L); isdst2Jan1970 = localTime.tm_isdst; @@ -683,7 +694,7 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) } /* - * 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. */ @@ -704,9 +715,9 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) } offsetNew = (PRInt32)localTime.tm_sec - gmt->tm_sec - + 60L * ((PRInt32)localTime.tm_min - gmt->tm_min) - + 3600L * ((PRInt32)localTime.tm_hour - gmt->tm_hour) - + 86400L * (PRInt32)dayOffset; + + 60L * ((PRInt32)localTime.tm_min - gmt->tm_min) + + 3600L * ((PRInt32)localTime.tm_hour - gmt->tm_hour) + + 86400L * (PRInt32)dayOffset; if (localTime.tm_isdst <= 0) { /* DST is not in effect */ @@ -732,11 +743,11 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) retVal.tp_dst_offset = 3600; } } - + return retVal; } -#endif /* defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) */ +#endif /* defined(XP_UNIX) || defined(XP_PC) */ /* *------------------------------------------------------------------------ @@ -751,27 +762,28 @@ 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). + * 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 + * 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). + * 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 + * 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) +static PRInt32 +NthSunday(PRInt32 mday, PRInt32 wday, PRInt32 N, PRInt32 ndays) { PRInt32 firstSun = firstSunday(mday, wday); - if (N < 0) + if (N < 0) { N = (ndays - firstSun) / 7; + } return firstSun + (7 * N); } @@ -825,9 +837,9 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt) ApplySecOffset(&st, retVal.tp_gmt_offset); if (st.tm_year < 2007) { /* first April Sunday - Last October Sunday */ - dst = &dstParams[0]; + dst = &dstParams[0]; } else { /* Second March Sunday - First November Sunday */ - dst = &dstParams[1]; + dst = &dstParams[1]; } /* @@ -837,38 +849,38 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt) if (st.tm_month < dst->dst_start_month) { 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; + 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; + /* 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 < dst->dst_end_month) { retVal.tp_dst_offset = 3600L; } 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; + 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; + /* 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; @@ -918,15 +930,15 @@ PR_GMTParameters(const PRExplodedTime *gmt) typedef enum { - TT_UNKNOWN, + TT_UNKNOWN, - TT_SUN, TT_MON, TT_TUE, TT_WED, TT_THU, TT_FRI, TT_SAT, + TT_SUN, TT_MON, TT_TUE, TT_WED, TT_THU, TT_FRI, TT_SAT, - TT_JAN, TT_FEB, TT_MAR, TT_APR, TT_MAY, TT_JUN, - TT_JUL, TT_AUG, TT_SEP, TT_OCT, TT_NOV, TT_DEC, + TT_JAN, TT_FEB, TT_MAR, TT_APR, TT_MAY, TT_JUN, + TT_JUL, TT_AUG, TT_SEP, TT_OCT, TT_NOV, TT_DEC, - TT_PST, TT_PDT, TT_MST, TT_MDT, TT_CST, TT_CDT, TT_EST, TT_EDT, - TT_AST, TT_NST, TT_GMT, TT_BST, TT_MET, TT_EET, TT_JST + TT_PST, TT_PDT, TT_MST, TT_MDT, TT_CST, TT_CDT, TT_EST, TT_EDT, + TT_AST, TT_NST, TT_GMT, TT_BST, TT_MET, TT_EET, TT_JST } TIME_TOKEN; /* @@ -962,716 +974,819 @@ typedef enum PR_IMPLEMENT(PRStatus) PR_ParseTimeStringToExplodedTime( - const char *string, - PRBool default_to_gmt, - PRExplodedTime *result) + const char *string, + PRBool default_to_gmt, + PRExplodedTime *result) { - TIME_TOKEN dotw = TT_UNKNOWN; - TIME_TOKEN month = TT_UNKNOWN; - TIME_TOKEN zone = TT_UNKNOWN; - int zone_offset = -1; - int dst_offset = 0; - int date = -1; - PRInt32 year = -1; - int hour = -1; - int min = -1; - int sec = -1; - struct tm *localTimeResult; - - const char *rest = string; - - int iterations = 0; - - PR_ASSERT(string && result); - if (!string || !result) return PR_FAILURE; - - while (*rest) + TIME_TOKEN dotw = TT_UNKNOWN; + TIME_TOKEN month = TT_UNKNOWN; + TIME_TOKEN zone = TT_UNKNOWN; + int zone_offset = -1; + int dst_offset = 0; + int date = -1; + PRInt32 year = -1; + int hour = -1; + int min = -1; + int sec = -1; + struct tm *localTimeResult; + + const char *rest = string; + + int iterations = 0; + + PR_ASSERT(string && result); + if (!string || !result) { + return PR_FAILURE; + } + + while (*rest) + { + + if (iterations++ > 1000) + { + return PR_FAILURE; + } + + switch (*rest) { + case 'a': case 'A': + if (month == TT_UNKNOWN && + (rest[1] == 'p' || rest[1] == 'P') && + (rest[2] == 'r' || rest[2] == 'R')) { + month = TT_APR; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_AST; + } + else if (month == TT_UNKNOWN && + (rest[1] == 'u' || rest[1] == 'U') && + (rest[2] == 'g' || rest[2] == 'G')) { + month = TT_AUG; + } + break; + case 'b': case 'B': + if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_BST; + } + break; + case 'c': case 'C': + if (zone == TT_UNKNOWN && + (rest[1] == 'd' || rest[1] == 'D') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_CDT; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_CST; + } + break; + case 'd': case 'D': + if (month == TT_UNKNOWN && + (rest[1] == 'e' || rest[1] == 'E') && + (rest[2] == 'c' || rest[2] == 'C')) { + month = TT_DEC; + } + break; + case 'e': case 'E': + if (zone == TT_UNKNOWN && + (rest[1] == 'd' || rest[1] == 'D') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_EDT; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 'e' || rest[1] == 'E') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_EET; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_EST; + } + break; + case 'f': case 'F': + if (month == TT_UNKNOWN && + (rest[1] == 'e' || rest[1] == 'E') && + (rest[2] == 'b' || rest[2] == 'B')) { + month = TT_FEB; + } + else if (dotw == TT_UNKNOWN && + (rest[1] == 'r' || rest[1] == 'R') && + (rest[2] == 'i' || rest[2] == 'I')) { + dotw = TT_FRI; + } + break; + case 'g': case 'G': + if (zone == TT_UNKNOWN && + (rest[1] == 'm' || rest[1] == 'M') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_GMT; + } + break; + case 'j': case 'J': + if (month == TT_UNKNOWN && + (rest[1] == 'a' || rest[1] == 'A') && + (rest[2] == 'n' || rest[2] == 'N')) { + month = TT_JAN; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_JST; + } + else if (month == TT_UNKNOWN && + (rest[1] == 'u' || rest[1] == 'U') && + (rest[2] == 'l' || rest[2] == 'L')) { + month = TT_JUL; + } + else if (month == TT_UNKNOWN && + (rest[1] == 'u' || rest[1] == 'U') && + (rest[2] == 'n' || rest[2] == 'N')) { + month = TT_JUN; + } + break; + case 'm': case 'M': + if (month == TT_UNKNOWN && + (rest[1] == 'a' || rest[1] == 'A') && + (rest[2] == 'r' || rest[2] == 'R')) { + month = TT_MAR; + } + else if (month == TT_UNKNOWN && + (rest[1] == 'a' || rest[1] == 'A') && + (rest[2] == 'y' || rest[2] == 'Y')) { + month = TT_MAY; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 'd' || rest[1] == 'D') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_MDT; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 'e' || rest[1] == 'E') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_MET; + } + else if (dotw == TT_UNKNOWN && + (rest[1] == 'o' || rest[1] == 'O') && + (rest[2] == 'n' || rest[2] == 'N')) { + dotw = TT_MON; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_MST; + } + break; + case 'n': case 'N': + if (month == TT_UNKNOWN && + (rest[1] == 'o' || rest[1] == 'O') && + (rest[2] == 'v' || rest[2] == 'V')) { + month = TT_NOV; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_NST; + } + break; + case 'o': case 'O': + if (month == TT_UNKNOWN && + (rest[1] == 'c' || rest[1] == 'C') && + (rest[2] == 't' || rest[2] == 'T')) { + month = TT_OCT; + } + break; + case 'p': case 'P': + if (zone == TT_UNKNOWN && + (rest[1] == 'd' || rest[1] == 'D') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_PDT; + } + else if (zone == TT_UNKNOWN && + (rest[1] == 's' || rest[1] == 'S') && + (rest[2] == 't' || rest[2] == 'T')) { + zone = TT_PST; + } + break; + case 's': case 'S': + if (dotw == TT_UNKNOWN && + (rest[1] == 'a' || rest[1] == 'A') && + (rest[2] == 't' || rest[2] == 'T')) { + dotw = TT_SAT; + } + else if (month == TT_UNKNOWN && + (rest[1] == 'e' || rest[1] == 'E') && + (rest[2] == 'p' || rest[2] == 'P')) { + month = TT_SEP; + } + else if (dotw == TT_UNKNOWN && + (rest[1] == 'u' || rest[1] == 'U') && + (rest[2] == 'n' || rest[2] == 'N')) { + dotw = TT_SUN; + } + break; + case 't': case 'T': + if (dotw == TT_UNKNOWN && + (rest[1] == 'h' || rest[1] == 'H') && + (rest[2] == 'u' || rest[2] == 'U')) { + dotw = TT_THU; + } + else if (dotw == TT_UNKNOWN && + (rest[1] == 'u' || rest[1] == 'U') && + (rest[2] == 'e' || rest[2] == 'E')) { + dotw = TT_TUE; + } + break; + case 'u': case 'U': + if (zone == TT_UNKNOWN && + (rest[1] == 't' || rest[1] == 'T') && + !(rest[2] >= 'A' && rest[2] <= 'Z') && + !(rest[2] >= 'a' && rest[2] <= 'z')) + /* UT is the same as GMT but UTx is not. */ + { + zone = TT_GMT; + } + break; + case 'w': case 'W': + if (dotw == TT_UNKNOWN && + (rest[1] == 'e' || rest[1] == 'E') && + (rest[2] == 'd' || rest[2] == 'D')) { + dotw = TT_WED; + } + break; + + case '+': case '-': + { + const char *end; + int sign; + if (zone_offset != -1) + { + /* already got one... */ + rest++; + break; + } + if (zone != TT_UNKNOWN && zone != TT_GMT) + { + /* GMT+0300 is legal, but PST+0300 is not. */ + rest++; + break; + } - if (iterations++ > 1000) + sign = ((*rest == '+') ? 1 : -1); + rest++; /* move over sign */ + end = rest; + while (*end >= '0' && *end <= '9') { + end++; + } + if (rest == end) { /* no digits here */ + break; + } + + if ((end - rest) == 4) + /* offset in HHMM */ + zone_offset = (((((rest[0]-'0')*10) + (rest[1]-'0')) * 60) + + (((rest[2]-'0')*10) + (rest[3]-'0'))); + else if ((end - rest) == 2) + /* offset in hours */ + { + zone_offset = (((rest[0]-'0')*10) + (rest[1]-'0')) * 60; + } + else if ((end - rest) == 1) + /* offset in hours */ + { + zone_offset = (rest[0]-'0') * 60; + } + else + /* 3 or >4 */ { - return PR_FAILURE; + break; } - switch (*rest) + zone_offset *= sign; + zone = TT_GMT; + break; + } + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + int tmp_hour = -1; + int tmp_min = -1; + int tmp_sec = -1; + const char *end = rest + 1; + while (*end >= '0' && *end <= '9') { + end++; + } + + /* end is now the first character after a range of digits. */ + + if (*end == ':') { - case 'a': case 'A': - if (month == TT_UNKNOWN && - (rest[1] == 'p' || rest[1] == 'P') && - (rest[2] == 'r' || rest[2] == 'R')) - month = TT_APR; - else if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_AST; - else if (month == TT_UNKNOWN && - (rest[1] == 'u' || rest[1] == 'U') && - (rest[2] == 'g' || rest[2] == 'G')) - month = TT_AUG; - break; - case 'b': case 'B': - if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_BST; - break; - case 'c': case 'C': - if (zone == TT_UNKNOWN && - (rest[1] == 'd' || rest[1] == 'D') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_CDT; - else if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_CST; - break; - case 'd': case 'D': - if (month == TT_UNKNOWN && - (rest[1] == 'e' || rest[1] == 'E') && - (rest[2] == 'c' || rest[2] == 'C')) - month = TT_DEC; - break; - case 'e': case 'E': - if (zone == TT_UNKNOWN && - (rest[1] == 'd' || rest[1] == 'D') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_EDT; - else if (zone == TT_UNKNOWN && - (rest[1] == 'e' || rest[1] == 'E') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_EET; - else if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_EST; - break; - case 'f': case 'F': - if (month == TT_UNKNOWN && - (rest[1] == 'e' || rest[1] == 'E') && - (rest[2] == 'b' || rest[2] == 'B')) - month = TT_FEB; - else if (dotw == TT_UNKNOWN && - (rest[1] == 'r' || rest[1] == 'R') && - (rest[2] == 'i' || rest[2] == 'I')) - dotw = TT_FRI; - break; - case 'g': case 'G': - if (zone == TT_UNKNOWN && - (rest[1] == 'm' || rest[1] == 'M') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_GMT; - break; - case 'j': case 'J': - if (month == TT_UNKNOWN && - (rest[1] == 'a' || rest[1] == 'A') && - (rest[2] == 'n' || rest[2] == 'N')) - month = TT_JAN; - else if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_JST; - else if (month == TT_UNKNOWN && - (rest[1] == 'u' || rest[1] == 'U') && - (rest[2] == 'l' || rest[2] == 'L')) - month = TT_JUL; - else if (month == TT_UNKNOWN && - (rest[1] == 'u' || rest[1] == 'U') && - (rest[2] == 'n' || rest[2] == 'N')) - month = TT_JUN; - break; - case 'm': case 'M': - if (month == TT_UNKNOWN && - (rest[1] == 'a' || rest[1] == 'A') && - (rest[2] == 'r' || rest[2] == 'R')) - month = TT_MAR; - else if (month == TT_UNKNOWN && - (rest[1] == 'a' || rest[1] == 'A') && - (rest[2] == 'y' || rest[2] == 'Y')) - month = TT_MAY; - else if (zone == TT_UNKNOWN && - (rest[1] == 'd' || rest[1] == 'D') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_MDT; - else if (zone == TT_UNKNOWN && - (rest[1] == 'e' || rest[1] == 'E') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_MET; - else if (dotw == TT_UNKNOWN && - (rest[1] == 'o' || rest[1] == 'O') && - (rest[2] == 'n' || rest[2] == 'N')) - dotw = TT_MON; - else if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_MST; - break; - case 'n': case 'N': - if (month == TT_UNKNOWN && - (rest[1] == 'o' || rest[1] == 'O') && - (rest[2] == 'v' || rest[2] == 'V')) - month = TT_NOV; - else if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_NST; - break; - case 'o': case 'O': - if (month == TT_UNKNOWN && - (rest[1] == 'c' || rest[1] == 'C') && - (rest[2] == 't' || rest[2] == 'T')) - month = TT_OCT; - break; - case 'p': case 'P': - if (zone == TT_UNKNOWN && - (rest[1] == 'd' || rest[1] == 'D') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_PDT; - else if (zone == TT_UNKNOWN && - (rest[1] == 's' || rest[1] == 'S') && - (rest[2] == 't' || rest[2] == 'T')) - zone = TT_PST; - break; - case 's': case 'S': - if (dotw == TT_UNKNOWN && - (rest[1] == 'a' || rest[1] == 'A') && - (rest[2] == 't' || rest[2] == 'T')) - dotw = TT_SAT; - else if (month == TT_UNKNOWN && - (rest[1] == 'e' || rest[1] == 'E') && - (rest[2] == 'p' || rest[2] == 'P')) - month = TT_SEP; - else if (dotw == TT_UNKNOWN && - (rest[1] == 'u' || rest[1] == 'U') && - (rest[2] == 'n' || rest[2] == 'N')) - dotw = TT_SUN; - break; - case 't': case 'T': - if (dotw == TT_UNKNOWN && - (rest[1] == 'h' || rest[1] == 'H') && - (rest[2] == 'u' || rest[2] == 'U')) - dotw = TT_THU; - else if (dotw == TT_UNKNOWN && - (rest[1] == 'u' || rest[1] == 'U') && - (rest[2] == 'e' || rest[2] == 'E')) - dotw = TT_TUE; - break; - case 'u': case 'U': - if (zone == TT_UNKNOWN && - (rest[1] == 't' || rest[1] == 'T') && - !(rest[2] >= 'A' && rest[2] <= 'Z') && - !(rest[2] >= 'a' && rest[2] <= 'z')) - /* UT is the same as GMT but UTx is not. */ - zone = TT_GMT; - break; - case 'w': case 'W': - if (dotw == TT_UNKNOWN && - (rest[1] == 'e' || rest[1] == 'E') && - (rest[2] == 'd' || rest[2] == 'D')) - dotw = TT_WED; - break; - - case '+': case '-': - { - const char *end; - int sign; - if (zone_offset != -1) - { - /* already got one... */ - rest++; - break; - } - if (zone != TT_UNKNOWN && zone != TT_GMT) - { - /* GMT+0300 is legal, but PST+0300 is not. */ - rest++; - break; - } - - sign = ((*rest == '+') ? 1 : -1); - rest++; /* move over sign */ - end = rest; - while (*end >= '0' && *end <= '9') - end++; - if (rest == end) /* no digits here */ - break; - - if ((end - rest) == 4) - /* offset in HHMM */ - zone_offset = (((((rest[0]-'0')*10) + (rest[1]-'0')) * 60) + - (((rest[2]-'0')*10) + (rest[3]-'0'))); - else if ((end - rest) == 2) - /* offset in hours */ - zone_offset = (((rest[0]-'0')*10) + (rest[1]-'0')) * 60; - else if ((end - rest) == 1) - /* offset in hours */ - zone_offset = (rest[0]-'0') * 60; - else - /* 3 or >4 */ - break; - - zone_offset *= sign; - zone = TT_GMT; + if (hour >= 0 && min >= 0) { /* already got it */ + break; + } + + /* We have seen "[0-9]+:", so this is probably HH:MM[:SS] */ + if ((end - rest) > 2) + /* it is [0-9][0-9][0-9]+: */ + { + break; + } + if ((end - rest) == 2) + tmp_hour = ((rest[0]-'0')*10 + + (rest[1]-'0')); + else { + tmp_hour = (rest[0]-'0'); + } + + /* move over the colon, and parse minutes */ + + rest = ++end; + while (*end >= '0' && *end <= '9') { + end++; + } + + if (end == rest) + /* no digits after first colon? */ + { + break; + } + if ((end - rest) > 2) + /* it is [0-9][0-9][0-9]+: */ + { break; - } - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - int tmp_hour = -1; - int tmp_min = -1; - int tmp_sec = -1; - const char *end = rest + 1; - while (*end >= '0' && *end <= '9') - end++; - - /* end is now the first character after a range of digits. */ - - if (*end == ':') - { - if (hour >= 0 && min >= 0) /* already got it */ - break; - - /* We have seen "[0-9]+:", so this is probably HH:MM[:SS] */ - if ((end - rest) > 2) - /* it is [0-9][0-9][0-9]+: */ - break; - if ((end - rest) == 2) - tmp_hour = ((rest[0]-'0')*10 + - (rest[1]-'0')); - else - tmp_hour = (rest[0]-'0'); - - /* move over the colon, and parse minutes */ - - rest = ++end; - while (*end >= '0' && *end <= '9') - end++; - - if (end == rest) - /* no digits after first colon? */ - break; - if ((end - rest) > 2) - /* it is [0-9][0-9][0-9]+: */ - break; - if ((end - rest) == 2) - tmp_min = ((rest[0]-'0')*10 + - (rest[1]-'0')); - else - tmp_min = (rest[0]-'0'); - - /* now go for seconds */ - rest = end; - if (*rest == ':') - rest++; - end = rest; - while (*end >= '0' && *end <= '9') - end++; - - if (end == rest) - /* no digits after second colon - that's ok. */ - ; - else if ((end - rest) > 2) - /* it is [0-9][0-9][0-9]+: */ - break; - if ((end - rest) == 2) - tmp_sec = ((rest[0]-'0')*10 + - (rest[1]-'0')); - else - tmp_sec = (rest[0]-'0'); - - /* If we made it here, we've parsed hour and min, - and possibly sec, so it worked as a unit. */ - - /* skip over whitespace and see if there's an AM or PM - directly following the time. - */ - if (tmp_hour <= 12) - { - const char *s = end; - while (*s && (*s == ' ' || *s == '\t')) - s++; - if ((s[0] == 'p' || s[0] == 'P') && - (s[1] == 'm' || s[1] == 'M')) - /* 10:05pm == 22:05, and 12:05pm == 12:05 */ - tmp_hour = (tmp_hour == 12 ? 12 : tmp_hour + 12); - else if (tmp_hour == 12 && - (s[0] == 'a' || s[0] == 'A') && - (s[1] == 'm' || s[1] == 'M')) - /* 12:05am == 00:05 */ - tmp_hour = 0; - } - - hour = tmp_hour; - min = tmp_min; - sec = tmp_sec; - rest = end; - break; - } - if ((*end == '/' || *end == '-') && - end[1] >= '0' && end[1] <= '9') - { - /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 - or even 95-06-05... - #### But it doesn't handle 1995-06-22. - */ - int n1, n2, n3; - const char *s; - - if (month != TT_UNKNOWN) - /* if we saw a month name, this can't be. */ - break; - - s = rest; - - n1 = (*s++ - '0'); /* first 1 or 2 digits */ - if (*s >= '0' && *s <= '9') - n1 = n1*10 + (*s++ - '0'); - - if (*s != '/' && *s != '-') /* slash */ - break; - s++; - - if (*s < '0' || *s > '9') /* second 1 or 2 digits */ - break; - n2 = (*s++ - '0'); - if (*s >= '0' && *s <= '9') - n2 = n2*10 + (*s++ - '0'); - - if (*s != '/' && *s != '-') /* slash */ - break; - s++; - - if (*s < '0' || *s > '9') /* third 1, 2, 4, or 5 digits */ - break; - n3 = (*s++ - '0'); - if (*s >= '0' && *s <= '9') - n3 = n3*10 + (*s++ - '0'); - - if (*s >= '0' && *s <= '9') /* optional digits 3, 4, and 5 */ - { - n3 = n3*10 + (*s++ - '0'); - if (*s < '0' || *s > '9') - break; - n3 = n3*10 + (*s++ - '0'); - if (*s >= '0' && *s <= '9') - n3 = n3*10 + (*s++ - '0'); - } - - if ((*s >= '0' && *s <= '9') || /* followed by non-alphanum */ - (*s >= 'A' && *s <= 'Z') || - (*s >= 'a' && *s <= 'z')) - break; - - /* Ok, we parsed three 1-2 digit numbers, with / or - - between them. Now decide what the hell they are - (DD/MM/YY or MM/DD/YY or YY/MM/DD.) - */ - - if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */ - { - if (n2 > 12) break; - if (n3 > 31) break; - year = n1; - if (year < 70) - year += 2000; - else if (year < 100) - year += 1900; - month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); - date = n3; - rest = s; - break; - } - - if (n1 > 12 && n2 > 12) /* illegal */ - { - rest = s; - break; - } - - if (n3 < 70) - n3 += 2000; - else if (n3 < 100) - n3 += 1900; - - if (n1 > 12) /* must be DD/MM/YY */ - { - date = n1; - month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); - year = n3; - } - else /* assume MM/DD/YY */ - { - /* #### In the ambiguous case, should we consult the - locale to find out the local default? */ - month = (TIME_TOKEN)(n1 + ((int)TT_JAN) - 1); - date = n2; - year = n3; - } - rest = s; - } - else if ((*end >= 'A' && *end <= 'Z') || - (*end >= 'a' && *end <= 'z')) - /* Digits followed by non-punctuation - what's that? */ - ; - else if ((end - rest) == 5) /* five digits is a year */ - year = (year < 0 - ? ((rest[0]-'0')*10000L + - (rest[1]-'0')*1000L + - (rest[2]-'0')*100L + - (rest[3]-'0')*10L + - (rest[4]-'0')) - : year); - else if ((end - rest) == 4) /* four digits is a year */ - year = (year < 0 - ? ((rest[0]-'0')*1000L + - (rest[1]-'0')*100L + - (rest[2]-'0')*10L + - (rest[3]-'0')) - : year); - else if ((end - rest) == 2) /* two digits - date or year */ - { - int n = ((rest[0]-'0')*10 + - (rest[1]-'0')); - /* If we don't have a date (day of the month) and we see a number - less than 32, then assume that is the date. - - Otherwise, if we have a date and not a year, assume this is the - year. If it is less than 70, then assume it refers to the 21st - century. If it is two digits (>= 70), assume it refers to this - century. Otherwise, assume it refers to an unambiguous year. - - The world will surely end soon. - */ - if (date < 0 && n < 32) - date = n; - else if (year < 0) - { - if (n < 70) - year = 2000 + n; - else if (n < 100) - year = 1900 + n; - else - year = n; - } - /* else what the hell is this. */ - } - else if ((end - rest) == 1) /* one digit - date */ - date = (date < 0 ? (rest[0]-'0') : date); - /* else, three or more than five digits - what's that? */ + } + if ((end - rest) == 2) + tmp_min = ((rest[0]-'0')*10 + + (rest[1]-'0')); + else { + tmp_min = (rest[0]-'0'); + } + /* now go for seconds */ + rest = end; + if (*rest == ':') { + rest++; + } + end = rest; + while (*end >= '0' && *end <= '9') { + end++; + } + + if (end == rest) + /* no digits after second colon - that's ok. */ + ; + else if ((end - rest) > 2) + /* it is [0-9][0-9][0-9]+: */ + { break; - } + } + if ((end - rest) == 2) + tmp_sec = ((rest[0]-'0')*10 + + (rest[1]-'0')); + else { + tmp_sec = (rest[0]-'0'); + } + + /* If we made it here, we've parsed hour and min, + and possibly sec, so it worked as a unit. */ + + /* skip over whitespace and see if there's an AM or PM + directly following the time. + */ + if (tmp_hour <= 12) + { + const char *s = end; + while (*s && (*s == ' ' || *s == '\t')) { + s++; + } + if ((s[0] == 'p' || s[0] == 'P') && + (s[1] == 'm' || s[1] == 'M')) + /* 10:05pm == 22:05, and 12:05pm == 12:05 */ + { + tmp_hour = (tmp_hour == 12 ? 12 : tmp_hour + 12); + } + else if (tmp_hour == 12 && + (s[0] == 'a' || s[0] == 'A') && + (s[1] == 'm' || s[1] == 'M')) + /* 12:05am == 00:05 */ + { + tmp_hour = 0; + } + } + + hour = tmp_hour; + min = tmp_min; + sec = tmp_sec; + rest = end; + break; } + if ((*end == '/' || *end == '-') && + end[1] >= '0' && end[1] <= '9') + { + /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 + or even 95-06-05... + #### But it doesn't handle 1995-06-22. + */ + int n1, n2, n3; + const char *s; + + if (month != TT_UNKNOWN) + /* if we saw a month name, this can't be. */ + { + break; + } + + s = rest; + + n1 = (*s++ - '0'); /* first 1 or 2 digits */ + if (*s >= '0' && *s <= '9') { + n1 = n1*10 + (*s++ - '0'); + } + + if (*s != '/' && *s != '-') { /* slash */ + break; + } + s++; + + if (*s < '0' || *s > '9') { /* second 1 or 2 digits */ + break; + } + n2 = (*s++ - '0'); + if (*s >= '0' && *s <= '9') { + n2 = n2*10 + (*s++ - '0'); + } + + if (*s != '/' && *s != '-') { /* slash */ + break; + } + s++; + + if (*s < '0' || *s > '9') { /* third 1, 2, 4, or 5 digits */ + break; + } + n3 = (*s++ - '0'); + if (*s >= '0' && *s <= '9') { + n3 = n3*10 + (*s++ - '0'); + } + + if (*s >= '0' && *s <= '9') /* optional digits 3, 4, and 5 */ + { + n3 = n3*10 + (*s++ - '0'); + if (*s < '0' || *s > '9') { + break; + } + n3 = n3*10 + (*s++ - '0'); + if (*s >= '0' && *s <= '9') { + n3 = n3*10 + (*s++ - '0'); + } + } + + if ((*s >= '0' && *s <= '9') || /* followed by non-alphanum */ + (*s >= 'A' && *s <= 'Z') || + (*s >= 'a' && *s <= 'z')) { + break; + } + + /* Ok, we parsed three 1-2 digit numbers, with / or - + between them. Now decide what the hell they are + (DD/MM/YY or MM/DD/YY or YY/MM/DD.) + */ + + if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */ + { + if (n2 > 12) { + break; + } + if (n3 > 31) { + break; + } + year = n1; + if (year < 70) { + year += 2000; + } + else if (year < 100) { + year += 1900; + } + month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); + date = n3; + rest = s; + break; + } + + if (n1 > 12 && n2 > 12) /* illegal */ + { + rest = s; + break; + } - /* Skip to the end of this token, whether we parsed it or not. - Tokens are delimited by whitespace, or ,;-/ - But explicitly not :+-. - */ - while (*rest && - *rest != ' ' && *rest != '\t' && - *rest != ',' && *rest != ';' && - *rest != '-' && *rest != '+' && - *rest != '/' && - *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']') - rest++; - /* skip over uninteresting chars. */ - SKIP_MORE: - while (*rest && - (*rest == ' ' || *rest == '\t' || - *rest == ',' || *rest == ';' || *rest == '/' || - *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']')) - rest++; - - /* "-" is ignored at the beginning of a token if we have not yet - parsed a year (e.g., the second "-" in "30-AUG-1966"), or if - the character after the dash is not a digit. */ - if (*rest == '-' && ((rest > string && - isalpha((unsigned char)rest[-1]) && year < 0) || - rest[1] < '0' || rest[1] > '9')) + if (n3 < 70) { + n3 += 2000; + } + else if (n3 < 100) { + n3 += 1900; + } + + if (n1 > 12) /* must be DD/MM/YY */ + { + date = n1; + month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); + year = n3; + } + else /* assume MM/DD/YY */ + { + /* #### In the ambiguous case, should we consult the + locale to find out the local default? */ + month = (TIME_TOKEN)(n1 + ((int)TT_JAN) - 1); + date = n2; + year = n3; + } + rest = s; + } + else if ((*end >= 'A' && *end <= 'Z') || + (*end >= 'a' && *end <= 'z')) + /* Digits followed by non-punctuation - what's that? */ + ; + else if ((end - rest) == 5) /* five digits is a year */ + year = (year < 0 + ? ((rest[0]-'0')*10000L + + (rest[1]-'0')*1000L + + (rest[2]-'0')*100L + + (rest[3]-'0')*10L + + (rest[4]-'0')) + : year); + else if ((end - rest) == 4) /* four digits is a year */ + year = (year < 0 + ? ((rest[0]-'0')*1000L + + (rest[1]-'0')*100L + + (rest[2]-'0')*10L + + (rest[3]-'0')) + : year); + else if ((end - rest) == 2) /* two digits - date or year */ { - rest++; - goto SKIP_MORE; + int n = ((rest[0]-'0')*10 + + (rest[1]-'0')); + /* If we don't have a date (day of the month) and we see a number + less than 32, then assume that is the date. + + Otherwise, if we have a date and not a year, assume this is the + year. If it is less than 70, then assume it refers to the 21st + century. If it is two digits (>= 70), assume it refers to this + century. Otherwise, assume it refers to an unambiguous year. + + The world will surely end soon. + */ + if (date < 0 && n < 32) { + date = n; + } + else if (year < 0) + { + if (n < 70) { + year = 2000 + n; + } + else if (n < 100) { + year = 1900 + n; + } + else { + year = n; + } + } + /* else what the hell is this. */ } + else if ((end - rest) == 1) { /* one digit - date */ + date = (date < 0 ? (rest[0]-'0') : date); + } + /* else, three or more than five digits - what's that? */ + + break; + } + } + /* Skip to the end of this token, whether we parsed it or not. + Tokens are delimited by whitespace, or ,;-/ + But explicitly not :+-. + */ + while (*rest && + *rest != ' ' && *rest != '\t' && + *rest != ',' && *rest != ';' && + *rest != '-' && *rest != '+' && + *rest != '/' && + *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']') { + rest++; + } + /* skip over uninteresting chars. */ +SKIP_MORE: + while (*rest && + (*rest == ' ' || *rest == '\t' || + *rest == ',' || *rest == ';' || *rest == '/' || + *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']')) { + rest++; } - if (zone != TT_UNKNOWN && zone_offset == -1) + /* "-" is ignored at the beginning of a token if we have not yet + parsed a year (e.g., the second "-" in "30-AUG-1966"), or if + the character after the dash is not a digit. */ + if (*rest == '-' && ((rest > string && + isalpha((unsigned char)rest[-1]) && year < 0) || + rest[1] < '0' || rest[1] > '9')) { - switch (zone) - { - case TT_PST: zone_offset = -8 * 60; break; - case TT_PDT: zone_offset = -8 * 60; dst_offset = 1 * 60; break; - case TT_MST: zone_offset = -7 * 60; break; - case TT_MDT: zone_offset = -7 * 60; dst_offset = 1 * 60; break; - case TT_CST: zone_offset = -6 * 60; break; - case TT_CDT: zone_offset = -6 * 60; dst_offset = 1 * 60; break; - case TT_EST: zone_offset = -5 * 60; break; - case TT_EDT: zone_offset = -5 * 60; dst_offset = 1 * 60; break; - case TT_AST: zone_offset = -4 * 60; break; - case TT_NST: zone_offset = -3 * 60 - 30; break; - case TT_GMT: zone_offset = 0 * 60; break; - case TT_BST: zone_offset = 0 * 60; dst_offset = 1 * 60; break; - case TT_MET: zone_offset = 1 * 60; break; - case TT_EET: zone_offset = 2 * 60; break; - case TT_JST: zone_offset = 9 * 60; break; - default: - PR_ASSERT (0); - break; - } + rest++; + goto SKIP_MORE; + } + + } + + if (zone != TT_UNKNOWN && zone_offset == -1) + { + switch (zone) + { + case TT_PST: zone_offset = -8 * 60; break; + case TT_PDT: zone_offset = -8 * 60; dst_offset = 1 * 60; break; + case TT_MST: zone_offset = -7 * 60; break; + case TT_MDT: zone_offset = -7 * 60; dst_offset = 1 * 60; break; + case TT_CST: zone_offset = -6 * 60; break; + case TT_CDT: zone_offset = -6 * 60; dst_offset = 1 * 60; break; + case TT_EST: zone_offset = -5 * 60; break; + case TT_EDT: zone_offset = -5 * 60; dst_offset = 1 * 60; break; + case TT_AST: zone_offset = -4 * 60; break; + case TT_NST: zone_offset = -3 * 60 - 30; break; + case TT_GMT: zone_offset = 0 * 60; break; + case TT_BST: zone_offset = 0 * 60; dst_offset = 1 * 60; break; + case TT_MET: zone_offset = 1 * 60; break; + case TT_EET: zone_offset = 2 * 60; break; + case TT_JST: zone_offset = 9 * 60; break; + default: + PR_ASSERT (0); + break; } + } - /* If we didn't find a year, month, or day-of-the-month, we can't - possibly parse this, and in fact, mktime() will do something random - (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt - a numerologically significant date... */ - if (month == TT_UNKNOWN || date == -1 || year == -1 || year > PR_INT16_MAX) - return PR_FAILURE; + /* If we didn't find a year, month, or day-of-the-month, we can't + possibly parse this, and in fact, mktime() will do something random + (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt + a numerologically significant date... */ + if (month == TT_UNKNOWN || date == -1 || year == -1 || year > PR_INT16_MAX) { + return PR_FAILURE; + } - memset(result, 0, sizeof(*result)); - if (sec != -1) + memset(result, 0, sizeof(*result)); + if (sec != -1) { result->tm_sec = sec; - if (min != -1) + } + if (min != -1) { result->tm_min = min; - if (hour != -1) + } + if (hour != -1) { result->tm_hour = hour; - if (date != -1) + } + if (date != -1) { result->tm_mday = date; - if (month != TT_UNKNOWN) + } + if (month != TT_UNKNOWN) { result->tm_month = (((int)month) - ((int)TT_JAN)); - if (year != -1) + } + if (year != -1) { result->tm_year = year; - if (dotw != TT_UNKNOWN) + } + if (dotw != TT_UNKNOWN) { result->tm_wday = (((int)dotw) - ((int)TT_SUN)); - /* - * Mainly to compute wday and yday, but normalized time is also required - * by the check below that works around a Visual C++ 2005 mktime problem. - */ - PR_NormalizeTime(result, PR_GMTParameters); - /* The remaining work is to set the gmt and dst offsets in tm_params. */ - - if (zone == TT_UNKNOWN && default_to_gmt) - { - /* No zone was specified, so pretend the zone was GMT. */ - zone = TT_GMT; - zone_offset = 0; - } + } + /* + * Mainly to compute wday and yday, but normalized time is also required + * by the check below that works around a Visual C++ 2005 mktime problem. + */ + PR_NormalizeTime(result, PR_GMTParameters); + /* The remaining work is to set the gmt and dst offsets in tm_params. */ + + if (zone == TT_UNKNOWN && default_to_gmt) + { + /* No zone was specified, so pretend the zone was GMT. */ + zone = TT_GMT; + zone_offset = 0; + } - if (zone_offset == -1) - { - /* no zone was specified, and we're to assume that everything - is local. */ - struct tm localTime; - time_t secs; + if (zone_offset == -1) + { + /* no zone was specified, and we're to assume that everything + is local. */ + struct tm localTime; + time_t secs; - PR_ASSERT(result->tm_month > -1 && - result->tm_mday > 0 && - result->tm_hour > -1 && - result->tm_min > -1 && - result->tm_sec > -1); + PR_ASSERT(result->tm_month > -1 && + result->tm_mday > 0 && + result->tm_hour > -1 && + result->tm_min > -1 && + result->tm_sec > -1); - /* - * To obtain time_t from a tm structure representing the local - * time, we call mktime(). However, we need to see if we are - * on 1-Jan-1970 or before. If we are, we can't call mktime() - * because mktime() will crash on win16. In that case, we - * calculate zone_offset based on the zone offset at - * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the - * date we are parsing to transform the date to GMT. We also - * do so if mktime() returns (time_t) -1 (time out of range). - */ - - /* month, day, hours, mins and secs are always non-negative - so we dont need to worry about them. */ - if(result->tm_year >= 1970) - { - PRInt64 usec_per_sec; - - localTime.tm_sec = result->tm_sec; - localTime.tm_min = result->tm_min; - localTime.tm_hour = result->tm_hour; - localTime.tm_mday = result->tm_mday; - localTime.tm_mon = result->tm_month; - localTime.tm_year = result->tm_year - 1900; - /* Set this to -1 to tell mktime "I don't care". If you set - it to 0 or 1, you are making assertions about whether the - date you are handing it is in daylight savings mode or not; - and if you're wrong, it will "fix" it for you. */ - localTime.tm_isdst = -1; + /* + * To obtain time_t from a tm structure representing the local + * time, we call mktime(). However, we need to see if we are + * on 1-Jan-1970 or before. If we are, we can't call mktime() + * because mktime() will crash on win16. In that case, we + * calculate zone_offset based on the zone offset at + * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the + * date we are parsing to transform the date to GMT. We also + * do so if mktime() returns (time_t) -1 (time out of range). + */ + + /* month, day, hours, mins and secs are always non-negative + so we dont need to worry about them. */ + if(result->tm_year >= 1970) + { + PRInt64 usec_per_sec; + + localTime.tm_sec = result->tm_sec; + localTime.tm_min = result->tm_min; + localTime.tm_hour = result->tm_hour; + localTime.tm_mday = result->tm_mday; + localTime.tm_mon = result->tm_month; + localTime.tm_year = result->tm_year - 1900; + /* Set this to -1 to tell mktime "I don't care". If you set + it to 0 or 1, you are making assertions about whether the + date you are handing it is in daylight savings mode or not; + and if you're wrong, it will "fix" it for you. */ + localTime.tm_isdst = -1; #if _MSC_VER == 1400 /* 1400 = Visual C++ 2005 (8.0) */ - /* - * mktime will return (time_t) -1 if the input is a date - * after 23:59:59, December 31, 3000, US Pacific Time (not - * UTC as documented): - * http://msdn.microsoft.com/en-us/library/d1y53h2a(VS.80).aspx - * But if the year is 3001, mktime also invokes the invalid - * parameter handler, causing the application to crash. This - * problem has been reported in - * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=266036. - * We avoid this crash by not calling mktime if the date is - * out of range. To use a simple test that works in any time - * zone, we consider year 3000 out of range as well. (See - * bug 480740.) - */ - if (result->tm_year >= 3000) { - /* Emulate what mktime would have done. */ - errno = EINVAL; - secs = (time_t) -1; - } else { - secs = mktime(&localTime); - } + /* + * mktime will return (time_t) -1 if the input is a date + * after 23:59:59, December 31, 3000, US Pacific Time (not + * UTC as documented): + * http://msdn.microsoft.com/en-us/library/d1y53h2a(VS.80).aspx + * But if the year is 3001, mktime also invokes the invalid + * parameter handler, causing the application to crash. This + * problem has been reported in + * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=266036. + * We avoid this crash by not calling mktime if the date is + * out of range. To use a simple test that works in any time + * zone, we consider year 3000 out of range as well. (See + * bug 480740.) + */ + if (result->tm_year >= 3000) { + /* Emulate what mktime would have done. */ + errno = EINVAL; + secs = (time_t) -1; + } else { + secs = mktime(&localTime); + } #else - secs = mktime(&localTime); + secs = mktime(&localTime); #endif - if (secs != (time_t) -1) - { - PRTime usecs64; - LL_I2L(usecs64, secs); - LL_I2L(usec_per_sec, PR_USEC_PER_SEC); - LL_MUL(usecs64, usecs64, usec_per_sec); - PR_ExplodeTime(usecs64, PR_LocalTimeParameters, result); - return PR_SUCCESS; - } - } - - /* So mktime() can't handle this case. We assume the - zone_offset for the date we are parsing is the same as - the zone offset on 00:00:00 2 Jan 1970 GMT. */ - secs = 86400; - localTimeResult = MT_safe_localtime(&secs, &localTime); - PR_ASSERT(localTimeResult != NULL); - if (localTimeResult == NULL) { - return PR_FAILURE; - } - zone_offset = localTime.tm_min - + 60 * localTime.tm_hour - + 1440 * (localTime.tm_mday - 2); + if (secs != (time_t) -1) + { + PRTime usecs64; + LL_I2L(usecs64, secs); + LL_I2L(usec_per_sec, PR_USEC_PER_SEC); + LL_MUL(usecs64, usecs64, usec_per_sec); + PR_ExplodeTime(usecs64, PR_LocalTimeParameters, result); + return PR_SUCCESS; + } } - result->tm_params.tp_gmt_offset = zone_offset * 60; - result->tm_params.tp_dst_offset = dst_offset * 60; + /* So mktime() can't handle this case. We assume the + zone_offset for the date we are parsing is the same as + the zone offset on 00:00:00 2 Jan 1970 GMT. */ + secs = 86400; + localTimeResult = MT_safe_localtime(&secs, &localTime); + PR_ASSERT(localTimeResult != NULL); + if (localTimeResult == NULL) { + return PR_FAILURE; + } + zone_offset = localTime.tm_min + + 60 * localTime.tm_hour + + 1440 * (localTime.tm_mday - 2); + } - return PR_SUCCESS; + result->tm_params.tp_gmt_offset = zone_offset * 60; + result->tm_params.tp_dst_offset = dst_offset * 60; + + return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_ParseTimeString( - const char *string, - PRBool default_to_gmt, - PRTime *result) + const char *string, + PRBool default_to_gmt, + PRTime *result) { - PRExplodedTime tm; - PRStatus rv; + PRExplodedTime tm; + PRStatus rv; - rv = PR_ParseTimeStringToExplodedTime(string, - default_to_gmt, - &tm); - if (rv != PR_SUCCESS) + rv = PR_ParseTimeStringToExplodedTime(string, + default_to_gmt, + &tm); + if (rv != PR_SUCCESS) { return rv; + } - *result = PR_ImplodeTime(&tm); + *result = PR_ImplodeTime(&tm); - return PR_SUCCESS; + return PR_SUCCESS; } /* @@ -1720,9 +1835,9 @@ PR_FormatTime(char *buf, int buflen, const char *fmt, * additional fields: tm_zone and tm_gmtoff. */ -#if (__GLIBC__ >= 2) || defined(XP_BEOS) \ - || defined(NETBSD) || defined(OPENBSD) || defined(FREEBSD) \ - || defined(DARWIN) || defined(SYMBIAN) || defined(ANDROID) +#if (__GLIBC__ >= 2) || defined(NETBSD) \ + || defined(OPENBSD) || defined(FREEBSD) \ + || defined(DARWIN) || defined(ANDROID) a.tm_zone = NULL; a.tm_gmtoff = time->tm_params.tp_gmt_offset + time->tm_params.tp_dst_offset; @@ -1750,22 +1865,22 @@ PR_FormatTime(char *buf, int buflen, const char *fmt, static const char* abbrevDays[] = { - "Sun","Mon","Tue","Wed","Thu","Fri","Sat" + "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; static const char* days[] = { - "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" + "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" }; static const char* abbrevMonths[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static const char* months[] = -{ +{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; @@ -1813,7 +1928,7 @@ while(0) /* Needed by PR_FormatTimeUSEnglish() */ static unsigned int pr_WeekOfYear(const PRExplodedTime* time, - unsigned int firstDayOfWeek); + unsigned int firstDayOfWeek); /*********************************************************************************** @@ -1824,169 +1939,169 @@ static unsigned int pr_WeekOfYear(const PRExplodedTime* time, * needed to write things like MIME headers which must always be in US English. * **********************************************************************************/ - + PR_IMPLEMENT(PRUint32) PR_FormatTimeUSEnglish( char* buf, PRUint32 bufSize, const char* format, const PRExplodedTime* time ) { - char* bufPtr = buf; - const char* fmtPtr; - char tmpBuf[ 40 ]; - const int tmpBufSize = sizeof( tmpBuf ); - - - for( fmtPtr=format; *fmtPtr != '\0'; fmtPtr++ ) - { - if( *fmtPtr != '%' ) - { - ADDCHAR( bufPtr, bufSize, *fmtPtr ); - } - else - { - switch( *(++fmtPtr) ) - { - case '%': - /* escaped '%' character */ - ADDCHAR( bufPtr, bufSize, '%' ); - break; - - case 'a': - /* abbreviated weekday name */ - ADDSTR( bufPtr, bufSize, abbrevDays[ time->tm_wday ] ); - break; - - case 'A': - /* full weekday name */ - ADDSTR( bufPtr, bufSize, days[ time->tm_wday ] ); - break; - - case 'b': - /* abbreviated month name */ - ADDSTR( bufPtr, bufSize, abbrevMonths[ time->tm_month ] ); - break; - - case 'B': - /* full month name */ - ADDSTR(bufPtr, bufSize, months[ time->tm_month ] ); - break; - - case 'c': - /* Date and time. */ - PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%a %b %d %H:%M:%S %Y", time ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'd': - /* day of month ( 01 - 31 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_mday ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'H': - /* hour ( 00 - 23 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_hour ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'I': - /* hour ( 01 - 12 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2ld", - (time->tm_hour%12) ? time->tm_hour%12 : (PRInt32) 12 ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'j': - /* day number of year ( 001 - 366 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.3d",time->tm_yday + 1); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'm': - /* month number ( 01 - 12 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_month+1); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'M': - /* minute ( 00 - 59 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_min ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'p': - /* locale's equivalent of either AM or PM */ - ADDSTR( bufPtr, bufSize, (time->tm_hour<12)?"AM":"PM" ); - break; - - case 'S': - /* seconds ( 00 - 61 ), allows for leap seconds */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_sec ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'U': - /* week number of year ( 00 - 53 ), Sunday is the first day of week 1 */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 0 ) ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'w': - /* weekday number ( 0 - 6 ), Sunday = 0 */ - PR_snprintf(tmpBuf,tmpBufSize,"%d",time->tm_wday ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'W': - /* Week number of year ( 00 - 53 ), Monday is the first day of week 1 */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 1 ) ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'x': - /* Date representation */ - PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%m/%d/%y", time ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'X': - /* Time representation. */ - PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%H:%M:%S", time ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'y': - /* year within century ( 00 - 99 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.2d",time->tm_year % 100 ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'Y': - /* year as ccyy ( for example 1986 ) */ - PR_snprintf(tmpBuf,tmpBufSize,"%.4d",time->tm_year ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; - - case 'Z': - /* Time zone name or no characters if no time zone exists. - * Since time zone name is supposed to be independant of locale, we - * defer to PR_FormatTime() for this option. - */ - PR_FormatTime( tmpBuf, tmpBufSize, "%Z", time ); - ADDSTR( bufPtr, bufSize, tmpBuf ); - break; + char* bufPtr = buf; + const char* fmtPtr; + char tmpBuf[ 40 ]; + const int tmpBufSize = sizeof( tmpBuf ); - default: - /* Unknown format. Simply copy format into output buffer. */ - ADDCHAR( bufPtr, bufSize, '%' ); + + for( fmtPtr=format; *fmtPtr != '\0'; fmtPtr++ ) + { + if( *fmtPtr != '%' ) + { ADDCHAR( bufPtr, bufSize, *fmtPtr ); - break; - - } - } - } - - ADDCHAR( bufPtr, bufSize, '\0' ); - return (PRUint32)(bufPtr - buf - 1); + } + else + { + switch( *(++fmtPtr) ) + { + case '%': + /* escaped '%' character */ + ADDCHAR( bufPtr, bufSize, '%' ); + break; + + case 'a': + /* abbreviated weekday name */ + ADDSTR( bufPtr, bufSize, abbrevDays[ time->tm_wday ] ); + break; + + case 'A': + /* full weekday name */ + ADDSTR( bufPtr, bufSize, days[ time->tm_wday ] ); + break; + + case 'b': + /* abbreviated month name */ + ADDSTR( bufPtr, bufSize, abbrevMonths[ time->tm_month ] ); + break; + + case 'B': + /* full month name */ + ADDSTR(bufPtr, bufSize, months[ time->tm_month ] ); + break; + + case 'c': + /* Date and time. */ + PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%a %b %d %H:%M:%S %Y", time ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'd': + /* day of month ( 01 - 31 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_mday ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'H': + /* hour ( 00 - 23 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_hour ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'I': + /* hour ( 01 - 12 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2ld", + (time->tm_hour%12) ? time->tm_hour%12 : (PRInt32) 12 ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'j': + /* day number of year ( 001 - 366 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.3d",time->tm_yday + 1); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'm': + /* month number ( 01 - 12 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_month+1); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'M': + /* minute ( 00 - 59 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_min ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'p': + /* locale's equivalent of either AM or PM */ + ADDSTR( bufPtr, bufSize, (time->tm_hour<12)?"AM":"PM" ); + break; + + case 'S': + /* seconds ( 00 - 61 ), allows for leap seconds */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_sec ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'U': + /* week number of year ( 00 - 53 ), Sunday is the first day of week 1 */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 0 ) ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'w': + /* weekday number ( 0 - 6 ), Sunday = 0 */ + PR_snprintf(tmpBuf,tmpBufSize,"%d",time->tm_wday ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'W': + /* Week number of year ( 00 - 53 ), Monday is the first day of week 1 */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 1 ) ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'x': + /* Date representation */ + PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%m/%d/%y", time ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'X': + /* Time representation. */ + PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%H:%M:%S", time ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'y': + /* year within century ( 00 - 99 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.2d",time->tm_year % 100 ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'Y': + /* year as ccyy ( for example 1986 ) */ + PR_snprintf(tmpBuf,tmpBufSize,"%.4d",time->tm_year ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + case 'Z': + /* Time zone name or no characters if no time zone exists. + * Since time zone name is supposed to be independant of locale, we + * defer to PR_FormatTime() for this option. + */ + PR_FormatTime( tmpBuf, tmpBufSize, "%Z", time ); + ADDSTR( bufPtr, bufSize, tmpBuf ); + break; + + default: + /* Unknown format. Simply copy format into output buffer. */ + ADDCHAR( bufPtr, bufSize, '%' ); + ADDCHAR( bufPtr, bufSize, *fmtPtr ); + break; + + } + } + } + + ADDCHAR( bufPtr, bufSize, '\0' ); + return (PRUint32)(bufPtr - buf - 1); } @@ -1997,38 +2112,39 @@ PR_FormatTimeUSEnglish( char* buf, PRUint32 bufSize, * Returns the week number of the year (0-53) for the given time. firstDayOfWeek * is the day on which the week is considered to start (0=Sun, 1=Mon, ...). * Week 1 starts the first time firstDayOfWeek occurs in the year. In other words, - * a partial week at the start of the year is considered week 0. + * a partial week at the start of the year is considered week 0. * **********************************************************************************/ static unsigned int pr_WeekOfYear(const PRExplodedTime* time, unsigned int firstDayOfWeek) { - int dayOfWeek; - int dayOfYear; - - /* Get the day of the year for the given time then adjust it to represent the - * first day of the week containing the given time. - */ - dayOfWeek = time->tm_wday - firstDayOfWeek; - if (dayOfWeek < 0) - dayOfWeek += 7; - - dayOfYear = time->tm_yday - dayOfWeek; - - if( dayOfYear <= 0 ) - { - /* If dayOfYear is <= 0, it is in the first partial week of the year. */ - return 0; - } - - /* Count the number of full weeks ( dayOfYear / 7 ) then add a week if there - * are any days left over ( dayOfYear % 7 ). Because we are only counting to - * the first day of the week containing the given time, rather than to the - * actual day representing the given time, any days in week 0 will be "absorbed" - * as extra days in the given week. - */ - return (dayOfYear / 7) + ( (dayOfYear % 7) == 0 ? 0 : 1 ); + int dayOfWeek; + int dayOfYear; + + /* Get the day of the year for the given time then adjust it to represent the + * first day of the week containing the given time. + */ + dayOfWeek = time->tm_wday - firstDayOfWeek; + if (dayOfWeek < 0) { + dayOfWeek += 7; + } + + dayOfYear = time->tm_yday - dayOfWeek; + + if( dayOfYear <= 0 ) + { + /* If dayOfYear is <= 0, it is in the first partial week of the year. */ + return 0; + } + + /* Count the number of full weeks ( dayOfYear / 7 ) then add a week if there + * are any days left over ( dayOfYear % 7 ). Because we are only counting to + * the first day of the week containing the given time, rather than to the + * actual day representing the given time, any days in week 0 will be "absorbed" + * as extra days in the given week. + */ + return (dayOfYear / 7) + ( (dayOfYear % 7) == 0 ? 0 : 1 ); } |