aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Löwe <benni@mytum.de>2016-08-20 16:46:22 (GMT)
committerBenjamin Löwe <benni@mytum.de>2016-08-20 16:46:22 (GMT)
commitdc229047663cb9e7568159c4a4a9256db78747b4 (patch)
tree54c95ddb0cc33bfa93ca69d5dd3d22c905760713
parent72959e96a329409aabb3d15a932c9d415ef1fbb8 (diff)
refactored VCardTool::parseDateTime and VCardTool::createDateTime
- split createDateTime into createDate and createTime so they can be used separately to either export the date or the time. (createDateTime always exported the time because dateTime.time().isValid() returns true when dateTime has a valid date.) - parseDateTime now also recognizes offsets from UTC (e.g. +0100 or -12:30) - createDateTime can now write offsets from UTC - when parseDateTime can't parse the time *timeValid is set to false (I would like to use this in my next patch to prevent that the birthday field is parsed with a time when no time is present) - adjusted customidentifiertest and importexportvcardtest because they failed now - added some tests for createDateTime and parseDateTime (I had to make them public therefore) REVIEW: 128655
-rw-r--r--autotests/CMakeLists.txt1
-rw-r--r--autotests/customidentifiertest.cpp2
-rw-r--r--autotests/datetimetest.cpp127
-rw-r--r--autotests/datetimetest.h38
-rw-r--r--autotests/importexportvcardtest.cpp3
-rw-r--r--src/vcardtool.cpp156
-rw-r--r--src/vcardtool.h8
7 files changed, 261 insertions, 74 deletions
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 9d8b4c0..56287dc 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -38,5 +38,6 @@ ecm_add_tests(birthdaytest.cpp
nicknametest.cpp
roletest.cpp
orgtest.cpp
+ datetimetest.cpp
NAME_PREFIX "kcontacts-" LINK_LIBRARIES KF5Contacts Qt5::Test KF5::ConfigCore Qt5::Gui)
diff --git a/autotests/customidentifiertest.cpp b/autotests/customidentifiertest.cpp
index f96defd..70d93e2 100644
--- a/autotests/customidentifiertest.cpp
+++ b/autotests/customidentifiertest.cpp
@@ -110,7 +110,7 @@ void CustomIdentifierTest::shouldExportVcard4()
ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
expected = QByteArray("BEGIN:VCARD\r\n"
"VERSION:4.0\r\n"
- "ANNIVERSARY: 120903T000000\r\n"
+ "ANNIVERSARY:00120903T000000\r\n"
"EMAIL:foo@kde.org\r\n"
"EMAIL:bla@kde.org\r\n"
"N:;;;;\r\n"
diff --git a/autotests/datetimetest.cpp b/autotests/datetimetest.cpp
new file mode 100644
index 0000000..f4692fa
--- /dev/null
+++ b/autotests/datetimetest.cpp
@@ -0,0 +1,127 @@
+/*
+ This file is part of kcontacts.
+ Copyright (c) 2016 Benjamin Löwe <benni@mytum.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "datetimetest.h"
+#include <QTest>
+#include <vcardtool.h>
+
+
+DateTimeTest::DateTimeTest(QObject *parent)
+ : QObject(parent)
+{
+}
+
+DateTimeTest::~DateTimeTest()
+{
+}
+
+void DateTimeTest::shouldParseDateTime()
+{
+ using namespace KContacts;
+
+ QDateTime expected, dt;
+ bool timeIsValid;
+
+ dt = VCardTool::parseDateTime(QStringLiteral("2016-01-20T12:33:30+0200"));
+ expected = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 30), Qt::OffsetFromUTC, 2 * 3600);
+ QCOMPARE(dt, expected);
+ QCOMPARE(dt.isValid(), true);
+
+ dt = VCardTool::parseDateTime(QStringLiteral("2016-01-20T12:33:30+02"));
+ QCOMPARE(dt, expected);
+ QCOMPARE(dt.isValid(), true);
+
+ dt = VCardTool::parseDateTime(QStringLiteral("20160120T123330+0200"));
+ QCOMPARE(dt, expected);
+ QCOMPARE(dt.isValid(), true);
+
+ dt = VCardTool::parseDateTime(QStringLiteral("2016-01-20T12:33Z"));
+ expected = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 0), Qt::UTC);
+ QCOMPARE(dt, expected);
+ QCOMPARE(dt.isValid(), true);
+
+ dt = VCardTool::parseDateTime(QStringLiteral("2016-01-20T12:33-0300"));
+ expected = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 0), Qt::OffsetFromUTC, -3 * 3600);
+ QCOMPARE(dt, expected);
+ QCOMPARE(dt.isValid(), true);
+
+ dt = VCardTool::parseDateTime(QStringLiteral("2016-01-20T12:33"), &timeIsValid);
+ expected = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 0), Qt::LocalTime);
+ QCOMPARE(dt, expected);
+ QCOMPARE(timeIsValid, true);
+ QCOMPARE(dt.isValid(), true);
+
+ dt = VCardTool::parseDateTime(QStringLiteral("2016-01-20"), &timeIsValid);
+ expected = QDateTime(QDate(2016, 1, 20), QTime(), Qt::LocalTime);
+ QCOMPARE(dt, expected);
+ QCOMPARE(dt.isValid(), true);
+ QCOMPARE(timeIsValid, false);
+ QCOMPARE(dt.time(), QTime(0, 0));
+
+ dt = VCardTool::parseDateTime(QStringLiteral("T1233Z"), &timeIsValid);
+ QCOMPARE(dt.isValid(), false);
+ QCOMPARE(timeIsValid, true);
+ QCOMPARE(dt.time(), QTime(12, 33));
+}
+
+void DateTimeTest::shouldCreateDateTime()
+{
+ using namespace KContacts;
+
+ QDateTime dt;
+ QString str, expected;
+
+ dt = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 30), Qt::UTC);
+ str = VCardTool::createDateTime(dt, VCard::v4_0);
+ expected = QStringLiteral("20160120T123330Z");
+ QCOMPARE(str, expected);
+
+ dt = QDateTime(QDate(2016, 1, 20), QTime(), Qt::UTC);
+ str = VCardTool::createDateTime(dt, VCard::v4_0);
+ expected = QStringLiteral("20160120T000000Z");
+ QCOMPARE(str, expected);
+
+ dt = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 30), Qt::LocalTime);
+ str = VCardTool::createDateTime(dt, VCard::v4_0);
+ expected = QStringLiteral("20160120T123330");
+ QCOMPARE(str, expected);
+
+ dt = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 30), Qt::OffsetFromUTC, -2 * 3600);
+ str = VCardTool::createDateTime(dt, VCard::v4_0);
+ expected = QStringLiteral("20160120T123330-0200");
+ QCOMPARE(str, expected);
+
+ dt = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 30), Qt::OffsetFromUTC, +2.5 * 3600);
+ str = VCardTool::createDateTime(dt, VCard::v4_0);
+ expected = QStringLiteral("20160120T123330+0230");
+ QCOMPARE(str, expected);
+
+ dt = QDateTime(QDate(2016, 1, 20), QTime(12, 33, 30), Qt::OffsetFromUTC, -2 * 3600);
+ str = VCardTool::createDateTime(dt, VCard::v3_0);
+ expected = QStringLiteral("2016-01-20T12:33:30-02:00");
+ QCOMPARE(str, expected);
+
+ dt = QDateTime(QDate(), QTime(12, 33, 30), Qt::OffsetFromUTC, -2 * 3600);
+ str = VCardTool::createDateTime(dt, VCard::v3_0);
+ expected = QStringLiteral("");
+ QCOMPARE(str, expected);
+}
+
+QTEST_MAIN(DateTimeTest)
diff --git a/autotests/datetimetest.h b/autotests/datetimetest.h
new file mode 100644
index 0000000..329810e
--- /dev/null
+++ b/autotests/datetimetest.h
@@ -0,0 +1,38 @@
+/*
+ This file is part of kcontacts.
+ Copyright (c) 2016 Benjamin Löwe <benni@mytum.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef DATETIMETEST_H
+#define DATETIMETEST_H
+
+#include <QObject>
+
+class DateTimeTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit DateTimeTest(QObject *parent = Q_NULLPTR);
+ ~DateTimeTest();
+
+private Q_SLOTS:
+ void shouldParseDateTime();
+ void shouldCreateDateTime();
+};
+
+#endif // DATETIMETEST_H
diff --git a/autotests/importexportvcardtest.cpp b/autotests/importexportvcardtest.cpp
index c425b44..6ea5899 100644
--- a/autotests/importexportvcardtest.cpp
+++ b/autotests/importexportvcardtest.cpp
@@ -62,7 +62,7 @@ void ImportExportVCardTest::shouldExportFullTestVcard4()
"UID:urn:uuid:b8767877-b4a1-4c70-9acc-505d3819e519\r\n"
"CATEGORIES:FICTION,LITERATURE\r\n"
"PRODID:-//KADDRESSBOOK//NONSGML Version 1//EN\r\n"
- "REV:2014722T222710Z\r\n"
+ "REV:20140722T222710Z\r\n"
"URL;TYPE=home:https://sherlockholmes.com\r\n"
"KEY;MEDIATYPE=application/pgp-keys:https://sherlockholmes.com/sherlock-holmes.pub.asc\r\n"
"CALURI;PREF=1:https://sherlockholmes.com/calendar/sherlockholmes\r\n"
@@ -91,6 +91,7 @@ void ImportExportVCardTest::shouldExportFullTestVcard4()
"N:Holmes;Sherlock;;Mr;\r\n"
"NICKNAME:Shirley\r\n"
"PRODID:-//KADDRESSBOOK//NONSGML Version 1//EN\r\n"
+ "REV:20140722T222710Z\r\n"
"ROLE:Detective\r\n"
"TEL;PREF=1;VALUE=uri:ext=5555\r\n"
"TEL;TYPE=\"cell,voice\";VALUE=uri:tel:+44-555-555-6666\r\n"
diff --git a/src/vcardtool.cpp b/src/vcardtool.cpp
index e3684ba..b0bcb71 100644
--- a/src/vcardtool.cpp
+++ b/src/vcardtool.cpp
@@ -32,6 +32,7 @@
#include <QtCore/QString>
#include <QtCore/QBuffer>
#include <QDebug>
+#include <QRegularExpression>
using namespace KContacts;
@@ -1180,93 +1181,110 @@ Addressee::List VCardTool::parseVCards(const QByteArray &vcard) const
return addrList;
}
-QDateTime VCardTool::parseDateTime(const QString &str) const
+QDateTime VCardTool::parseDateTime(const QString &str, bool *timeValid)
{
- QDate date;
- QTime time;
-
- if (str.indexOf(QLatin1Char('-')) == -1) { // is base format (yyyymmdd)
- date = QDate(str.leftRef(4).toInt(), str.midRef(4, 2).toInt(),
- str.midRef(6, 2).toInt());
- } else { // is extended format yyyy-mm-dd
- date = QDate(str.leftRef(4).toInt(), str.midRef(5, 2).toInt(),
- str.midRef(8, 2).toInt());
- }
+ const QStringList strings = str.split(QLatin1Char('T'));
- // does it also contain a time ? (Note: mm, ss are optional according ISO-8601)
- int timeStart = str.indexOf(QLatin1Char('T'));
- if (timeStart >= 0) {
- int hour = 0, minute = 0, second = 0;
+ QString dateString = strings.at(0);
+ dateString = dateString.replace(QLatin1String("-"), QLatin1String(""));
+ QDate date = QDate::fromString(dateString, QStringLiteral("yyyyMMdd"));
- hour = str.midRef(timeStart + 1, 2).toInt(); // hour must always be given
-
- if (str.indexOf(QLatin1Char(':'), timeStart + 1) > 0) { // extended format (hh:mm:ss)
- if (str.length() >= (timeStart + 5)) {
- minute = str.midRef(timeStart + 4, 2).toInt();
- if (str.length() >= (timeStart + 8)) {
- second = str.midRef(timeStart + 7, 2).toInt();
+ QTime time;
+ Qt::TimeSpec spec = Qt::LocalTime;
+ int offsetSecs = 0;
+ if (strings.length() > 1) {
+ QString timeString = strings.at(1);
+ timeString = timeString.replace(QLatin1String(":"), QLatin1String(""));
+ QStringList timeStrings = timeString.split(QRegularExpression(QStringLiteral("[Z+-]")));
+ const QString hhmmssString = timeStrings.at(0);
+ switch(hhmmssString.size())
+ {
+ case 2:
+ time = QTime::fromString(hhmmssString, QStringLiteral("hh"));
+ break;
+ case 4:
+ time = QTime::fromString(hhmmssString, QStringLiteral("hhmm"));
+ break;
+ case 6:
+ time = QTime::fromString(hhmmssString, QStringLiteral("hhmmss"));
+ break;
+ }
+ if (timeStrings.length() > 1) {
+ if (timeString.contains(QLatin1Char('Z'))) {
+ spec = Qt::UTC;
+ } else {
+ spec = Qt::OffsetFromUTC;
+ QTime offsetTime;
+ const QString offsetString = timeStrings.at(1);
+ switch(offsetString.size())
+ {
+ case 2:
+ offsetTime = QTime::fromString(offsetString, QStringLiteral("hh"));
+ break;
+ case 4:
+ offsetTime = QTime::fromString(offsetString, QStringLiteral("hhmm"));
+ break;
}
+ offsetSecs = offsetTime.hour() * 3600 + offsetTime.minute() * 60;
}
- } else { // basic format (hhmmss)
- if (str.length() >= (timeStart + 4)) {
- minute = str.midRef(timeStart + 3, 2).toInt();
- if (str.length() >= (timeStart + 6)) {
- second = str.midRef(timeStart + 5, 2).toInt();
- }
+ if (timeString.contains(QLatin1Char('-'))) {
+ offsetSecs *= -1;
}
}
-
- time = QTime(hour, minute, second);
+ }
+ if (timeValid) {
+ *timeValid = time.isValid();
}
- Qt::TimeSpec spec = (str.right(1) == QLatin1String("Z")) ? Qt::UTC : Qt::LocalTime;
-
- QDateTime dateTime(date);
+ return QDateTime(date, time, spec, offsetSecs);
+}
- if (time.isValid()) {
- dateTime.setTime(time);
+QString VCardTool::createDateTime(const QDateTime &dateTime, VCard::Version version)
+{
+ if (!dateTime.date().isValid()) {
+ return QString();
}
-
- dateTime.setTimeSpec(spec);
- return dateTime;
+ QString str = createDate(dateTime.date(), version);
+ str += createTime(dateTime.time(), version);
+ if (dateTime.timeSpec() == Qt::UTC) {
+ str += QLatin1Char('Z');
+ } else if (dateTime.timeSpec() == Qt::OffsetFromUTC) {
+ const int offsetSecs = dateTime.offsetFromUtc();
+ if (offsetSecs >= 0) {
+ str += QLatin1Char('+');
+ } else {
+ str += QLatin1Char('-');
+ }
+ QTime offsetTime = QTime(0, 0).addSecs(abs(offsetSecs));
+ if (version == VCard::v4_0) {
+ str += offsetTime.toString(QStringLiteral("HHmm"));
+ } else {
+ str += offsetTime.toString(QStringLiteral("HH:mm"));
+ }
+ }
+ return str;
}
-QString VCardTool::createDateTime(const QDateTime &dateTime, VCard::Version version) const
+QString VCardTool::createDate(const QDate &date, VCard::Version version)
{
- QString str;
+ QString format;
if (version == VCard::v4_0) {
- if (dateTime.date().isValid()) {
- str.sprintf("%4d%02d%02d", dateTime.date().year(), dateTime.date().month(),
- dateTime.date().day());
- if (dateTime.time().isValid()) {
- QString tmp;
- tmp.sprintf("T%02d%02d%02d", dateTime.time().hour(), dateTime.time().minute(),
- dateTime.time().second());
- str += tmp;
-
- if (dateTime.timeSpec() == Qt::UTC) {
- str += QLatin1Char('Z');
- }
- }
- }
+ format = QStringLiteral("yyyyMMdd");
+ } else {
+ format = QStringLiteral("yyyy-MM-dd");
+ }
+ return date.toString(format);
+}
+QString VCardTool::createTime(const QTime &time, VCard::Version version)
+{
+ QString format;
+ if (version == VCard::v4_0) {
+ format = QStringLiteral("HHmmss");
} else {
- if (dateTime.date().isValid()) {
- str.sprintf("%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(),
- dateTime.date().day());
- if (dateTime.time().isValid()) {
- QString tmp;
- tmp.sprintf("T%02d:%02d:%02d", dateTime.time().hour(), dateTime.time().minute(),
- dateTime.time().second());
- str += tmp;
-
- if (dateTime.timeSpec() == Qt::UTC) {
- str += QLatin1Char('Z');
- }
- }
- }
+ format = QStringLiteral("HH:mm:ss");
}
- return str;
+ return QStringLiteral("T") + time.toString(format);
}
Picture VCardTool::parsePicture(const VCardLine &line) const
diff --git a/src/vcardtool.h b/src/vcardtool.h
index 2558c94..48890ed 100644
--- a/src/vcardtool.h
+++ b/src/vcardtool.h
@@ -58,6 +58,11 @@ public:
*/
Addressee::List parseVCards(const QByteArray &vcard) const;
+ static QDateTime parseDateTime(const QString &str, bool *timeValid = 0);
+ static QString createDateTime(const QDateTime &dateTime, VCard::Version version);
+ static QString createDate(const QDate &date, VCard::Version version);
+ static QString createTime(const QTime &time, VCard::Version version);
+
private:
QByteArray createVCards(const Addressee::List &list,
@@ -69,9 +74,6 @@ private:
*/
QStringList splitString(QChar sep, const QString &value) const;
- QDateTime parseDateTime(const QString &str) const;
- QString createDateTime(const QDateTime &dateTime, VCard::Version version) const;
-
Picture parsePicture(const VCardLine &line) const;
VCardLine createPicture(const QString &identifier, const Picture &pic, VCard::Version version) const;