diff --git a/autotests/testicalformat.h b/autotests/testicalformat.h --- a/autotests/testicalformat.h +++ b/autotests/testicalformat.h @@ -33,6 +33,8 @@ void testVolatileProperties(); void testCuType(); void testAlarm(); + void testDateTime_data(); + void testDateTime(); }; #endif diff --git a/autotests/testicalformat.cpp b/autotests/testicalformat.cpp --- a/autotests/testicalformat.cpp +++ b/autotests/testicalformat.cpp @@ -170,3 +170,48 @@ Alarm::Ptr alarm2 = event2->alarms()[0]; QCOMPARE(*alarm, *alarm2); } + +void ICalFormatTest::testDateTime_data() +{ + QTest::addColumn("dtStartData"); + QTest::addColumn("dtStart"); + + QTest::newRow("clock time") + << QByteArray("DTSTART:20191113T130000") + << QDateTime(QDate(2019, 11, 13), QTime(13, 00), Qt::LocalTime); + QTest::newRow("date") + << QByteArray("DTSTART;VALUE=DATE:20191113") + << QDateTime(QDate(2019, 11, 13)); + QTest::newRow("UTC time") + << QByteArray("DTSTART:20191113T130000Z") + << QDateTime(QDate(2019, 11, 13), QTime(13, 00), Qt::UTC); + QTest::newRow("time zone time") + << QByteArray("DTSTART;TZID=Europe/Paris:20191113T130000") + << QDateTime(QDate(2019, 11, 13), QTime(13, 00), QTimeZone("Europe/Paris")); +} + +void ICalFormatTest::testDateTime() +{ + QFETCH(QByteArray, dtStartData); + QFETCH(QDateTime, dtStart); + + // test fromString(QString) + const QByteArray serializedCalendar + = "BEGIN:VCALENDAR\nPRODID:-//K Desktop Environment//NONSGML libkcal 3.2//EN\nVERSION:2.0\nBEGIN:VEVENT\nUID:12345\n" + + dtStartData + + "\nEND:VEVENT\nEND:VCALENDAR"; + + ICalFormat format; + Incidence::Ptr event = format.fromString(QString::fromUtf8(serializedCalendar)); + QVERIFY(event); + QCOMPARE(dtStart, event->dtStart()); + + const QByteArray output = format.toRawString(event); + const QList lines = output.split('\n'); + for (const QByteArray &line: lines) { + if (line.startsWith(QByteArray("DTSTART"))) { + QCOMPARE(line.chopped(1), dtStartData); + break; + } + } +} diff --git a/src/icalformat_p.cpp b/src/icalformat_p.cpp --- a/src/icalformat_p.cpp +++ b/src/icalformat_p.cpp @@ -2369,11 +2369,13 @@ t.zone = nullptr; // zone is NOT set #if defined(USE_ICAL_3) if (datetime.timeSpec() == Qt::UTC || + (datetime.timeSpec() == Qt::TimeZone && datetime.timeZone() == QTimeZone::utc()) || (datetime.timeSpec() == Qt::OffsetFromUTC && datetime.offsetFromUtc() == 0)) { t = icaltime_convert_to_zone(t, icaltimezone_get_utc_timezone()); } #else t.is_utc = datetime.timeSpec() == Qt::UTC || + (datetime.timeSpec() == Qt::TimeZone && datetime.timeZone() == QTimeZone::utc()) || (datetime.timeSpec() == Qt::OffsetFromUTC && datetime.offsetFromUtc() == 0); #endif return t; @@ -2445,9 +2447,9 @@ QTimeZone qtz; #if defined(USE_ICAL_3) - if (!icaltime_is_utc(t)) { + if (!icaltime_is_utc(t) && dt.timeSpec() == Qt::TimeZone) { #else - if (!t.is_utc) { + if (!t.is_utc && dt.timeSpec() == Qt::TimeZone) { #endif qtz = dt.timeZone(); } @@ -2496,21 +2498,21 @@ // First try to get the timezone from cache timeZone = tzCache->tzForTime(QDateTime({ t.year, t.month, t.day }, {}), tzid); } - if (!timeZone.isValid()) { + if (!timeZone.isValid() && !tzid.isEmpty()) { // Fallback to trying to match against Qt timezone timeZone = QTimeZone(tzid); } - if (!timeZone.isValid()) { - // Finally, give up and assume local timezone - timeZone = QTimeZone::systemTimeZone(); - } + // If Time zone is still invalid, we will use LocalTime as TimeSpec. + } + QTime resultTime; + if (!t.is_date) { + resultTime = QTime(t.hour, t.minute, t.second); } QDateTime result; - if (t.is_date) { - result = QDateTime(QDate(t.year, t.month, t.day), {}, timeZone); + if (timeZone.isValid()) { + result = QDateTime(QDate(t.year, t.month, t.day), resultTime, timeZone); } else { - result = QDateTime(QDate(t.year, t.month, t.day), - QTime(t.hour, t.minute, t.second), timeZone); + result = QDateTime(QDate(t.year, t.month, t.day), resultTime); } return utc ? result.toUTC() : result; } diff --git a/src/icaltimezones.cpp b/src/icaltimezones.cpp --- a/src/icaltimezones.cpp +++ b/src/icaltimezones.cpp @@ -138,7 +138,7 @@ const ICalTimeZone tz = mCache.value(tzid); if (!tz.qZone.isValid()) { - return QTimeZone::systemTimeZone(); + return QTimeZone(); } // If the matched timezone is one of the UTC offset timezones, we need to make