Skip to content

Commit

Permalink
Fix Baltzo::TimeZoneUtil::convertLocalToUtc DRQS 174142713 (#4795)
Browse files Browse the repository at this point in the history
  • Loading branch information
bottha123 authored and GitHub Enterprise committed Jul 2, 2024
1 parent 102b05c commit a3cb19f
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 62 deletions.
7 changes: 5 additions & 2 deletions groups/bal/baltzo/baltzo_timezoneutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,8 @@ struct TimeZoneUtil {
// UTC of the time zone is rounded down to minute precision. Return 0
// on success, and a non-zero value with no effect otherwise. A return
// value of 'ErrorCode::k_UNSUPPORTED_ID' indicates that 'timeZoneId'
// was not recognized.
// was not recognized. The behavior is undefined unless the result of
// the initialization falls within the supported epoch.

static int convertLocalToUtc(bdlt::Datetime *result,
const bdlt::Datetime& localTime,
Expand All @@ -604,7 +605,9 @@ struct TimeZoneUtil {
// offset from UTC of the time zone is rounded down to minute
// precision. Return 0 on success, and a non-zero value with no effect
// otherwise. A return value of 'ErrorCode::k_UNSUPPORTED_ID'
// indicates that 'timeZoneId' was not recognized.
// indicates that 'timeZoneId' was not recognized. The behavior is
// undefined unless the result of the conversion falls within the
// supported epoch.

static int loadLocalTimePeriod(LocalTimePeriod *result,
const LocalDatetime& localTime);
Expand Down
69 changes: 56 additions & 13 deletions groups/bal/baltzo/baltzo_timezoneutil.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2286,10 +2286,10 @@ int main(int argc, char *argv[])
//: 1 'k_UNSUPPORTED_ID' is returned when an invalid identifier is
//: passed in.
//:
//: 2 'baltzo::TimeZoneUtilImp::convertLocalToUtc' is invoked return
//: the correct result.
//: 2 'baltzo::TimeZoneUtilImp::convertLocalToUtc' is invoked and
//: the correct result is returned.
//:
//: 3 'dstPolicy' is default to 'e_UNSPECIFIED' if not specified.
//: 3 'dstPolicy' defaults to 'e_UNSPECIFIED' if not specified.
//:
//: 4 QoI: Asserted precondition violations are detected when enabled.
//
Expand All @@ -2306,7 +2306,8 @@ int main(int argc, char *argv[])
//:
//: 4 Verify that, in appropriate build modes, defensive checks are
//: triggered for invalid input (using the 'BSLS_ASSERTTEST_*'
//: macros). (C-4)
//: macros). Use 'BSLS_ASSERTTEST_ASSERT_FAIL_RAW' for verifying
//: defensive checks triggered from other components. (C-4)
//
// Testing:
// convertLocalToUtc(Datetm *, const Datetm&, const ch *, Dst);
Expand Down Expand Up @@ -2473,8 +2474,7 @@ int main(int argc, char *argv[])
"\t'convertLocalToUtc' class method" << endl;
{
const bdlt::Datetime TIME(2010, 1, 1, 12, 0);

bdlt::Datetime resultTime;
bdlt::Datetime resultTime;
baltzo::LocalDatetime resultLcl;

ASSERT_PASS(Obj::convertLocalToUtc(&resultTime,
Expand Down Expand Up @@ -2502,6 +2502,20 @@ int main(int argc, char *argv[])
ASSERT_FAIL(Obj::convertLocalToUtc(&resultLcl,
TIME,
0));

#ifdef BSLS_ASSERT_SAFE_IS_ACTIVE
const bdlt::Datetime TIME2(1, 1, 1);

BSLS_ASSERTTEST_ASSERT_FAIL_RAW(Obj::convertLocalToUtc(
&resultTime,
TIME2,
SA));

BSLS_ASSERTTEST_ASSERT_FAIL_RAW(Obj::convertLocalToUtc(
&resultLcl,
TIME2,
SA));
#endif
}
}
} break;
Expand All @@ -2513,10 +2527,10 @@ int main(int argc, char *argv[])
//: 1 'k_UNSUPPORTED_ID' is returned when an invalid identifier is
//: passed in.
//:
//: 2 'baltzo::TimeZoneUtilImp::initLocalTime' is invoked return the
//: correct result.
//: 2 'baltzo::TimeZoneUtilImp::initLocalTime' is invoked and the
//: correct result is returned.
//:
//: 3 'dstPolicy' is default to 'e_UNSPECIFIED' if not specified.
//: 3 'dstPolicy' defaults to 'e_UNSPECIFIED' if not specified.
//:
//: 4 QoI: Asserted precondition violations are detected when enabled.
//
Expand All @@ -2533,7 +2547,8 @@ int main(int argc, char *argv[])
//:
//: 4 Verify that, in appropriate build modes, defensive checks are
//: triggered for invalid input (using the 'BSLS_ASSERTTEST_*'
//: macros). (C-4)
//: macros). Use 'BSLS_ASSERTTEST_ASSERT_FAIL_RAW' for verifying
//: defensive checks triggered from other components. (C-4)
//
// Testing:
// initLocalTime(DatetmTz *, const Datetm&, const ch *, Dst);
Expand Down Expand Up @@ -2714,10 +2729,10 @@ int main(int argc, char *argv[])
{
const bdlt::Datetime TIME(2010, 1, 1, 12, 0);

bdlt::Datetime resultTime;
bdlt::DatetimeTz resultTz;
bdlt::Datetime resultTime;
bdlt::DatetimeTz resultTz;
baltzo::LocalDatetime resultLcl;
Validity::Enum resultValidity;
Validity::Enum resultValidity;

ASSERT_PASS(Obj::initLocalTime(&resultTz,
TIME,
Expand Down Expand Up @@ -2745,6 +2760,18 @@ int main(int argc, char *argv[])
TIME,
0));

#ifdef BSLS_ASSERT_SAFE_IS_ACTIVE
const bdlt::Datetime TIME2(1, 1, 1);

BSLS_ASSERTTEST_ASSERT_FAIL_RAW(Obj::initLocalTime(&resultTz,
TIME2,
SA));

BSLS_ASSERTTEST_ASSERT_FAIL_RAW(Obj::initLocalTime(&resultLcl,
TIME2,
SA));
#endif

// ------------------------------------------------------------

ASSERT_PASS(Obj::initLocalTime(&resultTz,
Expand All @@ -2767,6 +2794,14 @@ int main(int argc, char *argv[])
TIME,
0));

#ifdef BSLS_ASSERT_SAFE_IS_ACTIVE
BSLS_ASSERTTEST_ASSERT_FAIL_RAW(Obj::initLocalTime(
&resultTz,
&resultValidity,
TIME2,
SA));
#endif

// ------------------------------------------------------------

ASSERT_PASS(Obj::initLocalTime(&resultLcl,
Expand All @@ -2788,6 +2823,14 @@ int main(int argc, char *argv[])
&resultValidity,
TIME,
0));

#ifdef BSLS_ASSERT_SAFE_IS_ACTIVE
BSLS_ASSERTTEST_ASSERT_FAIL_RAW(Obj::initLocalTime(
&resultLcl,
&resultValidity,
TIME2,
SA));
#endif
}
}
} break;
Expand Down
20 changes: 3 additions & 17 deletions groups/bal/baltzo/baltzo_timezoneutilimp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,8 @@ void TimeZoneUtilImp::resolveLocalTime(
BSLS_ASSERT(*resultValidity != Validity::e_VALID_UNIQUE
|| utcOffset1 == utcOffset2);

utcOffsetInSeconds = *resultValidity == Validity::e_INVALID
? utcOffset1 : utcOffset2;
utcOffsetInSeconds = *resultValidity == Validity::e_INVALID
? utcOffset1 : utcOffset2;
}

// Use the resolved UTC offset to create the resolved UTC value for
Expand All @@ -346,22 +346,8 @@ void TimeZoneUtilImp::resolveLocalTime(
bdlt::Datetime resolvedUtcTime = localTime;

const int rc = resolvedUtcTime.addMinutesIfValid(-utcOffsetInMinutes);
BSLS_REVIEW_OPT(0 == rc &&
"'addMinutes' would return an invalid Datetime.");

// The following block should be removed once the above 'BSLS_REVIEW_OPT'
// is replaced by 'BSLS_ASSERT'.
BSLS_ASSERT_SAFE(0 == rc); // See DRQS 174142713.
if (0 != rc) {
const int buffSize = 32;
char resolvedBuffer[buffSize];
resolvedUtcTime.printToBuffer(resolvedBuffer, buffSize);
BSLS_LOG_ERROR(
"DRQS 171227423: Converting 'resolvedUtcTime'=\"%s\" using "
"'resolvedUtcTime.addMinutes(-utcOffsetInMinutes)' where "
"'utcOffsetInMinutes=%d' would result in an invalid 'Datetime'.",
resolvedBuffer,
utcOffsetInMinutes);

resolvedUtcTime.addMinutes(-utcOffsetInMinutes);
}

Expand Down
6 changes: 4 additions & 2 deletions groups/bal/baltzo/baltzo_timezoneutilimp.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ struct TimeZoneUtilImp {
// whether 'localTime' is unique, ambiguous but valid, or invalid.
// Return 0 on success, and a non-zero value otherwise. A return
// status of 'ErrorCode::k_UNSUPPORTED_ID' indicates that 'timeZoneId'
// is not recognized.
// is not recognized. The behavior is undefined unless the result of
// the initialization falls within the supported epoch.

static int loadLocalTimePeriodForUtc(LocalTimePeriod *result,
const char *timeZoneId,
Expand Down Expand Up @@ -230,7 +231,8 @@ struct TimeZoneUtilImp {
// unique, valid but ambiguous, or invalid; load into the specified
// 'transitionIter' an iterator pointing to the transition that
// characterizes the attributes of 'localTime'. The behavior is
// undefined unless 'ZoneinfoUtil::isWellFormed(timeZone)' is 'true'.
// undefined unless 'ZoneinfoUtil::isWellFormed(timeZone)' is 'true'
// and the result of the resolution falls within the supported epoch.

};

Expand Down
67 changes: 39 additions & 28 deletions groups/bal/baltzo/baltzo_timezoneutilimp.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,8 @@ int main(int argc, char *argv[])
// Concerns:
//: 1 The parameters are correctly forwarded to 'resolveLocalTime'.
//:
//: 2 Asserted precondition violations are detected when enabled.
//:
//: 3 Return 'Err::k_UNSUPPORTED_ID' if an invalid time zone id is
//: passed.
//:
Expand All @@ -1496,10 +1498,10 @@ int main(int argc, char *argv[])
//
// Plan:
//: 1 Invoke 'initLocalTime' passing an invalid time zone id
//: and check the result. (C-6)
//: and check the result. (C-3)
//:
//: 2 Invoke 'initLocalTime' passing an invalid time zone
//: cache and check the result. (C-7)
//: cache and check the result. (C-4)
//:
//: 3 Using the table-driven technique:
//:
Expand All @@ -1508,6 +1510,9 @@ int main(int argc, char *argv[])
//: passed in as input, (d) the expected validity of the input
//: time, and (e) the expected local time value to be loaded in the
//: result (C-1).
//:
//: 4 Do negative testing to verify that asserts catch all the
//: undefined behavior in the contract. (C-2)
//
// Testing:
// 'initLocalTime(DatetimeTz *, Datetime& , char *, Dst, Cache *)
Expand Down Expand Up @@ -1741,10 +1746,9 @@ int main(int argc, char *argv[])
if (veryVerbose) cout << "\tCLASS METHOD 'initLocalTime'" << endl;
{
const bdlt::Datetime VALID_INPUT(2011, 04, 10);
const baltzo::Zoneinfo BAD;

bdlt::DatetimeTz result;
Validity::Enum resultValidity;
Validity::Enum resultValidity;

ASSERT_PASS(Obj::initLocalTime(&result,
&resultValidity,
Expand Down Expand Up @@ -1780,6 +1784,17 @@ int main(int argc, char *argv[])
NY,
DU,
0));

#ifdef BSLS_ASSERT_SAFE_IS_ACTIVE
const bdlt::Datetime VALID_INPUT2(1, 1, 1);

ASSERT_FAIL(Obj::initLocalTime(&result,
&resultValidity,
VALID_INPUT2,
SA,
DU,
&testCache));
#endif
}
}
} break;
Expand All @@ -1799,40 +1814,33 @@ int main(int argc, char *argv[])
//: 4 The (output) iterator refers to the specified input
//: 'baltzo::Zoneinfo'.
//:
//: 5 Return 'Err::k_UNSUPPORTED_ID' if an invalid time zone id is
//: passed.
//:
//: 6 Does not return 0 or 'Err::k_UNSUPPORTED_ID' if another error
//: occurs.
//: 5 Asserted precondition violations are detected when enabled.
//:
//:7 The correct transition and descriptor is applied for time zones
//: for which the local time always with DST *on*, passing in
//: different policies.
//: 6 The correct transition and descriptor is applied for time zones
//: for which the local time always with DST *on*, passing in
//: different policies.
//:
//:8 The correct transition and descriptor is applied for time zones
//: for which the local time always with DST *off*, passing in
//: different policies.
//: 7 The correct transition and descriptor is applied for time zones
//: for which the local time always with DST *off*, passing in
//: different policies.
//:
//:9 The correct transition and descriptor is applied for time zones
//: that have only one transition to DST in the past, passing in
//: different policies.
//: 8 The correct transition and descriptor is applied for time zones
//: that have only one transition to DST in the past, passing in
//: different policies.
//
// Plan:
//: 1 Invoke 'resolveLocalTime' passing an invalid time zone id
//: and check the result. (C-5)
//:
//: 2 Invoke 'resolveLocalTime' passing an invalid time zone
//: cache and check the result. (C-6)
//:
//: 3 Using the table-driven technique:
//: 1 Using the table-driven technique:
//:
//: 1 Specify a set values (one per row), including (a) time zone id,
//: (b) local time values to be passed in as input, (c) DST policy
//: passed in as input, (d) expected local-time result value, (e)
//: the expected validity of the input time, and (f) the attribute
//: values describing the expected local-time descriptor held by
//: the transition to which the loaded (output) iterator refers.
//: (C-1..4, 7..9)
//: (C-1..4, 6..8)
//:
//: 2 Do negative testing to verify that asserts catch all the
//: undefined behavior in the contract. (C-5)
//
// Testing:
// 'resolveLocalTime(...)
Expand Down Expand Up @@ -2356,10 +2364,8 @@ int main(int argc, char *argv[])
"\t'resolveLocalTime' class method " << endl;
{
const bdlt::Datetime VALID_INPUT(2011, 04, 10);
const bdlt::Datetime VALID_INPUT2(1, 1, 1);
const baltzo::Zoneinfo BAD;
const baltzo::Zoneinfo *NYZI = testCache.lookupZoneinfo(NY);
const baltzo::Zoneinfo *SAZI = testCache.lookupZoneinfo(SA);

bdlt::DatetimeTz result;
Iterator resultIterator;
Expand Down Expand Up @@ -2400,12 +2406,17 @@ int main(int argc, char *argv[])
DU,
BAD));

#ifdef BSLS_ASSERT_SAFE_IS_ACTIVE
const bdlt::Datetime VALID_INPUT2(1, 1, 1);
const baltzo::Zoneinfo *SAZI = testCache.lookupZoneinfo(SA);

ASSERT_FAIL(Obj::resolveLocalTime(&result,
&resultValidity,
&resultIterator,
VALID_INPUT2,
DU,
*SAZI));
#endif
}
}
} break;
Expand Down

0 comments on commit a3cb19f

Please sign in to comment.