diff options
author | Дилян Палаузов <git-dpa@aegee.org> | 2022-01-04 17:11:56 +0200 |
---|---|---|
committer | Allen Winter <allen.winter@kdab.com> | 2022-01-15 16:53:07 -0500 |
commit | d7e46baed224ca54e448fd506c9271e7da21b28f (patch) | |
tree | 5dd0bcbd45e29f1156a80467496331041070516d | |
parent | 19e0baaa50deebdfc4368ca0a4216f71b5998bce (diff) | |
download | libical-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.txt | 3 | ||||
-rw-r--r-- | src/libical/icalcomponent.c | 68 | ||||
-rw-r--r-- | src/libical/icalcomponent.h | 20 | ||||
-rw-r--r-- | src/test/regression.c | 61 |
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... **/ |