summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorДилян Палаузов <git-dpa@aegee.org>2022-01-04 17:11:56 +0200
committerAllen Winter <allen.winter@kdab.com>2022-01-15 16:53:07 -0500
commitd7e46baed224ca54e448fd506c9271e7da21b28f (patch)
tree5dd0bcbd45e29f1156a80467496331041070516d
parent19e0baaa50deebdfc4368ca0a4216f71b5998bce (diff)
downloadlibical-git-d7e46baed224ca54e448fd506c9271e7da21b28f.tar.gz
icalcomponent_get_duration() — calculate the duration differently for VEVENT and VTODO
icalcomponent_get_dtend() — return null-time, unless called on VEVENT, VAVAILABILITY or VFREEBUSY.
-rw-r--r--ReleaseNotes.txt3
-rw-r--r--src/libical/icalcomponent.c68
-rw-r--r--src/libical/icalcomponent.h20
-rw-r--r--src/test/regression.c61
4 files changed, 129 insertions, 23 deletions
diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index cd82f85c..c7bd29de 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -3,7 +3,8 @@ Release Highlights
Version 3.0.13 (UNRELEASED):
----------------------------
- *
+ * icalcomponent_get_dtend() return icaltime_null_time(), unless called on VEVENT, VAVAILABILITY or VFREEBUSY
+ * icalcomponent_get_duration() for VTODO calculate with DUE instead of DTEND
Version 3.0.12 (08 December 2021):
----------------------------------
diff --git a/src/libical/icalcomponent.c b/src/libical/icalcomponent.c
index 1a3655b9..dc085709 100644
--- a/src/libical/icalcomponent.c
+++ b/src/libical/icalcomponent.c
@@ -1337,10 +1337,23 @@ struct icaltimetype icalcomponent_get_dtstart(icalcomponent *comp)
struct icaltimetype icalcomponent_get_dtend(icalcomponent *comp)
{
icalcomponent *inner = icalcomponent_get_inner(comp);
- icalproperty *end_prop = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
- icalproperty *dur_prop = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
+ const icalcomponent_kind kind = icalcomponent_isa(inner);
+ icalproperty *end_prop, *dur_prop;
struct icaltimetype ret;
+ switch(kind) {
+ case ICAL_VAVAILABILITY_COMPONENT:
+ case ICAL_VEVENT_COMPONENT:
+ case ICAL_VFREEBUSY_COMPONENT:
+ case ICAL_XAVAILABLE_COMPONENT:
+ break;
+ default:
+ return icaltime_null_time();
+ }
+
+ end_prop = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
+ dur_prop = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
+
if (end_prop != 0 && dur_prop == 0) {
ret = icalproperty_get_datetime_with_component(end_prop, comp);
} else if (end_prop == 0 && dur_prop != 0) {
@@ -1357,13 +1370,17 @@ struct icaltimetype icalcomponent_get_dtend(icalcomponent *comp)
ret = icaltime_add(start, duration);
} else if (end_prop == 0 && dur_prop == 0) {
- struct icaltimetype start = icalcomponent_get_dtstart(inner);
- if (icaltime_is_date(start)) {
- struct icaldurationtype duration = icaldurationtype_null_duration();
- duration.days = 1;
- ret = icaltime_add(start, duration);
+ if (kind == ICAL_VEVENT_COMPONENT) {
+ struct icaltimetype start = icalcomponent_get_dtstart(inner);
+ if (icaltime_is_date(start)) {
+ struct icaldurationtype duration = icaldurationtype_null_duration();
+ duration.days = 1;
+ ret = icaltime_add(start, duration);
+ } else {
+ ret = start;
+ }
} else {
- ret = start;
+ ret = icaltime_null_time();
}
} else {
/* Error, both duration and dtend have been specified */
@@ -1419,12 +1436,32 @@ void icalcomponent_set_duration(icalcomponent *comp, struct icaldurationtype v)
struct icaldurationtype icalcomponent_get_duration(icalcomponent *comp)
{
icalcomponent *inner = icalcomponent_get_inner(comp);
+ const icalcomponent_kind kind = icalcomponent_isa(inner);
+ icalproperty *end_prop, *dur_prop;
+ struct icaltimetype end;
+ struct icaldurationtype ret;
+
+ switch(kind) {
+ case ICAL_VAVAILABILITY_COMPONENT:
+ case ICAL_VEVENT_COMPONENT:
+ case ICAL_XAVAILABLE_COMPONENT:
+ end_prop = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
+ if (end_prop) {
+ end = icalcomponent_get_dtend(inner);
+ }
+ break;
+ case ICAL_VTODO_COMPONENT:
+ end_prop = icalcomponent_get_first_property(inner, ICAL_DUE_PROPERTY);
+ if (end_prop) {
+ end = icalcomponent_get_due(inner);
+ }
+ break;
+ default:
+ /* The libical API is used incorrectly */
+ return icaldurationtype_null_duration();
+ }
- icalproperty *end_prop = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
-
- icalproperty *dur_prop = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
-
- struct icaldurationtype ret = icaldurationtype_null_duration();
+ dur_prop = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
if (dur_prop != 0 && end_prop == 0) {
ret = icalproperty_get_duration(dur_prop);
@@ -1436,15 +1473,16 @@ struct icaldurationtype icalcomponent_get_duration(icalcomponent *comp)
* The standard actually allows different time zones.
*/
struct icaltimetype start = icalcomponent_get_dtstart(inner);
- struct icaltimetype end = icalcomponent_get_dtend(inner);
ret = icaltime_subtract(end, start);
} else if (end_prop == 0 && dur_prop == 0) {
struct icaltimetype start = icalcomponent_get_dtstart(inner);
- if (icaltime_is_date(start)) {
+ ret = icaldurationtype_null_duration();
+ if (kind == ICAL_VEVENT_COMPONENT && icaltime_is_date(start)) {
ret.days = 1;
}
} else {
+ ret = icaldurationtype_null_duration();
/* Error, both duration and dtend have been specified */
icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
}
diff --git a/src/libical/icalcomponent.h b/src/libical/icalcomponent.h
index 5e44fe26..70533a34 100644
--- a/src/libical/icalcomponent.h
+++ b/src/libical/icalcomponent.h
@@ -263,6 +263,13 @@ LIBICAL_ICAL_EXPORT struct icaltimetype icalcomponent_get_dtstart(icalcomponent
* there is a DTEND and you call get_duration, the routine will
* return the difference between DTEND and DTSTART.
*
+ * When DURATION and DTEND are both missing, for VEVENT an implicit
+ * DTEND is calculated based of DTSTART; for AVAILABLE, VAVAILABILITY,
+ * and VFREEBUSY null-time is returned.
+ *
+ * Returns null-time, unless called on AVAILABLE, VEVENT,
+ * VAVAILABILITY, or VFREEBUSY components.
+ *
* FIXME this is useless until we can flag the failure
*/
LIBICAL_ICAL_EXPORT struct icaltimetype icalcomponent_get_dtend(icalcomponent *comp);
@@ -327,15 +334,14 @@ LIBICAL_ICAL_EXPORT void icalcomponent_set_duration(icalcomponent *comp,
/** @brief Gets the DURATION property as an icalduration
*
* For the icalcomponent routines only, DTEND and DURATION are tied
- * together.
- * If a DURATION property is not present but a DTEND is, we use
- * that to determine the proper end.
- *
- * For the icalcomponent routines only, dtend and duration are tied
* together. If you call the get routine for one and the other
* exists, the routine will calculate the return value. That is, if
- * there is a DTEND and you call get_duration, the routine will
- * return the difference between DTEND and DTSTART.
+ * there is a DTEND and you call get_duration, the routine will return
+ * the difference between DTEND and DTSTART in AVAILABLE, VEVENT, or
+ * VAVAILABILITY; and the difference between DUE and DTSTART in VTODO.
+ * When both DURATION and DTEND are missing from VEVENT an implicit
+ * duration is returned, based on the value-type of DTSTART. Otherwise
+ * null-duration is returned.
*/
LIBICAL_ICAL_EXPORT struct icaldurationtype icalcomponent_get_duration(icalcomponent *comp);
diff --git a/src/test/regression.c b/src/test/regression.c
index 41171169..076922b5 100644
--- a/src/test/regression.c
+++ b/src/test/regression.c
@@ -4772,6 +4772,66 @@ static void test_vcc_vcard_parse(void)
ok("vCalendar-broken cannot be parsed", (vcal == NULL));
}
+static void test_implicit_dtend_duration(void)
+{
+ const struct icaltimetype start1 = icaltime_from_string("20220108");
+ icalcomponent* c = icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalcomponent_vanew(
+ ICAL_VEVENT_COMPONENT,
+ icalproperty_vanew_dtstart(start1, 0),
+ 0),
+ 0);
+ struct icaldurationtype d = icalcomponent_get_duration(c);
+ struct icaltimetype end = icalcomponent_get_dtend(c),
+ start = icaltime_from_string("20220108T101010Z");
+ if (VERBOSE) {
+ printf("%s\n", icaldurationtype_as_ical_string(d));
+ }
+ str_is("icaldurationtype_as_ical_string(d)", "P1D", icaldurationtype_as_ical_string(d));
+
+ if (VERBOSE) {
+ printf("%s\n", icaltime_as_ical_string(end));
+ }
+ str_is("icaltime_as_ical_string(end)", "20220109", icaltime_as_ical_string(end));
+
+ icalcomponent_set_dtstart(c, start);
+ d = icalcomponent_get_duration(c);
+ end = icalcomponent_get_dtend(c);
+ if (VERBOSE) {
+ printf("%s\n", icaldurationtype_as_ical_string(d));
+ }
+ int_is("icaldurationtype_as_int(d)", 0, icaldurationtype_as_int(d));
+
+ if (VERBOSE) {
+ printf("%s\n", icaltime_as_ical_string(end));
+ }
+ int_is("icaltime_compare(start, end)", 0, icaltime_compare(start, end));
+ icalcomponent_free(c);
+
+
+ c = icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalcomponent_vanew(
+ ICAL_VTODO_COMPONENT,
+ icalproperty_vanew_dtstart(start1, 0),
+ 0),
+ 0);
+ icalcomponent_set_due(c, icaltime_from_string("20220109"));
+ d = icalcomponent_get_duration(c);
+ end = icalcomponent_get_dtend(c);
+ if (VERBOSE) {
+ printf("%s\n", icaldurationtype_as_ical_string(d));
+ }
+ str_is("P1D", "P1D", icaldurationtype_as_ical_string(d));
+
+ if (VERBOSE) {
+ printf("%i\n", icaltime_is_null_time(end));
+ }
+ int_is("icaltime_is_null_time(end)", 1, icaltime_is_null_time(end));
+ icalcomponent_free(c);
+}
+
int main(int argc, char *argv[])
{
#if !defined(HAVE_UNISTD_H)
@@ -4911,6 +4971,7 @@ int main(int argc, char *argv[])
test_run("Test icalcomponent_normalize", test_icalcomponent_normalize, do_test, do_header);
test_run("Test builtin compat TZID", test_builtin_compat_tzid, do_test, do_header);
test_run("Test VCC vCard parse", test_vcc_vcard_parse, do_test, do_header);
+ test_run("Test implicit DTEND and DURATION for VEVENT and VTODO", test_implicit_dtend_duration, do_test, do_header);
/** OPTIONAL TESTS go here... **/