Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kcalendarcore for openSUSE:Factory 
checked in at 2021-10-18 21:58:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kcalendarcore (Old)
 and      /work/SRC/openSUSE:Factory/.kcalendarcore.new.1890 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kcalendarcore"

Mon Oct 18 21:58:26 2021 rev:25 rq:924415 version:5.87.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kcalendarcore/kcalendarcore.changes      
2021-09-16 23:14:55.323813874 +0200
+++ /work/SRC/openSUSE:Factory/.kcalendarcore.new.1890/kcalendarcore.changes    
2021-10-18 22:00:00.429998733 +0200
@@ -1,0 +2,16 @@
+Sun Oct  3 20:33:35 UTC 2021 - Christophe Giboudeaux <[email protected]>
+
+- Update to 5.87.0
+  * New feature release
+  * For more details please see:
+  * https://kde.org/announcements/frameworks/5/5.87.0
+- Changes since 5.86.0:
+  * Add Gitlab CI configuration
+  * Set the correct last modified time when creating an exception for a 
recurring event.
+  * icalformat_p.cpp - support ATTACH parameter FILENAME (kde#436161)
+  * Add Qt5Gui as dependency in pkgconfig file.
+  * autotests/testicaltimezones.cpp - fix unused variable warning
+  * Read floating date time as LocalTime
+  * Implement PERIOD support in RDATE
+
+-------------------------------------------------------------------

Old:
----
  kcalendarcore-5.86.0.tar.xz
  kcalendarcore-5.86.0.tar.xz.sig

New:
----
  kcalendarcore-5.87.0.tar.xz
  kcalendarcore-5.87.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kcalendarcore.spec ++++++
--- /var/tmp/diff_new_pack.ZlmnwM/_old  2021-10-18 22:00:00.901999074 +0200
+++ /var/tmp/diff_new_pack.ZlmnwM/_new  2021-10-18 22:00:00.901999074 +0200
@@ -16,14 +16,14 @@
 #
 
 
-%define _tar_path 5.86
+%define _tar_path 5.87
 # Full KF5 version (e.g. 5.33.0)
 %{!?_kf5_version: %global _kf5_version %{version}}
 # Last major and minor KF5 version (e.g. 5.33)
 %{!?_kf5_bugfix_version: %define _kf5_bugfix_version %(echo %{_kf5_version} | 
awk -F. '{print $1"."$2}')}
 %bcond_without lang
 Name:           kcalendarcore
-Version:        5.86.0
+Version:        5.87.0
 Release:        0
 Summary:        Library to access and handle calendar data
 License:        LGPL-2.0-or-later


++++++ kcalendarcore-5.86.0.tar.xz -> kcalendarcore-5.87.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/.gitlab-ci.yml 
new/kcalendarcore-5.87.0/.gitlab-ci.yml
--- old/kcalendarcore-5.86.0/.gitlab-ci.yml     1970-01-01 01:00:00.000000000 
+0100
+++ new/kcalendarcore-5.87.0/.gitlab-ci.yml     2021-10-02 14:14:52.000000000 
+0200
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: 2020 Volker Krause <[email protected]>
+# SPDX-License-Identifier: CC0-1.0
+
+include:
+  - 
https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/.kde-ci.yml 
new/kcalendarcore-5.87.0/.kde-ci.yml
--- old/kcalendarcore-5.86.0/.kde-ci.yml        1970-01-01 01:00:00.000000000 
+0100
+++ new/kcalendarcore-5.87.0/.kde-ci.yml        2021-10-02 14:14:52.000000000 
+0200
@@ -0,0 +1,7 @@
+Dependencies:
+- 'on': ['@all']
+  'require':
+    'frameworks/extra-cmake-modules': '@same'
+
+Options:
+  test-before-installing: True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/CMakeLists.txt 
new/kcalendarcore-5.87.0/CMakeLists.txt
--- old/kcalendarcore-5.86.0/CMakeLists.txt     2021-09-04 17:41:34.000000000 
+0200
+++ new/kcalendarcore-5.87.0/CMakeLists.txt     2021-10-02 14:14:52.000000000 
+0200
@@ -1,11 +1,11 @@
 cmake_minimum_required(VERSION 3.16)
-set(KF_VERSION "5.86.0") # handled by release scripts
+set(KF_VERSION "5.87.0") # handled by release scripts
 
 project(KCalendarCore VERSION ${KF_VERSION})
 
 # ECM setup
 include(FeatureSummary)
-find_package(ECM 5.86.0  NO_MODULE)
+find_package(ECM 5.87.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL "https://commits.kde.org/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
@@ -120,7 +120,7 @@
 if (NOT WIN32)
     ecm_generate_pkgconfig_file(BASE_NAME KF5CalendarCore
       INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KCalendarCore/
-      DEPS Qt5Core
+      DEPS "Qt5Core Qt5Gui"
     INSTALL)
 endif()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.86.0/autotests/data/Compat/Evolution_2.8.2_timezone_test.ics.ical.ref
 
new/kcalendarcore-5.87.0/autotests/data/Compat/Evolution_2.8.2_timezone_test.ics.ical.ref
--- 
old/kcalendarcore-5.86.0/autotests/data/Compat/Evolution_2.8.2_timezone_test.ics.ical.ref
   2021-09-04 17:41:34.000000000 +0200
+++ 
new/kcalendarcore-5.87.0/autotests/data/Compat/Evolution_2.8.2_timezone_test.ics.ical.ref
   2021-10-02 14:14:52.000000000 +0200
@@ -3,9 +3,6 @@
 VERSION:2.0
 X-KDE-ICAL-IMPLEMENTATION-VERSION:1.0
 X-LibKCal-Testsuite-OutTZ:Europe/London
-BEGIN:VTIMEZONE
-TZID:GMT
-END:VTIMEZONE
 BEGIN:VEVENT
 DTSTAMP:20070127T211005Z
 CREATED:20070127T211013
@@ -13,8 +10,8 @@
 SEQUENCE:2
 LAST-MODIFIED:20070127T211124
 SUMMARY:Nominal is 1200 to 1230 _GMT_ on 27 Jan 2007
-DTSTART;TZID=GMT:20070127T120000
-DTEND;TZID=GMT:20070127T123000
+DTSTART:20070127T120000
+DTEND:20070127T123000
 TRANSP:OPAQUE
 END:VEVENT
 END:VCALENDAR
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.86.0/autotests/data/Compat/Mozilla_1.0.ics.ical.ref 
new/kcalendarcore-5.87.0/autotests/data/Compat/Mozilla_1.0.ics.ical.ref
--- old/kcalendarcore-5.86.0/autotests/data/Compat/Mozilla_1.0.ics.ical.ref     
2021-09-04 17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/data/Compat/Mozilla_1.0.ics.ical.ref     
2021-10-02 14:14:52.000000000 +0200
@@ -2,9 +2,6 @@
 PRODID:-//K Desktop Environment//NONSGML libkcal 4.3//EN
 VERSION:2.0
 X-KDE-ICAL-IMPLEMENTATION-VERSION:1.0
-BEGIN:VTIMEZONE
-TZID:GMT
-END:VTIMEZONE
 BEGIN:VTODO
 DTSTAMP:20171006T143852Z
 CREATED:20171006T143852Z
@@ -13,8 +10,8 @@
 SUMMARY:Call Beacon to transfer funds
 STATUS:NEEDS-ACTION
 CLASS:PRIVATE
-DUE;TZID=GMT:20040505T111500
-DTSTART;TZID=GMT:20040505T101500
+DUE:20040505T111500
+DTSTART:20040505T101500
 PERCENT-COMPLETE:0
 END:VTODO
 BEGIN:VEVENT
@@ -53,8 +50,8 @@
 SUMMARY:Dental Exam
 STATUS:CONFIRMED
 CLASS:PRIVATE
-DTSTART;TZID=GMT:20040510T090000
-DTEND;TZID=GMT:20040510T110000
+DTSTART:20040510T090000
+DTEND:20040510T110000
 TRANSP:OPAQUE
 END:VEVENT
 BEGIN:VEVENT
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/autotests/testicalformat.cpp 
new/kcalendarcore-5.87.0/autotests/testicalformat.cpp
--- old/kcalendarcore-5.86.0/autotests/testicalformat.cpp       2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testicalformat.cpp       2021-10-02 
14:14:52.000000000 +0200
@@ -11,6 +11,7 @@
 #include "event.h"
 #include "icalformat.h"
 #include "memorycalendar.h"
+#include "occurrenceiterator.h"
 
 #include <QTest>
 #include <QTimeZone>
@@ -252,3 +253,100 @@
         }
     }
 }
+
+void ICalFormatTest::testRDate()
+{
+    ICalFormat format;
+
+    const QString serializedCalendar = QLatin1String(
+        "BEGIN:VCALENDAR\n"
+        "VERSION:2.0\n"
+        "PRODID:-//Lotus Development Corporation//NONSGML Notes 9.0.1//EN_C\n"
+        "METHOD:PUBLISH\n"
+        "BEGIN:VEVENT\n"
+        "DTSTART:20210630T100000Z\n"
+        "DTEND:20210630T110000Z\n"
+        "TRANSP:OPAQUE\n"
+        "RDATE;VALUE=PERIOD:20210630T100000Z/20210630T110000Z\n"
+        " 
,20210825T100000Z/20210825T110000Z,20211027T100000Z/20211027T110000Z\n"
+        " ,20211215T110000Z/PT2H\n"
+        "LAST-MODIFIED:20210601T094627Z\n"
+        "DTSTAMP:20210601T092939Z\n"
+        "UID:5FC21473F5CC80CCC12586E70033ED9C-Lotus_Notes_Generated\n"
+        "END:VEVENT\n"
+        "END:VCALENDAR\n");
+    MemoryCalendar::Ptr calendar(new MemoryCalendar(QTimeZone::utc()));
+    QVERIFY(format.fromString(calendar, serializedCalendar));
+    const QString uid = 
QString::fromLatin1("5FC21473F5CC80CCC12586E70033ED9C-Lotus_Notes_Generated");
+    Incidence::Ptr event = calendar->incidence(uid);
+    QVERIFY(event);
+    QVERIFY(event->recurs());
+
+    const QDateTime ev1(QDate(2021, 6, 30), QTime(10, 0), Qt::UTC);
+    const QDateTime ev2(QDate(2021, 8, 25), QTime(10, 0), Qt::UTC);
+    const QDateTime ev3(QDate(2021, 10, 27), QTime(10, 0), Qt::UTC);
+    const QDateTime ev4(QDate(2021, 12, 15), QTime(11, 0), Qt::UTC);
+    QCOMPARE(event->recurrence()->rDateTimes(),
+             QList<QDateTime>() << ev1 << ev2 << ev3 << ev4);
+
+    OccurrenceIterator it(*calendar, QDateTime(QDate(2021, 6, 1), QTime(0, 0)),
+                          QDateTime(QDate(2021, 12, 31), QTime(0, 0)));
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.occurrenceStartDate(), ev1);
+    QCOMPARE(it.occurrenceEndDate(), ev1.addSecs(3600));
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.occurrenceStartDate(), ev2);
+    QCOMPARE(it.occurrenceEndDate(), ev2.addSecs(3600));
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.occurrenceStartDate(), ev3);
+    QCOMPARE(it.occurrenceEndDate(), ev3.addSecs(3600));
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.occurrenceStartDate(), ev4);
+    QCOMPARE(it.occurrenceEndDate(), ev4.addSecs(7200));
+
+    const QStringList output = format.toString(calendar, 
QString()).split(QString::fromLatin1("\r\n"));
+    
QVERIFY(output.contains(QString::fromLatin1("RDATE;VALUE=PERIOD:20210630T100000Z/20210630T110000Z")));
+    
QVERIFY(output.contains(QString::fromLatin1("RDATE;VALUE=PERIOD:20210825T100000Z/20210825T110000Z")));
+    
QVERIFY(output.contains(QString::fromLatin1("RDATE;VALUE=PERIOD:20211027T100000Z/20211027T110000Z")));
+    
QVERIFY(output.contains(QString::fromLatin1("RDATE;VALUE=PERIOD:20211215T110000Z/PT2H")));
+}
+
+void ICalFormatTest::testDateTime_data()
+{
+    QTest::addColumn<QByteArray>("dtStartData");
+    QTest::addColumn<QDateTime>("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")
+        << QDate(2019, 11, 13).startOfDay();
+    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());
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/autotests/testicalformat.h 
new/kcalendarcore-5.87.0/autotests/testicalformat.h
--- old/kcalendarcore-5.86.0/autotests/testicalformat.h 2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testicalformat.h 2021-10-02 
14:14:52.000000000 +0200
@@ -23,6 +23,9 @@
     void testAlarm();
     void testDateTimeSerialization_data();
     void testDateTimeSerialization();
+    void testRDate();
+    void testDateTime_data();
+    void testDateTime();
 };
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/autotests/testicaltimezones.cpp 
new/kcalendarcore-5.87.0/autotests/testicaltimezones.cpp
--- old/kcalendarcore-5.86.0/autotests/testicaltimezones.cpp    2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testicaltimezones.cpp    2021-10-02 
14:14:52.000000000 +0200
@@ -132,6 +132,7 @@
 // When there's an extra transition from +0000 to +0100
 // in 1978 (FreeBSD and old Debian), we get one more
 // transition and slightly different RRULEs
+#ifdef Q_OS_FREEBSD
 static const char *VTZ_PragueExtra =
     "BEGIN:VTIMEZONE\r\n"
     "TZID:Europe/Prague\r\n"
@@ -173,6 +174,7 @@
     "RDATE:19950924T030000\r\n"
     "END:STANDARD\r\n"
     "END:VTIMEZONE\r\n";
+#endif
 
 // CALENDAR component header and footer
 static const char *calendarHeader =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.86.0/autotests/testoccurrenceiterator.cpp 
new/kcalendarcore-5.87.0/autotests/testoccurrenceiterator.cpp
--- old/kcalendarcore-5.86.0/autotests/testoccurrenceiterator.cpp       
2021-09-04 17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testoccurrenceiterator.cpp       
2021-10-02 14:14:52.000000000 +0200
@@ -273,3 +273,51 @@
     KCalendarCore::OccurrenceIterator rIt2(calendar, tomorrow, 
tomorrow.addDays(1));
     QVERIFY(!rIt2.hasNext());
 }
+
+void TestOccurrenceIterator::testEndDate()
+{
+    const QDateTime start(QDate(2021, 8, 30), QTime(10, 0, 0));
+    const QDateTime end(QDate(2021, 8, 30), QTime(11, 0, 0));
+
+    const QDateTime start2(QDate(2021, 8, 30), QTime(15, 0, 0));
+    const QDateTime end2(QDate(2021, 8, 30), QTime(18, 0, 0));
+
+    KCalendarCore::MemoryCalendar calendar(QTimeZone::utc());
+
+    KCalendarCore::Event::Ptr event(new KCalendarCore::Event);
+    event->setUid(QStringLiteral("event"));
+    event->setSummary(QStringLiteral("event"));
+    event->setDtStart(start);
+    event->setDtEnd(end);
+    event->recurrence()->setDaily(1);
+    event->recurrence()->addRDateTimePeriod(KCalendarCore::Period(start2, 
end2));
+    calendar.addEvent(event);
+
+    KCalendarCore::Journal::Ptr journal(new KCalendarCore::Journal);
+    journal->setUid(QStringLiteral("journal"));
+    journal->setDtStart(start);
+    calendar.addJournal(journal);
+
+    KCalendarCore::OccurrenceIterator rIt(calendar, start, start.addDays(1));
+    // The base event.
+    QVERIFY(rIt.hasNext());
+    rIt.next();
+    QCOMPARE(rIt.occurrenceStartDate(), start);
+    QCOMPARE(rIt.occurrenceEndDate(), end);
+    // The additional occurrence with a longer duration.
+    QVERIFY(rIt.hasNext());
+    rIt.next();
+    QCOMPARE(rIt.occurrenceStartDate(), start2);
+    QCOMPARE(rIt.occurrenceEndDate(), end2);
+    // The recurring occurrence with the base duration.
+    QVERIFY(rIt.hasNext());
+    rIt.next();
+    QCOMPARE(rIt.occurrenceStartDate(), start.addDays(1));
+    QCOMPARE(rIt.occurrenceEndDate(), end.addDays(1));
+    // The journal.
+    QVERIFY(rIt.hasNext());
+    rIt.next();
+    QCOMPARE(rIt.occurrenceStartDate(), start);
+    QVERIFY(!rIt.occurrenceEndDate().isValid());
+    QVERIFY(!rIt.hasNext());
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.86.0/autotests/testoccurrenceiterator.h 
new/kcalendarcore-5.87.0/autotests/testoccurrenceiterator.h
--- old/kcalendarcore-5.86.0/autotests/testoccurrenceiterator.h 2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testoccurrenceiterator.h 2021-10-02 
14:14:52.000000000 +0200
@@ -19,6 +19,7 @@
     void testWithExceptionThisAndFuture();
     void testSubDailyRecurrences();
     void testJournals();
+    void testEndDate();
 };
 
 #endif // TESTOCCURRENCEITERATOR_H
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.86.0/autotests/testrecurrenceexception.cpp 
new/kcalendarcore-5.87.0/autotests/testrecurrenceexception.cpp
--- old/kcalendarcore-5.86.0/autotests/testrecurrenceexception.cpp      
2021-09-04 17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testrecurrenceexception.cpp      
2021-10-02 14:14:52.000000000 +0200
@@ -22,10 +22,14 @@
     todo->setDtDue(dtdue);
     todo->recurrence()->setDaily(1);
     todo->recurrence()->setDuration(3);
+    todo->setCreated(dtstart);
+    todo->setLastModified(dtstart);
 
     const KCalendarCore::Todo::Ptr exception = 
KCalendarCore::MemoryCalendar::createException(todo, recurrenceId, 
false).staticCast<KCalendarCore::Todo>();
     QCOMPARE(exception->dtStart(), recurrenceId);
     QCOMPARE(exception->dtDue(), QDateTime(dtdue).addDays(1));
+    QVERIFY(exception->created() >= todo->created());
+    QVERIFY(exception->lastModified() >= exception->created());
     // FIXME should be done on clearing the recurrence, but we can't due to BC.
     // Probably not that important as long as dtRecurrence is ignored if the 
todo is not recurring
     // QCOMPARE(exception->dtRecurrence(), QDateTime());
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.86.0/autotests/testtimesininterval.cpp 
new/kcalendarcore-5.87.0/autotests/testtimesininterval.cpp
--- old/kcalendarcore-5.86.0/autotests/testtimesininterval.cpp  2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testtimesininterval.cpp  2021-10-02 
14:14:52.000000000 +0200
@@ -276,3 +276,31 @@
 
     QCOMPARE(expectedEventOccurrences.size(), 0);
 }
+
+void TimesInIntervalTest::testRDatePeriod()
+{
+    const QDateTime start(QDate(2021, 8, 30), QTime(11, 14));
+    const QDateTime end(QDate(2021, 8, 30), QTime(11, 42));
+    const QDateTime other(QDate(2021, 8, 30), QTime(12, 00));
+    const QDateTime later(QDate(2021, 8, 30), QTime(15, 00));
+    Recurrence recur;
+
+    QVERIFY(!recur.recurs());
+    QVERIFY(!recur.rDateTimePeriod(start).isValid());
+
+    recur.addRDateTimePeriod(Period(start, end));
+    QVERIFY(recur.recurs());
+    QCOMPARE(recur.rDateTimePeriod(start), Period(start, end));
+
+    const QList<QDateTime> timesInInterval = 
recur.timesInInterval(start.addDays(-1),
+                                                                   
start.addDays(+1));
+    QCOMPARE(timesInInterval, QList<QDateTime>() << start);
+
+    recur.addRDateTime(other);
+    QCOMPARE(recur.rDateTimes(), QList<QDateTime>() << start << other);
+    QCOMPARE(recur.rDateTimePeriod(start), Period(start, end));
+
+    recur.setRDateTimes(QList<QDateTime>() << other << later);
+    QCOMPARE(recur.rDateTimes(), QList<QDateTime>() << other << later);
+    QVERIFY(!recur.rDateTimePeriod(start).isValid());
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/autotests/testtimesininterval.h 
new/kcalendarcore-5.87.0/autotests/testtimesininterval.h
--- old/kcalendarcore-5.86.0/autotests/testtimesininterval.h    2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/autotests/testtimesininterval.h    2021-10-02 
14:14:52.000000000 +0200
@@ -23,6 +23,7 @@
     void testLocalTimeHandlingNonAllDay();
     void testLocalTimeHandlingAllDay();
     void testByDayRecurrence();
+    void testRDatePeriod();
 };
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/calendar.cpp 
new/kcalendarcore-5.87.0/src/calendar.cpp
--- old/kcalendarcore-5.86.0/src/calendar.cpp   2021-09-04 17:41:34.000000000 
+0200
+++ new/kcalendarcore-5.87.0/src/calendar.cpp   2021-10-02 14:14:52.000000000 
+0200
@@ -5,6 +5,7 @@
   SPDX-FileCopyrightText: 2000-2004 Cornelius Schumacher <[email protected]>
   SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <[email protected]>
   SPDX-FileCopyrightText: 2006 David Jarvie <[email protected]>
+  SPDX-FileCopyrightText: 2021 Boris Shmarin <[email protected]>
 
   SPDX-License-Identifier: LGPL-2.0-or-later
 */
@@ -583,7 +584,9 @@
     }
 
     Incidence::Ptr newInc(incidence->clone());
-    newInc->setCreated(QDateTime::currentDateTimeUtc());
+    const QDateTime current = QDateTime::currentDateTimeUtc();
+    newInc->setCreated(current);
+    newInc->setLastModified(current);
     newInc->setRevision(0);
     // Recurring exceptions are not support for now
     newInc->clearRecurrence();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/calfilter.cpp 
new/kcalendarcore-5.87.0/src/calfilter.cpp
--- old/kcalendarcore-5.86.0/src/calfilter.cpp  2021-09-04 17:41:34.000000000 
+0200
+++ new/kcalendarcore-5.87.0/src/calfilter.cpp  2021-10-02 14:14:52.000000000 
+0200
@@ -72,14 +72,10 @@
         return;
     }
 
-    Event::List::Iterator it = eventList->begin();
-    while (it != eventList->end()) {
-        if (!filterIncidence(*it)) {
-            it = eventList->erase(it);
-        } else {
-            ++it;
-        }
-    }
+    auto it = std::remove_if(eventList->begin(), eventList->end(), [=](const 
Incidence::Ptr &incidence) {
+        return !filterIncidence(incidence);
+    });
+    eventList->erase(it, eventList->end());
 }
 
 // TODO: avoid duplicating apply() code
@@ -89,14 +85,10 @@
         return;
     }
 
-    Todo::List::Iterator it = todoList->begin();
-    while (it != todoList->end()) {
-        if (!filterIncidence(*it)) {
-            it = todoList->erase(it);
-        } else {
-            ++it;
-        }
-    }
+    auto it = std::remove_if(todoList->begin(), todoList->end(), [=](const 
Incidence::Ptr &incidence) {
+        return !filterIncidence(incidence);
+    });
+    todoList->erase(it, todoList->end());
 }
 
 void CalFilter::apply(Journal::List *journalList) const
@@ -105,14 +97,10 @@
         return;
     }
 
-    Journal::List::Iterator it = journalList->begin();
-    while (it != journalList->end()) {
-        if (!filterIncidence(*it)) {
-            it = journalList->erase(it);
-        } else {
-            ++it;
-        }
-    }
+    auto it = std::remove_if(journalList->begin(), journalList->end(), 
[=](const Incidence::Ptr &incidence) {
+        return !filterIncidence(incidence);
+    });
+    journalList->erase(it, journalList->end());
 }
 
 bool CalFilter::filterIncidence(const Incidence::Ptr &incidence) const
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/icalformat_p.cpp 
new/kcalendarcore-5.87.0/src/icalformat_p.cpp
--- old/kcalendarcore-5.86.0/src/icalformat_p.cpp       2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/src/icalformat_p.cpp       2021-10-02 
14:14:52.000000000 +0200
@@ -567,7 +567,21 @@
     }
     dateTimeList = incidence->recurrence()->rDateTimes();
     for (auto rdtIt = dateTimeList.constBegin(); rdtIt != 
dateTimeList.constEnd(); ++rdtIt) {
-        icalcomponent_add_property(parent, 
writeICalDateTimeProperty(ICAL_RDATE_PROPERTY, *rdtIt, tzUsedList));
+        Period period = incidence->recurrence()->rDateTimePeriod(*rdtIt);
+        if (period.isValid()) {
+            icaldatetimeperiodtype tp;
+            tp.time = icaltime_null_time();
+            tp.period = icalperiodtype_null_period();
+            tp.period.start = writeICalDateTime(period.start());
+            if (period.hasDuration()) {
+                tp.period.duration = writeICalDuration(period.duration());
+            } else {
+                tp.period.end = writeICalDateTime(period.end());
+            }
+            icalcomponent_add_property(parent, icalproperty_new_rdate(tp));
+        } else {
+            icalcomponent_add_property(parent, 
writeICalDateTimeProperty(ICAL_RDATE_PROPERTY, *rdtIt, tzUsedList));
+        }
     }
 
     // attachments
