Exemple #1
0
static void NeutralizeTimezone(tm& t) {
  static bool initialized = false;
  static long timezone_difference = 0;

  if (!initialized) {
    _tzset();
    _get_timezone(&timezone_difference);

    long dst_difference = 0;
    _get_dstbias(&dst_difference);
    timezone_difference += dst_difference;

    initialized = true;
  }

  t.tm_sec -= timezone_difference;  // mktime uses the current time zone
}
Exemple #2
0
void SG_time__decode__local(SG_context* pCtx, SG_int64 iTime, SG_time* pTime)
{
	// iTime contains time in milliseconds since epoch in UTC.
	// convert this to a SG_time expressed in localtime.

	time_t t1 = iTime / MILLISECONDS_PER_SECOND;

#if defined(MAC) || defined(LINUX)
	struct tm* ptm = localtime(&t1);
#endif
#if defined(WINDOWS)
	struct tm tBuf;
	struct tm* ptm = &tBuf;
	long tzBiasSec, dstBiasSec;
	(void)_localtime64_s(&tBuf,&t1);
	(void)_get_dstbias(&dstBiasSec);
	(void)_get_timezone(&tzBiasSec);
#endif

	SG_NULLARGCHECK_RETURN(pTime);

	pTime->year = ptm->tm_year + 1900;
	pTime->month = ptm->tm_mon + 1;
	pTime->mday = ptm->tm_mday;
	pTime->hour = ptm->tm_hour;
	pTime->min = ptm->tm_min;
	pTime->sec = ptm->tm_sec;
	pTime->msec = (SG_uint32)(iTime % MILLISECONDS_PER_SECOND);

	pTime->wday = ptm->tm_wday;
	pTime->yday = ptm->tm_yday;

#if defined(MAC) || defined(LINUX)
	pTime->offsetUTC = (SG_int32)ptm->tm_gmtoff;
#endif
#if defined(WINDOWS)
	pTime->offsetUTC = -(SG_int32)(tzBiasSec + ((ptm->tm_isdst > 0) ? dstBiasSec : 0));
#endif

}
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);
}
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;
}