📄 prtime.c
字号:
} time->tm_mday = nDays[IsLeapYear(time->tm_year)][time->tm_month]; } time->tm_wday--; 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]) { time->tm_mday = 1; time->tm_month++; if (time->tm_month > 11) { time->tm_month = 0; time->tm_year++; time->tm_yday = 0; } } time->tm_wday++; if (time->tm_wday > 6) time->tm_wday = 0; }}PR_IMPLEMENT(void)PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params){ int daysInMonth; PRInt32 fourYears; PRInt32 remainder; PRInt32 numDays; /* Get back to GMT */ time->tm_sec -= time->tm_params.tp_gmt_offset + time->tm_params.tp_dst_offset; time->tm_params.tp_gmt_offset = 0; time->tm_params.tp_dst_offset = 0; /* Now normalize GMT */ if (time->tm_usec < 0 || time->tm_usec >= 1000000) { time->tm_sec += time->tm_usec / 1000000; time->tm_usec %= 1000000; if (time->tm_usec < 0) { time->tm_usec += 1000000; time->tm_sec--; } } /* Note that we do not count leap seconds in this implementation */ if (time->tm_sec < 0 || time->tm_sec >= 60) { time->tm_min += time->tm_sec / 60; time->tm_sec %= 60; if (time->tm_sec < 0) { time->tm_sec += 60; time->tm_min--; } } if (time->tm_min < 0 || time->tm_min >= 60) { time->tm_hour += time->tm_min / 60; time->tm_min %= 60; if (time->tm_min < 0) { time->tm_min += 60; time->tm_hour--; } } if (time->tm_hour < 0 || time->tm_hour >= 24) { time->tm_mday += time->tm_hour / 24; time->tm_hour %= 24; if (time->tm_hour < 0) { time->tm_hour += 24; time->tm_mday--; } } /* Normalize month and year before mday */ if (time->tm_month < 0 || time->tm_month >= 12) { time->tm_year += time->tm_month / 12; time->tm_month %= 12; if (time->tm_month < 0) { time->tm_month += 12; time->tm_year--; } } /* Now that month and year are in proper range, normalize mday */ if (time->tm_mday < 1) { /* mday too small */ do { /* the previous month */ time->tm_month--; if (time->tm_month < 0) { time->tm_month = 11; time->tm_year--; } time->tm_mday += nDays[IsLeapYear(time->tm_year)][time->tm_month]; } while (time->tm_mday < 1); } else { daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; while (time->tm_mday > daysInMonth) { /* mday too large */ time->tm_mday -= daysInMonth; time->tm_month++; if (time->tm_month > 11) { time->tm_month = 0; time->tm_year++; } daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; } } /* Recompute yday and wday */ time->tm_yday = time->tm_mday + lastDayOfMonth[IsLeapYear(time->tm_year)][time->tm_month]; fourYears = (time->tm_year - 1970) / 4; remainder = (time->tm_year - 1970) % 4; if (remainder < 0) { remainder += 4; fourYears--; } numDays = fourYears * (4 * 365 + 1); switch (remainder) { case 0: break; case 1: numDays += 365; /* 1970 */ break; case 2: numDays += 365 + 365; /* 1970 and 1971 */ break; case 3: numDays += 365 + 365 + 366; /* 1970-2 */ } numDays += time->tm_yday; time->tm_wday = (numDays + 4) % 7; if (time->tm_wday < 0) { time->tm_wday += 7; } /* Recompute time parameters */ time->tm_params = params(time); ApplySecOffset(time, time->tm_params.tp_gmt_offset + time->tm_params.tp_dst_offset);}/* *------------------------------------------------------------------------- * * PR_LocalTimeParameters -- * * returns the time parameters for the local time zone * * The following uses localtime() from the standard C library. * (time.h) This is our fallback implementation. Unix and PC * use this version. Mac has its own machine-dependent * implementation of this function. * *------------------------------------------------------------------------- */#include <time.h>#if defined(HAVE_INT_LOCALTIME_R)/* * 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 * 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 * with 0. */#define MT_safe_localtime(timer, result) \ (localtime_r(timer, result) == -1 ? NULL: result)#elif defined(HAVE_POINTER_LOCALTIME_R)#define MT_safe_localtime localtime_r#else#if defined(XP_MAC)extern struct tm *Maclocaltime(const time_t * t);#endifstatic PRLock *monitor = NULL;static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result){ struct tm *tmPtr; 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) { if (monitor == NULL) { monitor = PR_NewLock(); } PR_Lock(monitor); } /* * Microsoft (all flavors) localtime() returns a NULL pointer if 'clock' * represents a time before midnight January 1, 1970. In * that case, we also return a NULL pointer and the struct tm * object pointed to by 'result' is not modified. * * Watcom C/C++ 11.0 localtime() treats time_t as unsigned long * hence, does not recognize negative values of clock as pre-1/1/70. * We have to manually check (WIN16 only) for negative value of * clock and return NULL. * * With negative values of clock, emx returns the struct tm for * clock plus ULONG_MAX. So we also have to check for the invalid * structs returned for timezones west of Greenwich when clock == 0. */ #if defined(XP_MAC) tmPtr = Maclocaltime(clock);#else tmPtr = localtime(clock);#endif#if defined(WIN16) || defined(XP_OS2_EMX) if ( (PRInt32) *clock < 0 || ( (PRInt32) *clock == 0 && tmPtr->tm_year != 70)) result = NULL; else *result = *tmPtr;#else if (tmPtr) { *result = *tmPtr; } else { result = NULL; }#endif /* WIN16 */ if (needLock) PR_Unlock(monitor); return result;}#endif /* definition of MT_safe_localtime() */#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS)PR_IMPLEMENT(PRTimeParameters)PR_LocalTimeParameters(const PRExplodedTime *gmt){ PRTimeParameters retVal; struct tm localTime; time_t secs; PRTime secs64; PRInt64 usecPerSec; PRInt64 maxInt32; PRInt32 dayOffset; PRInt32 offset2Jan1970; PRInt32 offsetNew; int isdst2Jan1970; /* * Calculate the GMT offset. First, figure out what is * 00:00:00 Jan. 2, 1970 GMT (which is exactly a day, or 86400 * seconds, since the epoch) in local time. Then we calculate * the difference between local time and GMT in seconds: * gmt_offset = local_time - GMT * * Caveat: the validity of this calculation depends on two * assumptions: * 1. Daylight saving time was not in effect on Jan. 2, 1970. * 2. The time zone of the geographic location has not changed * since Jan. 2, 1970. */ secs = 86400L; (void) MT_safe_localtime(&secs, &localTime); /* 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); isdst2Jan1970 = localTime.tm_isdst; /* * Now compute DST offset. We calculate the overall offset * of local time from GMT, similar to above. The overall * offset has two components: gmt offset and dst offset. * We subtract gmt offset from the overall offset to get * the dst offset. * overall_offset = local_time - GMT * overall_offset = gmt_offset + dst_offset * ==> dst_offset = local_time - GMT - gmt_offset */ secs64 = PR_ImplodeTime(gmt); /* This is still in microseconds */ LL_I2L(usecPerSec, PR_USEC_PER_SEC); LL_DIV(secs64, secs64, usecPerSec); /* Convert to seconds */ LL_I2L(maxInt32, 0x7fffffff); if (LL_CMP(secs64, >, maxInt32)) { /* secs64 is too large for time_t (32-bit integer) */ retVal.tp_gmt_offset = offset2Jan1970; retVal.tp_dst_offset = 0; return retVal; } LL_L2I(secs, secs64); /* * On Windows, localtime() (and our MT_safe_localtime() too) * returns a NULL pointer for time before midnight January 1, * 1970 GMT. In that case, we just use the GMT offset for * Jan 2, 1970 and assume that DST was not in effect. */ if (MT_safe_localtime(&secs, &localTime) == NULL) { retVal.tp_gmt_offset = offset2Jan1970; retVal.tp_dst_offset = 0; return retVal; } /* * 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. */ dayOffset = (PRInt32) localTime.tm_wday - gmt->tm_wday; /* * Need to adjust for wrapping around of day of the week from * 6 back to 0. */ if (dayOffset == -6) { /* Local time is Sunday (0) and GMT is Saturday (6) */ dayOffset = 1; } else if (dayOffset == 6) { /* Local time is Saturday (6) and GMT is Sunday (0) */ dayOffset = -1; } 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; if (localTime.tm_isdst <= 0) { /* DST is not in effect */ retVal.tp_gmt_offset = offsetNew; retVal.tp_dst_offset = 0; } else { /* DST is in effect */ if (isdst2Jan1970 <=0) { /* * DST was not in effect back in 2 Jan. 1970. * Use the offset back then as the GMT offset,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -