struct tm *localtime_r(const time_t *t, struct tm *result) { __tzset(); __time_to_tm(*t - __timezone, result); result->tm_isdst = -1; return __dst_adjust(result); }
_CRTIMP errno_t __cdecl _ftime64_s ( struct __timeb64 *tp ) { FT nt_time; __time64_t t; TIME_ZONE_INFORMATION tzinfo; DWORD tzstate; long timezone = 0; _VALIDATE_RETURN_ERRCODE( ( tp != NULL ), EINVAL ) __tzset(); _ERRCHECK(_get_timezone(&timezone)); tp->timezone = (short)(timezone / 60); GetSystemTimeAsFileTime( &(nt_time.ft_struct) ); /* * Obtain the current DST status. Note the status is cached and only * updated once per minute, if necessary. */ if ( (t = (__time64_t)(nt_time.ft_scalar / 600000000i64)) != elapsed_minutes_cache ) { if ( (tzstate = GetTimeZoneInformation( &tzinfo )) != 0xFFFFFFFF ) { /* * Must be very careful in determining whether or not DST is * really in effect. */ if ( (tzstate == TIME_ZONE_ID_DAYLIGHT) && (tzinfo.DaylightDate.wMonth != 0) && (tzinfo.DaylightBias != 0) ) dstflag_cache = DAYLIGHT_TIME; else /* * When in doubt, assume standard time */ dstflag_cache = STANDARD_TIME; } else dstflag_cache = UNKNOWN_TIME; elapsed_minutes_cache = t; } tp->dstflag = (short)dstflag_cache; tp->millitm = (unsigned short)((nt_time.ft_scalar / 10000i64) % 1000i64); tp->time = (__time64_t)((nt_time.ft_scalar - EPOCH_BIAS) / 10000000i64); return 0; }
time_t mktime(struct tm *tm) { int isdst = tm->tm_isdst; time_t t, lt; __tzset(); tm->tm_sec += __timezone; if (isdst > 0) tm->tm_sec += __dst_offset; t = __tm_to_time(tm); lt = t - __timezone; if (isdst > 0) lt -= __dst_offset; __time_to_tm(lt, tm); __dst_adjust(tm); return t; }
static __time64_t __cdecl _make__time64_t ( struct tm *tb, int ultflag ) { __time64_t tmptm1, tmptm2, tmptm3; struct tm tbtemp; long dstbias = 0; long timezone = 0; _VALIDATE_RETURN( ( tb != NULL ), EINVAL, ( ( __time64_t )( -1 ) ) ) /* * First, make sure tm_year is reasonably close to being in range. */ if ( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; /* * Adjust month value so it is in the range 0 - 11. This is because * we don't know how many days are in months 12, 13, 14, etc. */ if ( (tb->tm_mon < 0) || (tb->tm_mon > 11) ) { tmptm1 += (tb->tm_mon / 12); if ( (tb->tm_mon %= 12) < 0 ) { tb->tm_mon += 12; tmptm1--; } /* * Make sure year count is still in range. */ if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed years *****/ /* * Calculate days elapsed minus one, in the given year, to the given * month. Check for leap year and adjust if necessary. */ tmptm2 = _days[tb->tm_mon]; if ( _IS_LEAP_YEAR(tmptm1) && (tb->tm_mon > 1) ) tmptm2++; /* * Calculate elapsed days since base date (midnight, 1/1/70, UTC) * * * 365 days for each elapsed year since 1970, plus one more day for * each elapsed leap year. no danger of overflow because of the range * check (above) on tmptm1. */ tmptm3 = (tmptm1 - _BASE_YEAR) * 365 + _ELAPSED_LEAP_YEARS(tmptm1); /* * elapsed days to current month (still no possible overflow) */ tmptm3 += tmptm2; /* * elapsed days to current date. */ tmptm1 = tmptm3 + (tmptm2 = (__time64_t)(tb->tm_mday)); /***** HERE: tmptm1 holds number of elapsed days *****/ /* * Calculate elapsed hours since base date */ tmptm2 = tmptm1 * 24; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_hour); /***** HERE: tmptm1 holds number of elapsed hours *****/ /* * Calculate elapsed minutes since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_min); /***** HERE: tmptm1 holds number of elapsed minutes *****/ /* * Calculate elapsed seconds since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_sec); /***** HERE: tmptm1 holds number of elapsed seconds *****/ if ( ultflag ) { /* * Adjust for timezone. No need to check for overflow since * localtime() will check its arg value */ __tzset(); _ERRCHECK(_get_dstbias(&dstbias)); _ERRCHECK(_get_timezone(&timezone)); tmptm1 += timezone; /* * Convert this second count back into a time block structure. * If localtime returns NULL, return an error. */ if ( _localtime64_s(&tbtemp, &tmptm1) != 0 ) goto err_mktime; /* * Now must compensate for DST. The ANSI rules are to use the * passed-in tm_isdst flag if it is non-negative. Otherwise, * compute if DST applies. Recall that tbtemp has the time without * DST compensation, but has set tm_isdst correctly. */ if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) && (tbtemp.tm_isdst > 0)) ) { tmptm1 += dstbias; if ( _localtime64_s(&tbtemp, &tmptm1) != 0 ) goto err_mktime; } } else { if ( _gmtime64_s(&tbtemp, &tmptm1) != 0) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/ /***** for local time if requested *****/ *tb = tbtemp; return tmptm1; err_mktime: /* * All errors come to here */ errno = EINVAL; return (__time64_t)(-1); }
struct tm * __cdecl localtime ( const time_t *ptime ) { REG1 struct tm *ptm; long ltime; /* * Check for illegal time_t value */ if ( (long)*ptime < 0L ) return( NULL ); #ifdef _WIN32 __tzset(); #else /* _WIN32 */ #if defined (_M_MPPC) || defined (_M_M68K) _tzset(); #endif /* defined (_M_MPPC) || defined (_M_M68K) */ #endif /* _WIN32 */ if ( (*ptime > 3 * _DAY_SEC) && (*ptime < LONG_MAX - 3 * _DAY_SEC) ) { /* * The date does not fall within the first three, or last * three, representable days of the Epoch. Therefore, there * is no possibility of overflowing or underflowing the * time_t representation as we compensate for timezone and * Daylight Savings Time. */ ltime = (long)*ptime - _timezone; ptm = gmtime( (time_t *)<ime ); /* * Check and adjust for Daylight Saving Time. */ if ( _daylight && _isindst( ptm ) ) { ltime -= _dstbias; ptm = gmtime( (time_t *)<ime ); ptm->tm_isdst = 1; } } else { ptm = gmtime( ptime ); /* * The date falls with the first three, or last three days * of the Epoch. It is possible the time_t representation * would overflow or underflow while compensating for * timezone and Daylight Savings Time. Therefore, make the * timezone and Daylight Savings Time adjustments directly * in the tm structure. The beginning of the Epoch is * 00:00:00, 01-01-70 (UTC) and the last representable second * in the Epoch is 03:14:07, 01-19-2038 (UTC). This will be * used in the calculations below. * * First, adjust for the timezone. */ if ( _isindst(ptm) ) ltime = (long)ptm->tm_sec - (_timezone + _dstbias); else ltime = (long)ptm->tm_sec - _timezone; ptm->tm_sec = (int)(ltime % 60); if ( ptm->tm_sec < 0 ) { ptm->tm_sec += 60; ltime -= 60; } ltime = (long)ptm->tm_min + ltime/60; ptm->tm_min = (int)(ltime % 60); if ( ptm->tm_min < 0 ) { ptm->tm_min += 60; ltime -= 60; } ltime = (long)ptm->tm_hour + ltime/60; ptm->tm_hour = (int)(ltime % 24); if ( ptm->tm_hour < 0 ) { ptm->tm_hour += 24; ltime -=24; } ltime /= 24; if ( ltime > 0L ) { /* * There is no possibility of overflowing the tm_mday * and tm_yday fields since the date can be no later * than January 19. */ ptm->tm_wday = (ptm->tm_wday + ltime) % 7; ptm->tm_mday += ltime; ptm->tm_yday += ltime; } else if ( ltime < 0L ) { /* * It is possible to underflow the tm_mday and tm_yday * fields. If this happens, then adjusted date must * lie in December 1969. */ ptm->tm_wday = (ptm->tm_wday + 7 + ltime) % 7; if ( (ptm->tm_mday += ltime) <= 0 ) { ptm->tm_mday += 31; ptm->tm_yday = 364; ptm->tm_mon = 11; ptm->tm_year--; } else { ptm->tm_yday += ltime; } } } return(ptm); }
static errno_t __cdecl common_localtime_s( tm* const ptm, TimeType const* const ptime ) throw() { typedef __crt_time_time_t_traits<TimeType> time_traits; _VALIDATE_RETURN_ERRCODE(ptm != nullptr, EINVAL); memset(ptm, 0xff, sizeof(tm)); _VALIDATE_RETURN_ERRCODE(ptime != nullptr, EINVAL); // Check for illegal time_t value: _VALIDATE_RETURN_ERRCODE_NOEXC(*ptime >= 0, EINVAL); _VALIDATE_RETURN_ERRCODE_NOEXC(*ptime <= time_traits::max_time_t, EINVAL); __tzset(); int daylight = 0; long dstbias = 0; long timezone = 0; _ERRCHECK(_get_daylight(&daylight)); _ERRCHECK(_get_dstbias (&dstbias )); _ERRCHECK(_get_timezone(&timezone)); if (*ptime > 3 * _DAY_SEC && *ptime < time_traits::max_time_t - 3 * _DAY_SEC) { // The date does not fall within the first three or last three representable // days; therefore, there is no possibility of overflowing or underflowing // the time_t representation as we compensate for time zone and daylight // savings time. TimeType ltime = *ptime - timezone; errno_t status0 = time_traits::gmtime_s(ptm, <ime); if (status0 != 0) return status0; // Check and adjust for daylight savings time: if (daylight && _isindst(ptm)) { ltime -= dstbias; errno_t const status1 = time_traits::gmtime_s(ptm, <ime); if (status1 != 0) return status1; ptm->tm_isdst = 1; } } else { // The date falls within the first three or last three representable days; // therefore, it is possible that the time_t representation would overflow // or underflow while compensating for time zone and daylight savings time. // Therefore, we make the time zone and daylight savings time adjustments // directly in the tm structure. errno_t const status0 = time_traits::gmtime_s(ptm, ptime); if (status0 != 0) return status0; TimeType ltime = static_cast<TimeType>(ptm->tm_sec); // First, adjust for the time zone: if (daylight && _isindst(ptm)) { ltime -= (timezone + dstbias); ptm->tm_isdst = 1; } else { ltime -= timezone; } ptm->tm_sec = static_cast<int>(ltime % 60); if (ptm->tm_sec < 0) { ptm->tm_sec += 60; ltime -= 60; } ltime = static_cast<TimeType>(ptm->tm_min) + ltime / 60; ptm->tm_min = static_cast<int>(ltime % 60); if (ptm->tm_min < 0) { ptm->tm_min += 60; ltime -= 60; } ltime = static_cast<TimeType>(ptm->tm_hour) + ltime / 60; ptm->tm_hour = static_cast<int>(ltime % 24); if (ptm->tm_hour < 0) { ptm->tm_hour += 24; ltime -=24; } ltime /= 24; if (ltime > 0) { // There is no possibility of overflowing the tm_day and tm_yday // members because the date can be no later than January 19. ptm->tm_wday = (ptm->tm_wday + static_cast<int>(ltime)) % 7; ptm->tm_mday += static_cast<int>(ltime); ptm->tm_yday += static_cast<int>(ltime); } else if (ltime < 0) { // It is possible to underflow the tm_mday and tm_yday fields. If // this happens, then the adjusted date must lie in December 1969: ptm->tm_wday = (ptm->tm_wday + 7 + static_cast<int>(ltime)) % 7; ptm->tm_mday += static_cast<int>(ltime); if (ptm->tm_mday <= 0) { ptm->tm_mday += 31; // Per assumption #4 above, the time zone can cause the date to // underflow the epoch by more than a day. ptm->tm_yday = ptm->tm_yday + static_cast<int>(ltime) + 365; ptm->tm_mon = 11; ptm->tm_year--; } else { ptm->tm_yday += static_cast<int>(ltime); } } } return 0; }