@@ -1545,6 +1559,12 @@
             
attachment.setMimeType(QLatin1String(icalparameter_get_fmttype(p)));
         }
 
+        /* Support FILENAME property (Caldav). see 
https://datatracker.ietf.org/doc/html/rfc8607 */
+        p = icalproperty_get_first_parameter(attach, ICAL_FILENAME_PARAMETER);
+        if (p) {
+            
attachment.setLabel(QString::fromUtf8(icalparameter_get_xvalue(p)));
+        }
+
         p = icalproperty_get_first_parameter(attach, ICAL_X_PARAMETER);
         while (p) {
             QString xname = 
QString::fromLatin1(icalparameter_get_xname(p)).toUpper();
@@ -1773,7 +1793,15 @@
                     incidence->recurrence()->addRDateTime(kdt);
                 }
             } else {
-                // TODO: RDates as period are not yet implemented!
+                icaldatetimeperiodtype tp = icalproperty_get_rdate(p);
+                const QDateTime start = readICalDateTime(p, tp.period.start, 
tzlist, false);
+                if (icaltime_is_null_time(tp.period.end)) {
+                    Period period(start, readICalDuration(tp.period.duration));
+                    incidence->recurrence()->addRDateTimePeriod(period);
+                } else {
+                    Period period(start, readICalDateTime(p, tp.period.end, 
tzlist, false));
+                    incidence->recurrence()->addRDateTimePeriod(period);
+                }
             }
             break;
         }
@@ -2363,7 +2391,7 @@
     }
 
     QTimeZone qtz;
-    if (!icaltime_is_utc(t)) {
+    if (!icaltime_is_utc(t) && dt.timeSpec() == Qt::TimeZone) {
         qtz = dt.timeZone();
     }
 
@@ -2404,20 +2432,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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/icaltimezones.cpp 
new/kcalendarcore-5.87.0/src/icaltimezones.cpp
--- old/kcalendarcore-5.86.0/src/icaltimezones.cpp      2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/src/icaltimezones.cpp      2021-10-02 
14:14:52.000000000 +0200
@@ -118,7 +118,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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/occurrenceiterator.cpp 
new/kcalendarcore-5.87.0/src/occurrenceiterator.cpp
--- old/kcalendarcore-5.86.0/src/occurrenceiterator.cpp 2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/src/occurrenceiterator.cpp 2021-10-02 
14:14:52.000000000 +0200
@@ -47,16 +47,19 @@
         {
         }
 
-        Occurrence(const Incidence::Ptr &i, const QDateTime &recurrenceId, 
const QDateTime &startDate)
+        Occurrence(const Incidence::Ptr &i, const QDateTime &recurrenceId,
+                   const QDateTime &startDate, const QDateTime &endDate)
             : incidence(i)
             , recurrenceId(recurrenceId)
             , startDate(startDate)
+            , endDate(endDate)
         {
         }
 
         Incidence::Ptr incidence;
         QDateTime recurrenceId;
         QDateTime startDate;
+        QDateTime endDate;
     };
     QList<Occurrence> occurrenceList;
     QListIterator<Occurrence> occurrenceIt;
@@ -85,6 +88,20 @@
         return false;
     }
 
+    QDateTime occurrenceEnd(const Incidence::Ptr &inc, const QDateTime &start)
+    {
+        if (inc->hasDuration()) {
+            return inc->duration().end(start);
+        } else {
+            const QDateTime end = inc->dateTime(Incidence::RoleEnd);
+            if (end.isValid()) {
+                const Duration elapsed(inc->dtStart(), end, Duration::Seconds);
+                return elapsed.end(start);
+            }
+        }
+        return QDateTime();
+    }
+
     void setupIterator(const Calendar &calendar, const Incidence::List 
&incidences)
     {
         for (const Incidence::Ptr &inc : qAsConst(incidences)) {
@@ -131,7 +148,12 @@
                     }
 
                     if (!occurrenceIsHidden(calendar, incidence, 
occurrenceStartDate)) {
-                        occurrenceList << Private::Occurrence(incidence, 
recurrenceId, occurrenceStartDate);
+                        const Period period = 
inc->recurrence()->rDateTimePeriod(occurrenceStartDate);
+                        if (period.isValid()) {
+                            occurrenceList << Private::Occurrence(incidence, 
recurrenceId, occurrenceStartDate, period.end());
+                        } else {
+                            occurrenceList << Private::Occurrence(incidence, 
recurrenceId, occurrenceStartDate, occurrenceEnd(incidence, 
occurrenceStartDate));
+                        }
                     }
 
                     if (resetIncidence) {
@@ -140,7 +162,8 @@
                     }
                 }
             } else {
-                occurrenceList << Private::Occurrence(inc, {}, inc->dtStart());
+                occurrenceList << Private::Occurrence(inc, {}, inc->dtStart(),
+                                                      
inc->dateTime(Incidence::RoleEnd));
             }
         }
         occurrenceIt = QListIterator<Private::Occurrence>(occurrenceList);
@@ -225,6 +248,11 @@
     return d->current.startDate;
 }
 
+QDateTime OccurrenceIterator::occurrenceEndDate() const
+{
+    return d->current.endDate;
+}
+
 QDateTime OccurrenceIterator::recurrenceId() const
 {
     return d->current.recurrenceId;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/occurrenceiterator.h 
new/kcalendarcore-5.87.0/src/occurrenceiterator.h
--- old/kcalendarcore-5.86.0/src/occurrenceiterator.h   2021-09-04 
17:41:34.000000000 +0200
+++ new/kcalendarcore-5.87.0/src/occurrenceiterator.h   2021-10-02 
14:14:52.000000000 +0200
@@ -69,6 +69,17 @@
     QDateTime occurrenceStartDate() const;
 
     /**
+     * Returns the end date of the occurrence
+     *
+     * For incidence that supports end date (events and due date for todos),
+     * this is computed from the duration or directly the end date of
+     * the occurrence or an exception overriding that occurrence. For 
incidences
+     * without end date, an invalid date is returned.
+     * @since 5.87
+     */
+    QDateTime occurrenceEndDate() const;
+
+    /**
      * Returns the recurrence Id.
      *
      * This is the date where the occurrence starts without exceptions,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/period.cpp 
new/kcalendarcore-5.87.0/src/period.cpp
--- old/kcalendarcore-5.86.0/src/period.cpp     2021-09-04 17:41:34.000000000 
+0200
+++ new/kcalendarcore-5.87.0/src/period.cpp     2021-10-02 14:14:52.000000000 
+0200
@@ -96,6 +96,11 @@
     return *this;
 }
 
+bool Period::isValid() const
+{
+    return d->mStart.isValid();
+}
+
 QDateTime Period::start() const
 {
     return d->mStart;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/period.h 
new/kcalendarcore-5.87.0/src/period.h
--- old/kcalendarcore-5.86.0/src/period.h       2021-09-04 17:41:34.000000000 
+0200
+++ new/kcalendarcore-5.87.0/src/period.h       2021-10-02 14:14:52.000000000 
+0200
@@ -124,6 +124,12 @@
     Period &operator=(const Period &other);
 
     /**
+      Returns true if the Period is not empty.
+      @since 5.87
+    */
+    Q_REQUIRED_RESULT bool isValid() const;
+
+    /**
       Returns when this period starts.
     */
     Q_REQUIRED_RESULT QDateTime start() const;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/recurrence.cpp 
new/kcalendarcore-5.87.0/src/recurrence.cpp
--- old/kcalendarcore-5.86.0/src/recurrence.cpp 2021-09-04 17:41:34.000000000 
+0200
+++ new/kcalendarcore-5.87.0/src/recurrence.cpp 2021-10-02 14:14:52.000000000 
+0200
@@ -18,6 +18,7 @@
 #include <QDataStream>
 #include <QTime>
 #include <QTimeZone>
+#include <QHash>
 
 using namespace KCalendarCore;
 
@@ -34,6 +35,7 @@
 
     Private(const Private &p)
         : mRDateTimes(p.mRDateTimes)
+        , mRDateTimePeriods(p.mRDateTimePeriods)
         , mRDates(p.mRDates)
         , mExDateTimes(p.mExDateTimes)
         , mExDates(p.mExDates)
@@ -49,6 +51,7 @@
     RecurrenceRule::List mExRules;
     RecurrenceRule::List mRRules;
     QList<QDateTime> mRDateTimes;
+    QHash<QDateTime, Period> mRDateTimePeriods; // Map RDate starts with 
periods if any
     DateList mRDates;
     QList<QDateTime> mExDateTimes;
     DateList mExDates;
@@ -67,7 +70,7 @@
     //   qCDebug(KCALCORE_LOG) << mStartDateTime << p.mStartDateTime;
     if ((mStartDateTime != p.mStartDateTime && (mStartDateTime.isValid() || 
p.mStartDateTime.isValid())) || mAllDay != p.mAllDay
         || mRecurReadOnly != p.mRecurReadOnly || mExDates != p.mExDates || 
mExDateTimes != p.mExDateTimes || mRDates != p.mRDates
-        || mRDateTimes != p.mRDateTimes) {
+        || mRDateTimes != p.mRDateTimes || mRDateTimePeriods != 
p.mRDateTimePeriods) {
         return false;
     }
 
@@ -522,11 +525,15 @@
     d->mStartDateTime = d->mStartDateTime.toTimeZone(oldTz);
     d->mStartDateTime.setTimeZone(newTz);
 
+    QHash<QDateTime, Period> oldPeriods = d->mRDateTimePeriods;
     int i;
     int end;
     for (i = 0, end = d->mRDateTimes.count(); i < end; ++i) {
+        QHash<QDateTime, Period>::Iterator period = 
oldPeriods.find(d->mRDateTimes[i]);
+        period->shiftTimes(oldTz, newTz);
         d->mRDateTimes[i] = d->mRDateTimes[i].toTimeZone(oldTz);
         d->mRDateTimes[i].setTimeZone(newTz);
+        d->mRDateTimePeriods.insert(d->mRDateTimes[i], *period);
     }
     for (i = 0, end = d->mExDateTimes.count(); i < end; ++i) {
         d->mExDateTimes[i] = d->mExDateTimes[i].toTimeZone(oldTz);
@@ -561,6 +568,7 @@
     d->mExRules.clear();
     d->mRDates.clear();
     d->mRDateTimes.clear();
+    d->mRDateTimePeriods.clear();
     d->mExDates.clear();
     d->mExDateTimes.clear();
     d->mCachedType = rMax;
@@ -1337,6 +1345,7 @@
 
     d->mRDateTimes = rdates;
     sortAndRemoveDuplicates(d->mRDateTimes);
+    d->mRDateTimePeriods.clear();
     updated();
 }
 
@@ -1350,6 +1359,22 @@
     updated();
 }
 
