Allow omitting month and day when parsing ISO date

This leaves only the year as mandatory component (other components
can already be omitted).
This commit is contained in:
Martchus 2020-04-24 22:15:49 +02:00
parent 73470d0b65
commit c834f8923d
2 changed files with 12 additions and 1 deletions

View File

@ -119,6 +119,8 @@ DateTime DateTime::fromString(const char *str)
std::pair<DateTime, TimeSpan> DateTime::fromIsoString(const char *str)
{
int values[9] = { 0 };
int *const yearIndex = values + 0;
int *const monthIndex = values + 1;
int *const dayIndex = values + 2;
int *const hourIndex = values + 3;
int *const secondsIndex = values + 5;
@ -178,7 +180,13 @@ std::pair<DateTime, TimeSpan> DateTime::fromIsoString(const char *str)
if (deltaNegative) {
delta = TimeSpan(-delta.totalTicks());
}
return make_pair(DateTime::fromDateAndTime(values[0], values[1], *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds), delta);
if (valueIndex < monthIndex && !*monthIndex) {
*monthIndex = 1;
}
if (valueIndex < dayIndex && !*dayIndex) {
*dayIndex = 1;
}
return make_pair(DateTime::fromDateAndTime(*yearIndex, *monthIndex, *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds), delta);
}
/*!

View File

@ -171,6 +171,9 @@ void ChronoTests::testDateTime()
CPPUNIT_ASSERT_EQUAL(600, test5.first.nanosecond());
CPPUNIT_ASSERT_EQUAL("2017-08-23T19:40:15.9850776-02:30"s, test5.first.toIsoString(test5.second));
// test further variants
CPPUNIT_ASSERT_EQUAL_MESSAGE("only year", DateTime::fromDate(2008), DateTime::fromIsoStringGmt("2008"));
CPPUNIT_ASSERT_EQUAL_MESSAGE("only year and month", DateTime::fromDate(2008, 12), DateTime::fromIsoStringGmt("2008-12"));
CPPUNIT_ASSERT_EQUAL_MESSAGE("only date", DateTime::fromDate(2008, 12, 5), DateTime::fromIsoStringGmt("2008-12-05"));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Zulu time", TimeSpan(), DateTime::fromIsoString("2017-08-23T19:40:15.985077682Z").second);
CPPUNIT_ASSERT_EQUAL_MESSAGE("no minutes", TimeSpan::fromHours(3), DateTime::fromIsoString("2017-08-23T19:40:15.985077682+03").second);
const auto test6 = DateTime::fromIsoString("1970-01-01T01:02:03+01:00");