diff --git a/src/common/datetimefmt.cpp b/src/common/datetimefmt.cpp index 79993651cd..9da429c7c8 100644 --- a/src/common/datetimefmt.cpp +++ b/src/common/datetimefmt.cpp @@ -1866,17 +1866,19 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end) // tokenize the string while ( p != pEnd ) { - // skip white space and date delimiters - if ( wxStrchr(".,/-\t\r\n ", *p) ) - { - ++p; - continue; - } - // modify copy of the iterator as we're not sure if the next token is // still part of the date at all wxString::const_iterator pCopy = p; + // skip white space and date delimiters + while ( pCopy != pEnd && wxStrchr(".,/-\t\r\n ", *pCopy) ) + { + ++pCopy; + } + + if ( pCopy == pEnd ) + break; + // we can have either alphabetic or numeric token, start by testing if // it's the latter unsigned long val; @@ -2033,9 +2035,9 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end) { const wxString ord = wxGetTranslation(ordinals[n]); const size_t len = ord.length(); - if ( date.compare(p - pBegin, len, ord) == 0 ) + if ( date.compare(pCopy - pBegin, len, ord) == 0 ) { - p += len; + pCopy += len; break; } } diff --git a/tests/datetime/datetimetest.cpp b/tests/datetime/datetimetest.cpp index bb1086eca9..6104d975fe 100644 --- a/tests/datetime/datetimetest.cpp +++ b/tests/datetime/datetimetest.cpp @@ -913,13 +913,33 @@ void DateTimeTestCase::TestTimeParse() wxDateTime dt; // Parsing standard formats should work. - CPPUNIT_ASSERT( dt.ParseTime("12:34:56") ); - CPPUNIT_ASSERT_EQUAL( "12:34:56", dt.FormatISOTime() ); + const char* end = dt.ParseTime("12:34:56"); + CPPUNIT_ASSERT( end ); + if ( end ) + { + CPPUNIT_ASSERT_EQUAL( "12:34:56", dt.FormatISOTime() ); + CPPUNIT_ASSERT_EQUAL( "", wxString(end) ); + } + dt.ResetTime(); + + // Valid, but followed by something. + end = dt.ParseTime("12:34:56 0123 something"); + CPPUNIT_ASSERT( end ); + if ( end ) + { + CPPUNIT_ASSERT_EQUAL( "12:34:56", dt.FormatISOTime() ); + CPPUNIT_ASSERT_EQUAL( " 0123 something", wxString(end) ); + } + dt.ResetTime(); // Parsing just hours should work too. - dt.ResetTime(); - CPPUNIT_ASSERT( dt.ParseTime("17") ); - CPPUNIT_ASSERT_EQUAL( "17:00:00", dt.FormatISOTime() ); + end = dt.ParseTime("17"); + CPPUNIT_ASSERT( end ); + if ( end ) + { + CPPUNIT_ASSERT_EQUAL( "17:00:00", dt.FormatISOTime() ); + CPPUNIT_ASSERT_EQUAL( "", wxString(end) ); + } // Parsing gibberish shouldn't work. CPPUNIT_ASSERT( !dt.ParseTime("bloordyblop") ); @@ -1139,6 +1159,18 @@ void DateTimeTestCase::TestParseRFC822() false }, + { + "Sun 01 Jun 2008 16:39:10 +02", // truncated time zone + { 0 }, + false + }, + + { + "Sun 01 Jun 2008 16:39:10 G", // truncated time zone + { 0 }, + false + }, + { "Sat, 18 Dec 1999 10:48:30", // TZ missing { 0 }, @@ -1207,17 +1239,27 @@ void DateTimeTestCase::TestDateParse() const char *str; Date date; // NB: this should be in UTC bool good; + const char* beyondEnd; // what remains unprocessed of the input } parseTestDates[] = { - { "21 Mar 2006", { 21, wxDateTime::Mar, 2006 }, true }, - { "29 Feb 1976", { 29, wxDateTime::Feb, 1976 }, true }, - { "Feb 29 1976", { 29, wxDateTime::Feb, 1976 }, true }, - { "31/03/06", { 31, wxDateTime::Mar, 6 }, true }, - { "31/03/2006", { 31, wxDateTime::Mar, 2006 }, true }, + { "21 Mar 2006", { 21, wxDateTime::Mar, 2006 }, true, ""}, + { "29 Feb 1976", { 29, wxDateTime::Feb, 1976 }, true, "" }, + { "Feb 29 1976", { 29, wxDateTime::Feb, 1976 }, true, "" }, + { "31/03/06", { 31, wxDateTime::Mar, 6 }, true, "" }, + { "31/03/2006", { 31, wxDateTime::Mar, 2006 }, true, "" }, + { "Thu 20 Jun 2019", { 20, wxDateTime::Jun, 2019 }, true, "" }, + { "20 Jun 2019 Thu", { 20, wxDateTime::Jun, 2019 }, true, "" }, + { "Dec sixth 2017", { 6, wxDateTime::Dec, 2017 }, true, "" }, + + // valid, but followed by something + { "Dec 31 1979 was the end of 70s", + { 31, wxDateTime::Dec, 1979 }, true, " was the end of 70s" }, // some invalid ones too { "29 Feb 2006" }, { "31/04/06" }, + { "Sat 20 Jun 2019" }, // it was not a Saturday + { "20 Jun 2019 Sat" }, // it was not a Saturday { "bloordyblop" }, { "2 . . " }, { "14:30:15" }, @@ -1243,6 +1285,7 @@ void DateTimeTestCase::TestDateParse() ); CPPUNIT_ASSERT_EQUAL( parseTestDates[n].date.DT(), dt ); + CPPUNIT_ASSERT_EQUAL( wxString(parseTestDates[n].beyondEnd), wxString(end) ); } else // failed to parse { @@ -1345,18 +1388,21 @@ void DateTimeTestCase::TestDateTimeParse() const char *str; Date date; // NB: this should be in UTC bool good; + const char *beyondEnd; // what remains unprocessed of the input } parseTestDates[] = { { "Thu 22 Nov 2007 07:40:00 PM", { 22, wxDateTime::Nov, 2007, 19, 40, 0 }, - true + true, + "" }, { "2010-01-04 14:30", { 4, wxDateTime::Jan, 2010, 14, 30, 0 }, - true + true, + "" }, { @@ -1369,15 +1415,33 @@ void DateTimeTestCase::TestDateTimeParse() { "bloordyblop", { 1, wxDateTime::Jan, 9999, 0, 0, 0}, - false + false, + "bloordyblop" + }, + + { + "2022-03-09 19:12:05 and some text after space", + { 9, wxDateTime::Mar, 2022, 19, 12, 5, -1 }, + true, + " and some text after space" + }, + + { + // something other than a space right after time + "2022-03-09 19:12:05AAaaaa", + { 9, wxDateTime::Mar, 2022, 19, 12, 5, -1 }, + true, + "AAaaaa" }, { "2012-01-01 10:12:05 +0100", { 1, wxDateTime::Jan, 2012, 10, 12, 5, -1 }, - true // ParseDateTime does know yet +0100, but - // ignoring that, parsing still succeeds + true, // ParseDateTime does know yet +0100, but + // ignoring that, parsing still succeeds + " +0100" }, + }; wxGCC_WARNING_RESTORE(missing-field-initializers) @@ -1400,6 +1464,7 @@ void DateTimeTestCase::TestDateTimeParse() ); CPPUNIT_ASSERT_EQUAL( parseTestDates[n].date.DT(), dt ); + CPPUNIT_ASSERT_EQUAL( wxString(parseTestDates[n].beyondEnd), wxString(end) ); } else // failed to parse {