+void Recurrence::addRDateTimePeriod(const Period &period)
+{
+    if (d->mRecurReadOnly) {
+        return;
+    }
+
+    setInsert(d->mRDateTimes, period.start());
+    d->mRDateTimePeriods.insert(period.start(), period);
+    updated();
+}
+
+Period Recurrence::rDateTimePeriod(const QDateTime &rdate) const
+{
+    return d->mRDateTimePeriods.value(rdate);
+}
+
 DateList Recurrence::rDates() const
 {
     return d->mRDates;
@@ -1487,6 +1512,11 @@
     }
 
     serializeQDateTimeList(out, r->d->mRDateTimes);
+    out << r->d->mRDateTimePeriods.size();
+    for (QHash<QDateTime, Period>::ConstIterator it = 
r->d->mRDateTimePeriods.constBegin();
+         it != r->d->mRDateTimePeriods.constEnd(); ++it) {
+        out << it.key() << it.value();
+    }
     serializeQDateTimeList(out, r->d->mExDateTimes);
     out << r->d->mRDates;
     serializeQDateTimeAsKDateTime(out, r->d->mStartDateTime);
@@ -1511,8 +1541,19 @@
 
     int rruleCount;
     int exruleCount;
+    int size;
 
     deserializeQDateTimeList(in, r->d->mRDateTimes);
+    in >> size;
+    r->d->mRDateTimePeriods.clear();
+    r->d->mRDateTimePeriods.reserve(size);
+    for (int i = 0; i < size; ++i) {
+        QDateTime start;
+        Period period;
+        in >> start >> period;
+        r->d->mRDateTimes << start;
+        r->d->mRDateTimePeriods.insert(start, period);
+    }
     deserializeQDateTimeList(in, r->d->mExDateTimes);
     in >> r->d->mRDates;
     deserializeKDateTimeAsQDateTime(in, r->d->mStartDateTime);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.86.0/src/recurrence.h 
new/kcalendarcore-5.87.0/src/recurrence.h
--- old/kcalendarcore-5.86.0/src/recurrence.h   2021-09-04 17:41:34.000000000 
+0200
+++ new/kcalendarcore-5.87.0/src/recurrence.h   2021-10-02 14:14:52.000000000 
+0200
@@ -13,6 +13,7 @@
 
 #include "kcalendarcore_export.h"
 #include "recurrencerule.h"
+#include "period.h"
 
 class QBitArray;
 class QTimeZone;
@@ -612,10 +613,26 @@
     // RDATE
     Q_REQUIRED_RESULT QList<QDateTime> rDateTimes() const;
     Q_REQUIRED_RESULT DateList rDates() const;
+    /**
+      Inquire if the given RDATE is associated to a PERIOD.
+      @param rdate a given RDATE in date time format.
+      @return a Period, invalid if there is no period associated to @param 
rdate.
+      @since 5.87
+     */
+    Q_REQUIRED_RESULT Period rDateTimePeriod(const QDateTime &rdate) const;
     void setRDateTimes(const QList<QDateTime> &rdates);
     void setRDates(const DateList &rdates);
     void addRDateTime(const QDateTime &rdate);
     void addRDate(const QDate &rdate);
+    /**
+      Add a RDATE defined as a PERIOD. The start date-time of the period is 
added
+      to the recurring date time list, and will be listed by a call to
+      rDateTimes(). Use then rDateTimePeriod() to fetch the associated
+      period defintion.
+      @param period a given RDATE in period defintion.
+      @since 5.87
+     */
+    void addRDateTimePeriod(const Period &period);
 
     // ExDATE
     Q_REQUIRED_RESULT QList<QDateTime> exDateTimes() const;

Reply via email to