VirtualBox

Ignore:
Timestamp:
May 7, 2018 2:21:31 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
122537
Message:

IPRT/time: misc fixes (incorrect offUTC conversion sign, forgotten storing of offUTC, incorrect month/day calculation for first day of month, avoiding assertions when leap year needs to be recalulated) for local time, make RTTimeImplode process local time correctly, plus an implementation of RTTimeLocalNormalize and RTTimeConvertToZulu. Much improved testcase exercising overflow handling in the local time case.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/time/time.cpp

    r72094 r72140  
    237237*/
    238238
     239/*********************************************************************************************************************************
     240*   Internal Functions                                                                                                           *
     241*********************************************************************************************************************************/
     242static PRTTIME rtTimeConvertToZulu(PRTTIME pTime);
     243
    239244
    240245/**
     
    390395 *                      The fields u8Month, u8WeekDay and u8MonthDay are not used,
    391396 *                      and all the other fields are expected to be within their
    392  *                      bounds. Use RTTimeNormalize() to calculate u16YearDay and
    393  *                      normalize the ranges of the fields.
     397 *                      bounds. Use RTTimeNormalize() or RTTimeLocalNormalize() to
     398 *                      calculate u16YearDay and normalize the ranges of the fields.
    394399 */
    395400RTDECL(PRTTIMESPEC) RTTimeImplode(PRTTIMESPEC pTimeSpec, PCRTTIME pTime)
     
    412417    AssertMsgReturn(pTime->i32Year <= RTTIME_MAX_YEAR && pTime->i32Year >= RTTIME_MIN_YEAR, ("%RI32\n", pTime->i32Year), NULL);
    413418
     419    RTTIME TimeUTC;
     420    if ((pTime->fFlags & RTTIME_FLAGS_TYPE_MASK) != RTTIME_FLAGS_TYPE_UTC)
     421    {
     422        TimeUTC = *pTime;
     423        pTime = rtTimeConvertToZulu(&TimeUTC);
     424    }
     425
    414426    /*
    415427     * Do the conversion to nanoseconds.
     
    437449/**
    438450 * Internal worker for RTTimeNormalize and RTTimeLocalNormalize.
    439  * It doesn't adjust the UCT offset but leaves that for RTTimeLocalNormalize.
    440451 */
    441452static PRTTIME rtTimeNormalizeInternal(PRTTIME pTime)
     
    536547                         : &g_aiDayOfYear[0];
    537548            pTime->u8Month = 1;
    538             while (pTime->u16YearDay > paiDayOfYear[pTime->u8Month])
     549            while (pTime->u16YearDay > paiDayOfYear[pTime->u8Month] - 1)
    539550                pTime->u8Month++;
    540551            Assert(pTime->u8Month >= 1 && pTime->u8Month <= 12);
     
    696707
    697708/**
     709 * Normalizes the fields of a time structure, assuming local time.
     710 *
     711 * It is possible to calculate year-day from month/day and vice
     712 * versa. If you adjust any of these, make sure to zero the
     713 * other so you make it clear which of the fields to use. If
     714 * it's ambiguous, the year-day field is used (and you get
     715 * assertions in debug builds).
     716 *
     717 * All the time fields and the year-day or month/day fields will
     718 * be adjusted for overflows. (Since all fields are unsigned, there
     719 * is no underflows.) It is possible to exploit this for simple
     720 * date math, though the recommended way of doing that to implode
     721 * the time into a timespec and do the math on that.
     722 *
     723 * @returns pTime on success.
     724 * @returns NULL if the data is invalid.
     725 *
     726 * @param   pTime       The time structure to normalize.
     727 *
     728 * @remarks This function doesn't work with UTC time, only with local time.
     729 */
     730RTDECL(PRTTIME) RTTimeLocalNormalize(PRTTIME pTime)
     731{
     732    /*
     733     * Validate that we've got the minimum of stuff handy.
     734     */
     735    AssertReturn(VALID_PTR(pTime), NULL);
     736    AssertMsgReturn(!(pTime->fFlags & ~RTTIME_FLAGS_MASK), ("%#x\n", pTime->fFlags), NULL);
     737    AssertMsgReturn((pTime->fFlags & RTTIME_FLAGS_TYPE_MASK) != RTTIME_FLAGS_TYPE_UTC, ("Use RTTimeNormalize!\n"), NULL);
     738
     739    pTime = rtTimeNormalizeInternal(pTime);
     740    if (pTime)
     741        pTime->fFlags |= RTTIME_FLAGS_TYPE_LOCAL;
     742    return pTime;
     743}
     744RT_EXPORT_SYMBOL(RTTimeLocalNormalize);
     745
     746
     747/**
    698748 * Converts a time spec to a ISO date string.
    699749 *
     
    9671017    if (pTime->u16YearDay > 1)
    9681018    {
    969         pTime->u16YearDay -= 0;
     1019        pTime->u16YearDay -= 1;
    9701020        pTime->u8Month     = 0;
    9711021        pTime->u8MonthDay  = 0;
     
    9771027        pTime->u8MonthDay  = 31;
    9781028        pTime->u8Month     = 12;
     1029        pTime->fFlags     &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);
    9791030    }
    9801031    return rtTimeNormalizeInternal(pTime);
     
    10251076 *
    10261077 * @returns pTime.
    1027  * @param   pTime       What to convers (in/out).
     1078 * @param   pTime       What to convert (in/out).
    10281079 */
    10291080static PRTTIME rtTimeConvertToZulu(PRTTIME pTime)
     
    10371088        pTime->fFlags |= RTTIME_FLAGS_TYPE_UTC;
    10381089        if (offUTC != 0)
    1039             rtTimeAddMinutes(pTime, offUTC);
     1090            rtTimeAddMinutes(pTime, -offUTC);
    10401091    }
    10411092    return pTime;
     1093}
     1094
     1095
     1096/**
     1097 * Converts a time structure to UTC, relying on UTC offset information if it contains local time.
     1098 *
     1099 * @returns pTime on success.
     1100 * @returns NULL if the data is invalid.
     1101 * @param   pTime       The time structure to convert.
     1102 */
     1103PRTTIME RTTimeConvertToZulu(PRTTIME pTime)
     1104{
     1105    /*
     1106     * Validate that we've got the minimum of stuff handy.
     1107     */
     1108    AssertReturn(VALID_PTR(pTime), NULL);
     1109    AssertMsgReturn(!(pTime->fFlags & ~RTTIME_FLAGS_MASK), ("%#x\n", pTime->fFlags), NULL);
     1110
     1111    return rtTimeConvertToZulu(rtTimeNormalizeInternal(pTime));
    10421112}
    10431113
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette