From 101433190f07511e5bc13c1a8173bc2db1dfa5e2 Mon Sep 17 00:00:00 2001 From: Dimitri Schoolwerth Date: Tue, 20 Jun 2017 16:38:14 +0400 Subject: [PATCH] Add time zone parsing support for HH:MM --- src/common/datetimefmt.cpp | 43 +++++++++++++++++++++++++++------ tests/datetime/datetimetest.cpp | 16 ++++++++++++ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/common/datetimefmt.cpp b/src/common/datetimefmt.cpp index 26ba97be77..916486242a 100644 --- a/src/common/datetimefmt.cpp +++ b/src/common/datetimefmt.cpp @@ -90,11 +90,13 @@ namespace // all the functions below taking non-const wxString::const_iterator p advance // it until the end of the match -// scans all digits (but no more than len) and returns the resulting number +// Scans all digits (but no more than len) and returns the resulting number. +// Optionally writes number of digits scanned to numScannedDigits. bool GetNumericToken(size_t len, wxString::const_iterator& p, const wxString::const_iterator& end, - unsigned long *number) + unsigned long *number, + size_t *numScannedDigits = NULL) { size_t n = 1; wxString s; @@ -106,6 +108,11 @@ bool GetNumericToken(size_t len, break; } + if (numScannedDigits) + { + *numScannedDigits = n - 1; + } + return !s.empty() && s.ToULong(number); } @@ -1499,14 +1506,34 @@ wxDateTime::ParseFormat(const wxString& date, else return false; // no match - // here should follow 4 digits HHMM ++input; - unsigned long tzHourMin; - if ( !GetNumericToken(4, input, end, &tzHourMin) ) - return false; // no match - const unsigned hours = tzHourMin / 100; - const unsigned minutes = tzHourMin % 100; + // Here should follow exactly 2 digits for hours (HH). + const size_t numRequiredDigits = 2; + size_t numScannedDigits; + + unsigned long hours; + if ( !GetNumericToken(numRequiredDigits, input, end, + &hours, &numScannedDigits) + || numScannedDigits != numRequiredDigits) + { + return false; // No match. + } + + // Optionally followed by a colon separator. + if ( input != end && *input == wxS(':') ) + { + ++input; + } + + // Followed by exactly 2 digits for minutes (MM). + unsigned long minutes; + if ( !GetNumericToken(numRequiredDigits, input, end, + &minutes, &numScannedDigits) + || numScannedDigits != numRequiredDigits) + { + return false; // No match. + } if ( hours > 12 || minutes > 59 ) return false; // bad format diff --git a/tests/datetime/datetimetest.cpp b/tests/datetime/datetimetest.cpp index b3a7cfe1f0..37f1f18a2f 100644 --- a/tests/datetime/datetimetest.cpp +++ b/tests/datetime/datetimetest.cpp @@ -906,9 +906,25 @@ void DateTimeTestCase::TestTimeZoneParse() // Z as UTC designator. { "13:37Z", true }, + // Colon as HH and MM separator. + { "17:37+04:00", true }, + + // // Colon separator and non-zero MM. + { "09:07-04:30", true }, + { "19:22+05:45", true }, + // Some invalid ones too. + { "00:00-1300" }, // Offset out of range. { "00:00+1300" }, // Offset out of range. + + // Not exactly 2 digits for hours and minutes. + { "17:37+4" }, + { "17:37+400" }, + { "17:37+040" }, + { "17:37+4:0" }, + { "17:37+4:00" }, + { "17:37+04:0" }, }; for ( size_t n = 0; n < WXSIZEOF(parseTestTimeZones); ++n )