Fix ISO date string parsing/formatting

This commit is contained in:
Martchus 2018-01-29 16:24:39 +01:00
parent 9ed143e7d5
commit 2862c81a23
1 changed files with 19 additions and 9 deletions

View File

@ -119,9 +119,10 @@ DateTime DateTime::fromString(const char *str)
* \brief Parses the specified ISO date time denotation provided as C-style string. * \brief Parses the specified ISO date time denotation provided as C-style string.
* \returns Returns a pair where the first value is the parsed date time and the second value * \returns Returns a pair where the first value is the parsed date time and the second value
* a time span which can be subtracted from the first value to get the UTC time. * a time span which can be subtracted from the first value to get the UTC time.
* * \remarks Not all variants allowed by ISO 8601 are supported right now, eg. delimiters can not
* Not sure whether it is actually ISO conform, but the expected format is something like * be omitted.
* "2016-08-29T21:32:31.588539814+02:00". * The common form (something like "2016-08-29T21:32:31.588539814+02:00") is supported of course.
* \sa https://en.wikipedia.org/wiki/ISO_8601
*/ */
std::pair<DateTime, TimeSpan> DateTime::fromIsoString(const char *str) std::pair<DateTime, TimeSpan> DateTime::fromIsoString(const char *str)
{ {
@ -151,6 +152,8 @@ std::pair<DateTime, TimeSpan> DateTime::fromIsoString(const char *str)
} else if (c == '-') { } else if (c == '-') {
if (valueIndex < dayIndex) { if (valueIndex < dayIndex) {
++valueIndex; ++valueIndex;
} else if (++valueIndex == deltaHourIndex) {
deltaNegative = true;
} else { } else {
throw ConversionException("unexpected \"-\" after day"); throw ConversionException("unexpected \"-\" after day");
} }
@ -170,17 +173,19 @@ std::pair<DateTime, TimeSpan> DateTime::fromIsoString(const char *str)
} }
} else if ((c == '+') && (++valueIndex == deltaHourIndex)) { } else if ((c == '+') && (++valueIndex == deltaHourIndex)) {
deltaNegative = false; deltaNegative = false;
} else if ((c == '-') && (++valueIndex == deltaHourIndex)) { } else if ((c == 'Z') && (++valueIndex == deltaHourIndex)) {
deltaNegative = true; valueIndex += 2;
} else if (c == '\0') { } else if (c == '\0') {
break; break;
} else { } else {
throw ConversionException(argsToString("unexpected \"", c, '\"')); throw ConversionException(argsToString("unexpected \"", c, '\"'));
} }
} }
deltaNegative && (*deltaHourIndex = -*deltaHourIndex); auto delta(TimeSpan::fromMinutes(*deltaHourIndex * 60 + values[8]));
return make_pair(DateTime::fromDateAndTime(values[0], values[1], *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds), if (deltaNegative) {
TimeSpan::fromMinutes(*deltaHourIndex * 60 + values[8])); delta = TimeSpan(-delta.totalTicks());
}
return make_pair(DateTime::fromDateAndTime(values[0], values[1], *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds), delta);
} }
/*! /*!
@ -246,7 +251,12 @@ string DateTime::toIsoString(TimeSpan timeZoneDelta) const
} }
} }
if (!timeZoneDelta.isNull()) { if (!timeZoneDelta.isNull()) {
s << (timeZoneDelta.isNegative() ? '-' : '+'); if (timeZoneDelta.isNegative()) {
s << '-';
timeZoneDelta = TimeSpan(-timeZoneDelta.totalTicks());
} else {
s << '+';
}
s << setw(2) << timeZoneDelta.hours() << ':' << setw(2) << timeZoneDelta.minutes(); s << setw(2) << timeZoneDelta.hours() << ':' << setw(2) << timeZoneDelta.minutes();
} }
return s.str(); return s.str();