Пример #1
0
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);
}
Пример #2
0
_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;
}
Пример #3
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;
}
Пример #4
0
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);
}
Пример #5
0
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 *)&ltime );

                /*
                 * Check and adjust for Daylight Saving Time.
                 */
                if ( _daylight && _isindst( ptm ) ) {
                        ltime -= _dstbias;
                        ptm = gmtime( (time_t *)&ltime );
                        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);
}
Пример #6
0
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, &ltime);
        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, &ltime);
            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;
}