summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2016-03-24 17:37:41 +0900
committerSlávek Banko <slavek.banko@axis.cz>2016-04-03 15:26:15 +0200
commit756ca239219c0cb83885517fe4f315444c221e22 (patch)
tree1692b74b563688fb8c984eb0ab4dc4cc047096f6
parent2663e4e350b93ed74479b5d6f872626f5e5f19aa (diff)
downloadtdelibs-756ca239219c0cb83885517fe4f315444c221e22.tar.gz
tdelibs-756ca239219c0cb83885517fe4f315444c221e22.zip
Fixed ISO8601 parsing in VCardTool. This relates to bug 2613.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it> (cherry picked from commit f9abaf54dabe13a48c6c8eed8926471c4cdabe97)
-rw-r--r--kabc/vcardtool.cpp101
1 files changed, 82 insertions, 19 deletions
diff --git a/kabc/vcardtool.cpp b/kabc/vcardtool.cpp
index 295360a03..e346c7c2f 100644
--- a/kabc/vcardtool.cpp
+++ b/kabc/vcardtool.cpp
@@ -20,6 +20,7 @@
#include <tqbuffer.h>
#include <tqdatastream.h>
+#include <tqregexp.h>
#include <tqstring.h>
#include "agent.h"
@@ -606,27 +607,89 @@ Addressee::List VCardTool::parseVCards( const TQString& vcard )
return addrList;
}
-TQDateTime VCardTool::parseDateTime( const TQString &str )
+TQDateTime VCardTool::parseDateTime(const TQString &str)
{
TQDateTime dateTime;
-
- if ( str.find( '-' ) == -1 ) { // is base format (yyyymmdd)
- dateTime.setDate( TQDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(),
- str.mid( 6, 2 ).toInt() ) );
-
- if ( str.find( 'T' ) ) // has time information yyyymmddThh:mm:ss
- dateTime.setTime( TQTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(),
- str.mid( 17, 2 ).toInt() ) );
-
- } else { // is extended format yyyy-mm-dd
- dateTime.setDate( TQDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(),
- str.mid( 8, 2 ).toInt() ) );
-
- if ( str.find( 'T' ) ) // has time information yyyy-mm-ddThh:mm:ss
- dateTime.setTime( TQTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(),
- str.mid( 17, 2 ).toInt() ) );
- }
-
+
+ /* This regex matches one of the following formats (description taken from
+ https://www.w3.org/TR/NOTE-datetime, copyright remains of the respective documentation author(s))
+ Year: YYYY (eg 1997)
+ Year and month: YYYY-MM (eg 1997-07)
+ Complete date: YYYY-MM-DD (eg 1997-07-16)
+ Complete date plus hours and minutes: YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
+ Complete date plus hours, minutes and seconds: YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
+ Complete date plus hours, minutes, seconds and a decimal fraction of a second
+ YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
+ where:
+ YYYY = four-digit year
+ MM = two-digit month (01=January, etc.)
+ DD = two-digit day of month (01 through 31)
+ hh = two digits of hour (00 through 23) (am/pm NOT allowed)
+ mm = two digits of minute (00 through 59)
+ ss = two digits of second (00 through 59)
+ s = one or more digits representing a decimal fraction of a second
+ TZD = time zone designator (Z or +hh:mm or -hh:mm)
+ */
+ TQRegExp re("(\\d{4})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d+))?)?"
+ "(?:(Z)|([+-])(\\d{2}):(\\d{2})))?)?)?", true, false);
+ if (!re.exactMatch(str))
+ {
+ // Try alternative format if pattern does not match
+ /* This regex matches one of the following formats (description adapted from
+ https://www.w3.org/TR/NOTE-datetime, copyright remains of the respective documentation author(s))
+ Year: YYYY (eg 1997)
+ Year and month: YYYYMM (eg 199707)
+ Complete date: YYYYMMDD (eg 19970716)
+ Complete date plus hours and minutes: YYYYMMDDThhmmTZD (eg 19970716T1920+0100)
+ Complete date plus hours, minutes and seconds: YYYYMMDDThhmmssTZD (eg 19970716T192030+0100)
+ Complete date plus hours, minutes, seconds and a decimal fraction of a second
+ YYYYMMDDThhmmsslTZD (eg 19970716T19203045+0100)
+ where:
+ YYYY = four-digit year
+ MM = two-digit month (01=January, etc.)
+ DD = two-digit day of month (01 through 31)
+ hh = two digits of hour (00 through 23) (am/pm NOT allowed)
+ mm = two digits of minute (00 through 59)
+ ss = two digits of second (00 through 59)
+ l = one or more digits representing a decimal fraction of a second
+ TZD = time zone designator (Z or +hhmm or -hhmm)
+ */
+ re.setPattern("(\\d{4})(?:(\\d{2})(?:(\\d{2})(?:T(\\d{2})(\\d{2})(?:(\\d{2})(?:(\\d+))?)?"
+ "(?:(Z)|([+-])(\\d{2})(\\d{2})))?)?)?");
+ }
+ if (re.exactMatch(str))
+ {
+ // Insert date
+ dateTime.setDate(TQDate(re.cap(1).toInt(), // year
+ !re.cap(2).isEmpty() ? re.cap(2).toInt() : 1, // month
+ !re.cap(3).isEmpty() ? re.cap(3).toInt() : 1)); // day
+ if (!re.cap(4).isEmpty())
+ {
+ // Time was also specified
+ int millis = 0;
+ if (!re.cap(7).isEmpty())
+ {
+ millis += re.cap(7)[0].isDigit() ? re.cap(7)[0].digitValue() * 100 : 0;
+ millis += re.cap(7)[1].isDigit() ? re.cap(7)[1].digitValue() * 10 : 0;
+ millis += re.cap(7)[2].isDigit() ? re.cap(7)[2].digitValue() : 0;
+ }
+ dateTime.setTime(TQTime(re.cap(4).toInt(), // hours
+ re.cap(5).toInt(), // minutes
+ !re.cap(6).isEmpty() ? re.cap(6).toInt() : 0, // seconds
+ millis)); // milliseconds
+ // Add time offset if time not in UTC format
+ if (!re.cap(9).isEmpty())
+ {
+ int offset = re.cap(10).toInt() * 3600 + re.cap(11).toInt() * 60;
+ if (re.cap(9) == "+")
+ {
+ // Local time zone is ahead of UTC time
+ offset = -offset;
+ }
+ dateTime = dateTime.addSecs(offset);
+ }
+ }
+ }
return dateTime;
}