diff --git a/Foundation/include/Poco/DateTimeParser.h b/Foundation/include/Poco/DateTimeParser.h index 5fa4d36d0..2d1882d83 100644 --- a/Foundation/include/Poco/DateTimeParser.h +++ b/Foundation/include/Poco/DateTimeParser.h @@ -59,24 +59,28 @@ class Foundation_API DateTimeParser public: static void parse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential); /// Parses a date and time in the given format from the given string. + /// Performs cleanup of the input string (trims spaces). /// Throws a SyntaxException if the string cannot be successfully parsed. /// Please see DateTimeFormatter::format() for a description of the format string. /// Class DateTimeFormat defines format strings for various standard date/time formats. static DateTime parse(const std::string& fmt, const std::string& str, int& timeZoneDifferential); /// Parses a date and time in the given format from the given string. + /// Performs cleanup of the input string (trims spaces). /// Throws a SyntaxException if the string cannot be successfully parsed. /// Please see DateTimeFormatter::format() for a description of the format string. /// Class DateTimeFormat defines format strings for various standard date/time formats. static bool tryParse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential); /// Parses a date and time in the given format from the given string. + /// Performs cleanup of the input string (trims spaces). /// Returns true if the string has been successfully parsed, false otherwise. /// Please see DateTimeFormatter::format() for a description of the format string. /// Class DateTimeFormat defines format strings for various standard date/time formats. static void parse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential); /// Parses a date and time from the given dateTime string. Before parsing, the method + /// performs cleanup of the input string (trims spaces) when cleanup is true and /// examines the dateTime string for a known date/time format. /// Throws a SyntaxException if the string cannot be successfully parsed. /// Please see DateTimeFormatter::format() for a description of the format string. @@ -84,12 +88,14 @@ public: static DateTime parse(const std::string& str, int& timeZoneDifferential); /// Parses a date and time from the given dateTime string. Before parsing, the method + /// performs cleanup of the input string (trims spaces) and /// examines the dateTime string for a known date/time format. /// Please see DateTimeFormatter::format() for a description of the format string. /// Class DateTimeFormat defines format strings for various standard date/time formats. static bool tryParse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential); /// Parses a date and time from the given dateTime string. Before parsing, the method + /// performs cleanup of the input string (trims spaces) and /// examines the dateTime string for a known date/time format. /// Please see DateTimeFormatter::format() for a description of the format string. /// Class DateTimeFormat defines format strings for various standard date/time formats. diff --git a/Foundation/src/DateTimeParser.cpp b/Foundation/src/DateTimeParser.cpp index 383f85c8d..9eb85f8c2 100644 --- a/Foundation/src/DateTimeParser.cpp +++ b/Foundation/src/DateTimeParser.cpp @@ -17,6 +17,7 @@ #include "Poco/DateTime.h" #include "Poco/Exception.h" #include "Poco/Ascii.h" +#include "Poco/String.h" namespace Poco { @@ -42,10 +43,17 @@ namespace Poco { { int i = 0; while (i < n && it != end && Ascii::isDigit(*it)) { var = var*10 + ((*it++) - '0'); i++; } while (i++ < n) var *= 10; } -void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential) +inline std::string cleanedInputString(const std::string& str) { + return Poco::trim(str); +} + +void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, DateTime& dateTime, int& timeZoneDifferential) +{ + const auto str = cleanedInputString(dtStr); + if (fmt.empty() || str.empty() || (DateTimeFormat::hasFormat(fmt) && !DateTimeFormat::isValid(str))) - throw SyntaxException("Invalid DateTimeString:" + str); + throw SyntaxException("Invalid DateTimeString:" + dtStr); int year = 0; int month = 0; @@ -223,8 +231,10 @@ DateTime DateTimeParser::parse(const std::string& str, int& timeZoneDifferential } -bool DateTimeParser::tryParse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential) +bool DateTimeParser::tryParse(const std::string& dtStr, DateTime& dateTime, int& timeZoneDifferential) { + const auto str = cleanedInputString(dtStr); + if (str.length() < 4) return false; if (str[3] == ',') diff --git a/Foundation/testsuite/src/DateTimeParserTest.cpp b/Foundation/testsuite/src/DateTimeParserTest.cpp index a6d6aba3b..8bae2bd74 100644 --- a/Foundation/testsuite/src/DateTimeParserTest.cpp +++ b/Foundation/testsuite/src/DateTimeParserTest.cpp @@ -751,6 +751,28 @@ void DateTimeParserTest::testGuess() assertTrue (tzd == 0); } +void DateTimeParserTest::testCleanup() +{ + int tzd; + + DateTime dt = DateTimeParser::parse("2005-01-08T12:30:00Z", tzd); + DateTime dt2 = DateTimeParser::parse(" 2005-01-08T12:30:00Z ", tzd); + + assertTrue (dt == dt2); + + assertTrue(DateTimeParser::tryParse(" 2005-01-08T12:30:00Z ", dt, tzd)); + + dt = DateTimeParser::parse(DateTimeFormat::ISO8601_FRAC_FORMAT, "2005-01-08T12:30:00.1Z", tzd); + dt2 = DateTimeParser::parse(DateTimeFormat::ISO8601_FRAC_FORMAT, "2005-01-08T12:30:00.1Z ", tzd); + + assertTrue (dt == dt2); + + assertTrue(DateTimeParser::tryParse(DateTimeFormat::ISO8601_FRAC_FORMAT, " 2005-01-08T12:30:00Z ", dt, tzd)); + + assertFalse(DateTimeParser::tryParse(DateTimeFormat::ISO8601_FRAC_FORMAT, " ", dt, tzd)); + +} + void DateTimeParserTest::testParseMonth() { @@ -790,7 +812,7 @@ void DateTimeParserTest::testParseMonth() month = DateTimeParser::parseMonth(it, str.end()); fail("Not a valid month name - must throw"); } - catch (SyntaxException&) + catch (const SyntaxException&) { } } @@ -834,7 +856,7 @@ void DateTimeParserTest::testParseDayOfWeek() dow = DateTimeParser::parseDayOfWeek(it, str.end()); fail("Not a valid weekday name - must throw"); } - catch (SyntaxException&) + catch (const SyntaxException&) { } } @@ -877,6 +899,7 @@ CppUnit::Test* DateTimeParserTest::suite() CppUnit_addTest(pSuite, DateTimeParserTest, testSORTABLE); CppUnit_addTest(pSuite, DateTimeParserTest, testCustom); CppUnit_addTest(pSuite, DateTimeParserTest, testGuess); + CppUnit_addTest(pSuite, DateTimeParserTest, testCleanup); CppUnit_addTest(pSuite, DateTimeParserTest, testParseMonth); CppUnit_addTest(pSuite, DateTimeParserTest, testParseDayOfWeek); diff --git a/Foundation/testsuite/src/DateTimeParserTest.h b/Foundation/testsuite/src/DateTimeParserTest.h index ea0b83e90..f25416971 100644 --- a/Foundation/testsuite/src/DateTimeParserTest.h +++ b/Foundation/testsuite/src/DateTimeParserTest.h @@ -35,6 +35,7 @@ public: void testSORTABLE(); void testCustom(); void testGuess(); + void testCleanup(); void testParseMonth(); void testParseDayOfWeek();