VirtualBox

Changeset 72140 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 7, 2018 2:21:31 PM (7 years ago)
Author:
vboxsync
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.

Location:
trunk/src/VBox/Runtime
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/VBox/VBoxRTImp.def

    r69111 r72140  
    13331333    RTThreadWaitNoResume
    13341334    RTThreadYield
     1335    RTTimeCompare
     1336    RTTimeConvertToZulu
    13351337    RTTimeDbgBad
    13361338    RTTimeDbgExpired
     
    13421344    RTTimeLocalDeltaNano
    13431345    RTTimeLocalExplode
     1346    RTTimeLocalNormalize
    13441347    RTTimeLocalNow
    13451348    RTTimeMilliTS
  • 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
  • trunk/src/VBox/Runtime/generic/RTTimeLocalExplode-generic.cpp

    r69111 r72140  
    3535RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
    3636{
    37     pTime = RTTimeExplode(pTime, pTimeSpec);
     37    RTTIMESPEC LocalTime = *pTimeSpec;
     38    int64_t LocalUTCOffset = RTTimeLocalDeltaNano(); /**< @todo this is obviously wrong. Need RTTimeLocalDeltaNanoFor(pTimeSpec); */
     39    RTTimeSpecAddNano(&LocalTime, LocalUTCOffset);
     40    pTime = RTTimeExplode(pTime, &LocalTime);
    3841    if (pTime)
    3942    {
    4043        pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
    41         pTime->offZone = RTTimeLocalDeltaNano() / (UINT64_C(1000000000)*3600); /** @todo this is obviously wrong. Need RTTimeLocalDeltaNanoFor(pTimeSpec); */
     44        pTime->offUTC = LocalUTCOffset / RT_NS_1MIN;
    4245    }
    4346    return pTime;
  • trunk/src/VBox/Runtime/r3/posix/timelocal-posix.cpp

    r72100 r72140  
    6464
    6565    /*
    66      * Explode it as both local and uct time.
     66     * Explode it as both local and UTC time.
    6767     */
    6868    struct tm TmLocal;
     
    9595         * Must add 24 hours to the value that is ahead of the other.
    9696         *
    97          * To determin which is ahead was busted for a long long time (bugref:9078),
     97         * To determine which is ahead was busted for a long long time (bugref:9078),
    9898         * so here are some examples and two different approaches.
    9999         *
     
    174174{
    175175    RTTIMESPEC LocalTime = *pTimeSpec;
    176     RTTimeSpecAddNano(&LocalTime, rtTimeLocalUTCOffset(&LocalTime, true /* current time, skip fallback */));
     176    int64_t LocalUTCOffset = rtTimeLocalUTCOffset(&LocalTime, true /* current time, skip fallback */);
     177    RTTimeSpecAddNano(&LocalTime, LocalUTCOffset);
    177178    pTime = RTTimeExplode(pTime, &LocalTime);
    178179    if (pTime)
     180    {
    179181        pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
     182        pTime->offUTC = LocalUTCOffset / RT_NS_1MIN;
     183    }
    180184    return pTime;
    181185}
  • trunk/src/VBox/Runtime/r3/win/time2-win.cpp

    r70345 r72140  
    7676                    pTime = RTTimeExplode(pTime, &LocalTime);
    7777                    if (pTime)
     78                    {
    7879                        pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
     80                        pTime->offUTC = (LocalTime - *pTimeSpec) / RT_NS_1MIN;
     81                    }
    7982                    return pTime;
    8083                }
     
    8891     */
    8992    LocalTime = *pTimeSpec;
    90     RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano());
     93    int64_t LocalUTCOffset = RTTimeLocalDeltaNano();
     94    RTTimeSpecAddNano(&LocalTime, LocalUTCOffset);
    9195    pTime = RTTimeExplode(pTime, &LocalTime);
    9296    if (pTime)
     97    {
    9398        pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
     99        pTime->offUTC = LocalUTCOffset / RT_NS_1MIN;
     100    }
    94101    return pTime;
    95102}
  • trunk/src/VBox/Runtime/testcase/tstRTTimeSpec.cpp

    r69111 r72140  
    7373    } while (0)
    7474
     75#define TEST_NS_LOCAL(ns) do {\
     76        CHECK_NZ(RTTimeLocalExplode(&T1, RTTimeSpecSetNano(&Ts1, ns))); \
     77        RTTestIPrintf(RTTESTLVL_ALWAYS, "%RI64 ns - %s\n", ns, ToString(&T1)); \
     78        CHECK_NZ(RTTimeImplode(&Ts2, &T1)); \
     79        if (!RTTimeSpecIsEqual(&Ts2, &Ts1)) \
     80            RTTestIFailed("FAILURE - %RI64 != %RI64, line no. %d\n", \
     81                          RTTimeSpecGetNano(&Ts2), RTTimeSpecGetNano(&Ts1), __LINE__); \
     82    } while (0)
     83
    7584#define TEST_SEC(sec) do {\
    7685        CHECK_NZ(RTTimeExplode(&T1, RTTimeSpecSetSeconds(&Ts1, sec))); \
     
    8291    } while (0)
    8392
    84 #define CHECK_TIME(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags)\
     93#define CHECK_TIME_EX(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags, _Silent)\
    8594    do { \
    8695        if (    (pTime)->i32Year != (_i32Year) \
     
    98107        { \
    99108            RTTestIFailed("   %s ; line no %d\n" \
    100                           "!= %04d-%02d-%02dT%02u-%02u-%02u.%09u [YD%u WD%u UO%d F%#x]\n", \
     109                          "!= %04d-%02d-%02dT%02u:%02u:%02u.%09u [YD%u WD%u UO%d F%#x]\n", \
    101110                          ToString(pTime), __LINE__, (_i32Year), (_u8Month), (_u8MonthDay), (_u8Hour), (_u8Minute), \
    102111                          (_u8Second), (_u32Nanosecond), (_u16YearDay), (_u8WeekDay), (_offUTC), (_fFlags)); \
    103112        } \
    104         else \
     113        else if (!_Silent) \
    105114            RTTestIPrintf(RTTESTLVL_ALWAYS, "=> %s\n", ToString(pTime)); \
    106115    } while (0)
     116#define CHECK_TIME(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags) CHECK_TIME_EX(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags, false)
     117#define CHECK_TIME_SILENT(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags) CHECK_TIME_EX(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags, true)
     118
     119#define CHECK_TIME_LOCAL_EX(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags, _Silent)\
     120    do { \
     121        uint32_t fOrigFlags = (pTime)->fFlags; \
     122        CHECK_NZ(RTTimeConvertToZulu(pTime)); \
     123        if (    (pTime)->i32Year != (_i32Year) \
     124            ||  (pTime)->u8Month != (_u8Month) \
     125            ||  (pTime)->u8WeekDay != (_u8WeekDay) \
     126            ||  (pTime)->u16YearDay != (_u16YearDay) \
     127            ||  (pTime)->u8MonthDay != (_u8MonthDay) \
     128            ||  (pTime)->u8Hour != (_u8Hour) \
     129            ||  (pTime)->u8Minute != (_u8Minute) \
     130            ||  (pTime)->u8Second != (_u8Second) \
     131            ||  (pTime)->u32Nanosecond != (_u32Nanosecond) \
     132            ||  (pTime)->offUTC != (_offUTC) \
     133            ||  (fOrigFlags & RTTIME_FLAGS_TYPE_MASK) != RTTIME_FLAGS_TYPE_LOCAL \
     134            ||  (pTime)->fFlags != (_fFlags) \
     135            ) \
     136        { \
     137            RTTestIFailed("   %s ; line no %d\n" \
     138                          "!= %04d-%02d-%02dT%02u:%02u:%02u.%09u [YD%u WD%u UO%d F%#x]\n", \
     139                          ToString(pTime), __LINE__, (_i32Year), (_u8Month), (_u8MonthDay), (_u8Hour), (_u8Minute), \
     140                          (_u8Second), (_u32Nanosecond), (_u16YearDay), (_u8WeekDay), (_offUTC), (_fFlags)); \
     141        } \
     142        else if (!_Silent) \
     143            RTTestIPrintf(RTTESTLVL_ALWAYS, "=> %s\n", ToString(pTime)); \
     144    } while (0)
     145#define CHECK_TIME_LOCAL(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags) CHECK_TIME_LOCAL_EX(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags, false)
     146#define CHECK_TIME_LOCAL_SILENT(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags) CHECK_TIME_LOCAL_EX(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags, true)
    107147
    108148#define SET_TIME(pTime, _i32Year, _u8Month, _u8MonthDay, _u8Hour, _u8Minute, _u8Second, _u32Nanosecond, _u16YearDay, _u8WeekDay, _offUTC, _fFlags)\
     
    179219
    180220    /*
     221     * Some local time tests with dates triggering unexpected wraparound bugs in previous code version
     222     * (on 2nd of a month). Test every hour to cover any TZ of the host OS.
     223     */
     224    RTTestSub(hTest, "Wraparound (local)");
     225    TEST_NS_LOCAL(INT64_C(1522576800000000000));
     226    CHECK_TIME_LOCAL(&T1, 2018,04,01, 10,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     227    TEST_NS_LOCAL(INT64_C(1522580400000000000));
     228    CHECK_TIME_LOCAL(&T1, 2018,04,01, 11,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     229    TEST_NS_LOCAL(INT64_C(1522584000000000000));
     230    CHECK_TIME_LOCAL(&T1, 2018,04,01, 12,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     231    TEST_NS_LOCAL(INT64_C(1522587600000000000));
     232    CHECK_TIME_LOCAL(&T1, 2018,04,01, 13,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     233    TEST_NS_LOCAL(INT64_C(1522591200000000000));
     234    CHECK_TIME_LOCAL(&T1, 2018,04,01, 14,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     235    TEST_NS_LOCAL(INT64_C(1522594800000000000));
     236    CHECK_TIME_LOCAL(&T1, 2018,04,01, 15,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     237    TEST_NS_LOCAL(INT64_C(1522598400000000000));
     238    CHECK_TIME_LOCAL(&T1, 2018,04,01, 16,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     239    TEST_NS_LOCAL(INT64_C(1522602000000000000));
     240    CHECK_TIME_LOCAL(&T1, 2018,04,01, 17,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     241    TEST_NS_LOCAL(INT64_C(1522605600000000000));
     242    CHECK_TIME_LOCAL(&T1, 2018,04,01, 18,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     243    TEST_NS_LOCAL(INT64_C(1522609200000000000));
     244    CHECK_TIME_LOCAL(&T1, 2018,04,01, 19,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     245    TEST_NS_LOCAL(INT64_C(1522612800000000000));
     246    CHECK_TIME_LOCAL(&T1, 2018,04,01, 20,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     247    TEST_NS_LOCAL(INT64_C(1522616400000000000));
     248    CHECK_TIME_LOCAL(&T1, 2018,04,01, 21,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     249    TEST_NS_LOCAL(INT64_C(1522620000000000000));
     250    CHECK_TIME_LOCAL(&T1, 2018,04,01, 22,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     251    TEST_NS_LOCAL(INT64_C(1522623600000000000));
     252    CHECK_TIME_LOCAL(&T1, 2018,04,01, 23,00,00,        0,  91, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     253    TEST_NS_LOCAL(INT64_C(1522627200000000000));
     254    CHECK_TIME_LOCAL(&T1, 2018,04,02,  0,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     255    TEST_NS_LOCAL(INT64_C(1522630800000000000));
     256    CHECK_TIME_LOCAL(&T1, 2018,04,02,  1,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     257    TEST_NS_LOCAL(INT64_C(1522634400000000000));
     258    CHECK_TIME_LOCAL(&T1, 2018,04,02,  2,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     259    TEST_NS_LOCAL(INT64_C(1522638000000000000));
     260    CHECK_TIME_LOCAL(&T1, 2018,04,02,  3,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     261    TEST_NS_LOCAL(INT64_C(1522641600000000000));
     262    CHECK_TIME_LOCAL(&T1, 2018,04,02,  4,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     263    TEST_NS_LOCAL(INT64_C(1522645200000000000));
     264    CHECK_TIME_LOCAL(&T1, 2018,04,02,  5,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     265    TEST_NS_LOCAL(INT64_C(1522648800000000000));
     266    CHECK_TIME_LOCAL(&T1, 2018,04,02,  6,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     267    TEST_NS_LOCAL(INT64_C(1522652400000000000));
     268    CHECK_TIME_LOCAL(&T1, 2018,04,02,  7,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     269    TEST_NS_LOCAL(INT64_C(1522656000000000000));
     270    CHECK_TIME_LOCAL(&T1, 2018,04,02,  8,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     271    TEST_NS_LOCAL(INT64_C(1522659600000000000));
     272    CHECK_TIME_LOCAL(&T1, 2018,04,02,  9,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     273    TEST_NS_LOCAL(INT64_C(1522663200000000000));
     274    CHECK_TIME_LOCAL(&T1, 2018,04,02, 10,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     275    TEST_NS_LOCAL(INT64_C(1522666800000000000));
     276    CHECK_TIME_LOCAL(&T1, 2018,04,02, 11,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     277    TEST_NS_LOCAL(INT64_C(1522670400000000000));
     278    CHECK_TIME_LOCAL(&T1, 2018,04,02, 12,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     279    TEST_NS_LOCAL(INT64_C(1522674000000000000));
     280    CHECK_TIME_LOCAL(&T1, 2018,04,02, 13,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     281    TEST_NS_LOCAL(INT64_C(1522677600000000000));
     282    CHECK_TIME_LOCAL(&T1, 2018,04,02, 14,00,00,        0,  92, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     283
     284    /*
    181285     * Test the limits.
    182286     */
     
    193297    CHECK_TIME(&T1, 2004, 9,17, 00,00,01,        0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR);
    194298
    195 
    196299    /*
    197300     * Test normalization (UTC).
     
    308411    CHECK_NZ(RTTimeNormalize(&T1));
    309412    CHECK_TIME(&T1, 2007,12,06, 02,15,23,        1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     413
     414    /*
     415     * Test normalization (local).
     416     */
     417    RTTestSub(hTest, "Normalization (local)");
     418    /* simple */
     419    CHECK_NZ(RTTimeNow(&Now));
     420    CHECK_NZ(RTTimeLocalExplode(&T1, &Now));
     421    T2 = T1;
     422    CHECK_NZ(RTTimeLocalNormalize(&T1));
     423    if (memcmp(&T1, &T2, sizeof(T1)))
     424        RTTestIFailed("simple normalization failed\n");
     425    CHECK_NZ(RTTimeImplode(&Ts1, &T1));
     426    CHECK_NZ(RTTimeSpecIsEqual(&Ts1, &Now));
     427
     428    /* a few partial dates. */
     429    memset(&T1, 0, sizeof(T1));
     430    SET_TIME(  &T1, 1970,01,01, 00,00,00,        0,   0, 0, -60, 0);
     431    CHECK_NZ(RTTimeLocalNormalize(&T1));
     432    CHECK_TIME_LOCAL(&T1, 1970,01,01, 01,00,00,        0,   1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     433
     434    SET_TIME(  &T1, 1970,00,00, 00,00,00,        1,   1, 0, -120, 0);
     435    CHECK_NZ(RTTimeLocalNormalize(&T1));
     436    CHECK_TIME_LOCAL(&T1, 1970,01,01, 02,00,00,        1,   1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     437
     438    SET_TIME(  &T1, 2007,12,06, 02,15,23,        1,   0, 0, 120, 0);
     439    CHECK_NZ(RTTimeLocalNormalize(&T1));
     440    CHECK_TIME_LOCAL(&T1, 2007,12,06, 00,15,23,        1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     441
     442    SET_TIME(  &T1, 1968,01,30, 00,19,24,        5,   0, 0, -480, 0);
     443    CHECK_NZ(RTTimeLocalNormalize(&T1));
     444    CHECK_TIME_LOCAL(&T1, 1968,01,30,  8,19,24,        5,  30, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR);
     445
     446    SET_TIME(  &T1, 1969,01,31, 03, 9, 2,        7,   0, 0, 180, 0);
     447    CHECK_NZ(RTTimeLocalNormalize(&T1));
     448    CHECK_TIME_LOCAL(&T1, 1969,01,31, 00, 9, 2,        7,  31, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     449
     450    SET_TIME(  &T1, 1969,03,31, 00, 9, 2,        7,   0, 0, -60, 0);
     451    CHECK_NZ(RTTimeLocalNormalize(&T1));
     452    CHECK_TIME_LOCAL(&T1, 1969,03,31, 01, 9, 2,        7,  90, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     453
     454    SET_TIME(  &T1, 1969,12,30, 18,00,00,        9,   0, 0, -360, 0);
     455    CHECK_NZ(RTTimeLocalNormalize(&T1));
     456    CHECK_TIME_LOCAL(&T1, 1969,12,31, 00,00,00,        9, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     457
     458    SET_TIME(  &T1, 1969,12,29, 12,00,00,       30,   0, 0, -720, 0);
     459    CHECK_NZ(RTTimeLocalNormalize(&T1));
     460    CHECK_TIME_LOCAL(&T1, 1969,12,30, 00,00,00,       30, 364, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     461
     462    SET_TIME(  &T1, 1969,00,00, 00,00,00,       30, 363, 0, 30, 0);
     463    CHECK_NZ(RTTimeLocalNormalize(&T1));
     464    CHECK_TIME_LOCAL(&T1, 1969,12,28, 23,30,00,       30, 362, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     465
     466    SET_TIME(  &T1, 1969,00,00, 00,00,00,       30, 362, 6, -60, 0);
     467    CHECK_NZ(RTTimeLocalNormalize(&T1));
     468    CHECK_TIME_LOCAL(&T1, 1969,12,28, 01,00,00,       30, 362, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     469
     470    SET_TIME(  &T1, 1969,12,27, 00,00,00,       30,   0, 5, -120, 0);
     471    CHECK_NZ(RTTimeLocalNormalize(&T1));
     472    CHECK_TIME_LOCAL(&T1, 1969,12,27, 02,00,00,       30, 361, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     473
     474    SET_TIME(  &T1, 1969,00,00, 00,00,00,       30, 360, 0, -120, 0);
     475    CHECK_NZ(RTTimeLocalNormalize(&T1));
     476    CHECK_TIME_LOCAL(&T1, 1969,12,26, 02,00,00,       30, 360, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     477
     478    SET_TIME(  &T1, 1969,12,25, 00,00,00,       12,   0, 0, 15, 0);
     479    CHECK_NZ(RTTimeLocalNormalize(&T1));
     480    CHECK_TIME_LOCAL(&T1, 1969,12,24, 23,45,00,       12, 358, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     481
     482    SET_TIME(  &T1, 1969,12,24, 00,00,00,       16,   0, 0, -15, 0);
     483    CHECK_NZ(RTTimeLocalNormalize(&T1));
     484    CHECK_TIME_LOCAL(&T1, 1969,12,24, 00,15,00,       16, 358, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     485
     486    /* outside the year table range */
     487    SET_TIME(  &T1, 1200,01,30, 00,00,00,        2,   0, 0, -720, 0);
     488    CHECK_NZ(RTTimeLocalNormalize(&T1));
     489    CHECK_TIME_LOCAL(&T1, 1200,01,30, 12,00,00,        2,  30, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR);
     490
     491    SET_TIME(  &T1, 2555,11,29, 00,00,00,        2,   0, 0, -480, 0);
     492    CHECK_NZ(RTTimeLocalNormalize(&T1));
     493    CHECK_TIME_LOCAL(&T1, 2555,11,29,  8,00,00,        2, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     494
     495    SET_TIME(  &T1, 2555,00,00, 00,00,00,        3, 333, 0, 60, 0);
     496    CHECK_NZ(RTTimeLocalNormalize(&T1));
     497    CHECK_TIME_LOCAL(&T1, 2555,11,28, 23,00,00,        3, 332, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     498
     499    /* time overflow */
     500    SET_TIME(  &T1, 1969,12,30, 255,255,255, UINT32_MAX, 364, 0, 60, 0);
     501    CHECK_NZ(RTTimeLocalNormalize(&T1));
     502    CHECK_TIME_LOCAL(&T1, 1970,01, 9, 18,19,19,294967295,   9, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     503
     504    /* date overflow */
     505    SET_TIME(  &T1, 2007,11,36, 02,15,23,        1,   0, 0, 60, 0);
     506    CHECK_NZ(RTTimeLocalNormalize(&T1));
     507    CHECK_TIME_LOCAL(&T1, 2007,12,06, 01,15,23,        1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     508
     509    SET_TIME(  &T1, 2007,10,67, 02,15,23,        1,   0, 0, 60, 0);
     510    CHECK_NZ(RTTimeLocalNormalize(&T1));
     511    CHECK_TIME_LOCAL(&T1, 2007,12,06, 01,15,23,        1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     512
     513    SET_TIME(  &T1, 2007,10,98, 02,15,23,        1,   0, 0, 60, 0);
     514    CHECK_NZ(RTTimeLocalNormalize(&T1));
     515    CHECK_TIME_LOCAL(&T1, 2008,01,06, 01,15,23,        1,   6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR);
     516
     517    SET_TIME(  &T1, 2006,24,06, 02,15,23,        1,   0, 0, 60, 0);
     518    CHECK_NZ(RTTimeLocalNormalize(&T1));
     519    CHECK_TIME_LOCAL(&T1, 2007,12,06, 01,15,23,        1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     520
     521    SET_TIME(  &T1, 2003,60,37, 02,15,23,        1,   0, 0, -60, 0);
     522    CHECK_NZ(RTTimeLocalNormalize(&T1));
     523    CHECK_TIME_LOCAL(&T1, 2008,01,06, 03,15,23,        1,   6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR);
     524
     525    SET_TIME(  &T1, 2003,00,00, 02,15,23,        1,1801, 0, -60, 0);
     526    CHECK_NZ(RTTimeLocalNormalize(&T1));
     527    CHECK_TIME_LOCAL(&T1, 2007,12,06, 03,15,23,        1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR);
     528
     529    /*
     530     * Test UTC and local time explode/implode round trips every 29 minutes for 3 years.
     531     * Relies heavily on correct behavior of RTTimeNormalize and does limited sanity checking.
     532     */
     533    RTTestSub(hTest, "Wraparound 3 year (UTC+local), silent");
     534    RTTimeSpecSetNano(&Ts1, 1420070400000000000);
     535    RTTIME Tcheck;
     536    memset(&Tcheck, 0, sizeof(Tcheck));
     537    Tcheck.i32Year = 2015;
     538    Tcheck.u16YearDay = 1;
     539    CHECK_NZ(RTTimeNormalize(&Tcheck));
     540    while (Tcheck.i32Year <= 2017)
     541    {
     542        if (RTTimeIsLeapYear(Tcheck.i32Year))
     543        {
     544            if (!(Tcheck.fFlags & RTTIME_FLAGS_LEAP_YEAR))
     545                RTTestIFailed("FAILURE - %d is not marked as a leap year, line no. %d\n",
     546                              Tcheck.i32Year, __LINE__);
     547        }
     548        else
     549        {
     550            if (!(Tcheck.fFlags & RTTIME_FLAGS_COMMON_YEAR))
     551                RTTestIFailed("FAILURE - %d is not marked as a common year, line no. %d\n",
     552                              Tcheck.i32Year, __LINE__);
     553        }
     554
     555        CHECK_NZ(RTTimeExplode(&T1, &Ts1));
     556        CHECK_NZ(RTTimeImplode(&Ts2, &T1));
     557        if (!RTTimeSpecIsEqual(&Ts2, &Ts1))
     558            RTTestIFailed("FAILURE - %RI64 != %RI64, line no. %d\n",
     559                          RTTimeSpecGetNano(&Ts2), RTTimeSpecGetNano(&Ts1), __LINE__);
     560        CHECK_TIME_SILENT(&T1, Tcheck.i32Year, Tcheck.u8Month, Tcheck.u8MonthDay, Tcheck.u8Hour, Tcheck.u8Minute, Tcheck.u8Second, Tcheck.u32Nanosecond, Tcheck.u16YearDay, Tcheck.u8WeekDay, Tcheck.offUTC, Tcheck.fFlags);
     561
     562        CHECK_NZ(RTTimeLocalExplode(&T1, &Ts1));
     563        CHECK_NZ(RTTimeImplode(&Ts2, &T1));
     564        if (!RTTimeSpecIsEqual(&Ts2, &Ts1))
     565            RTTestIFailed("FAILURE - %RI64 != %RI64, line no. %d\n",
     566                          RTTimeSpecGetNano(&Ts2), RTTimeSpecGetNano(&Ts1), __LINE__);
     567        CHECK_TIME_LOCAL_SILENT(&T1, Tcheck.i32Year, Tcheck.u8Month, Tcheck.u8MonthDay, Tcheck.u8Hour, Tcheck.u8Minute, Tcheck.u8Second, Tcheck.u32Nanosecond, Tcheck.u16YearDay, Tcheck.u8WeekDay, Tcheck.offUTC, Tcheck.fFlags);
     568
     569        RTTimeSpecAddNano(&Ts1, 29 * RT_NS_1MIN);
     570        Tcheck.u8Minute += 29;
     571        CHECK_NZ(RTTimeNormalize(&Tcheck));
     572    }
    310573
    311574    /*
Note: See TracChangeset for help on using the changeset viewer.

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