aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDon Lewis <truckman@FreeBSD.org>2018-03-20 02:52:28 +0000
committerDon Lewis <truckman@FreeBSD.org>2018-03-20 02:52:28 +0000
commitba213ee0370735c75f00870537df9a69169ebc3f (patch)
tree72a21eead974a9437b4dacfc680fc960894afd5d
parent31cb5d1aa60594544aa56a1551285880cb2371ab (diff)
downloadports-ba213ee0370735c75f00870537df9a69169ebc3f.tar.gz
ports-ba213ee0370735c75f00870537df9a69169ebc3f.zip
Import upstream patch:
https://github.com/libical/libical/commit/77f82ba88abbb633dc52335fcc050bec3b41c2 69 icaltzutil_fetch_timezone now creates VTIMEZONE components using RRULEs rather than expanding out every year (if USE_INTEROPERATIVE_VTIMEZONES was off) or using a single time zone back to 1970 (if it was one). This creates more accurate time zones that are compatible with dates whose time zones have since transitioned to a different offset (such as a date in America/New_York in 1980). Removed icaltzutil_set_exact_vtimezones_support and icaltzutil_get_exact_vtimezones_support. Removed USE_INTEROPERABLE_VTIMEZONES. Add missing USE_GNOME=introspection:build Fix segmentation fault with evolution-calendar-factory Pet portlint, USE_* comes before USES PR: 226460 Submitted by: cpm Obtained from: github libical/libical (partially)
Notes
Notes: svn path=/head/; revision=465060
-rw-r--r--devel/libical/Makefile6
-rw-r--r--devel/libical/files/patch-src_libical_icaltz-util.c520
-rw-r--r--devel/libical/files/patch-src_libical_icaltz-util.h41
-rw-r--r--devel/libical/files/patch-src_test_timezones.c82
4 files changed, 646 insertions, 3 deletions
diff --git a/devel/libical/Makefile b/devel/libical/Makefile
index 4361c0ceb96e..b6e0ca954f19 100644
--- a/devel/libical/Makefile
+++ b/devel/libical/Makefile
@@ -4,7 +4,7 @@
PORTNAME= libical
PORTVERSION= 2.0.0
DISTVERSIONPREFIX= v
-PORTREVISION= 2
+PORTREVISION= 3
CATEGORIES= devel
MAINTAINER= gnome@FreeBSD.org
@@ -15,9 +15,9 @@ LICENSE_COMB= dual
LIB_DEPENDS= libicuuc.so:devel/icu
-USE_GITHUB= yes
-
USES= cmake pathfix perl5
+USE_GITHUB= yes
+USE_GNOME= introspection:build
USE_PERL5= build
USE_LDCONFIG= yes
diff --git a/devel/libical/files/patch-src_libical_icaltz-util.c b/devel/libical/files/patch-src_libical_icaltz-util.c
new file mode 100644
index 000000000000..1f36e84e6e26
--- /dev/null
+++ b/devel/libical/files/patch-src_libical_icaltz-util.c
@@ -0,0 +1,520 @@
+--- src/libical/icaltz-util.c.orig 2018-03-09 22:23:47 UTC
++++ src/libical/icaltz-util.c
+@@ -4,20 +4,18 @@
+ *
+ * Copyright 2007, Novell, Inc.
+ *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of version 2 of the GNU Lesser General Public
+- * License as published by the Free Software Foundation.
++ * This library is free software; you can redistribute it and/or modify
++ * it under the terms of either:
+ *
+- * This program 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 Lesser General Public License for more details.
++ * The LGPL as published by the Free Software Foundation, version
++ * 2.1, available at: http://www.gnu.org/licenses/lgpl-2.1.html
+ *
+- * * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the
+- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
++ * Or:
++ *
++ * The Mozilla Public License Version 2.0. You may obtain a copy of
++ * the License at http://www.mozilla.org/MPL/
+ */
++//krazy:excludeall=cpp
+
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+@@ -93,9 +91,9 @@ typedef struct
+ char charcnt[4];
+ } tzinfo;
+
+-static char *zdir = NULL;
++static const char *zdir = NULL;
+
+-static char *search_paths[] = {
++static const char *search_paths[] = {
+ "/usr/share/zoneinfo",
+ "/usr/lib/zoneinfo",
+ "/etc/zoneinfo",
+@@ -144,6 +142,7 @@ static int decode(const void *ptr)
+ const unsigned char *p = ptr;
+ int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
+
++ /* cppcheck-suppress shiftNegative */
+ result = (result << 8) | *p++;
+ result = (result << 8) | *p++;
+ result = (result << 8) | *p++;
+@@ -153,9 +152,9 @@ static int decode(const void *ptr)
+ }
+ }
+
+-static char *zname_from_stridx(char *str, long idx)
++static char *zname_from_stridx(char *str, size_t idx)
+ {
+- long i;
++ size_t i;
+ size_t size;
+ char *ret;
+
+@@ -164,7 +163,7 @@ static char *zname_from_stridx(char *str
+ i++;
+ }
+
+- size = (size_t)(i - idx);
++ size = i - idx;
+ str += idx;
+ ret = (char *)malloc(size + 1);
+ ret = strncpy(ret, str, size);
+@@ -197,45 +196,6 @@ const char *icaltzutil_get_zone_director
+ return zdir;
+ }
+
+-static void find_transidx(time_t *transitions, ttinfo *types,
+- int *trans_idx, long int num_trans,
+- int *stdidx, int *dstidx)
+-{
+- time_t now, year_start;
+- int i, found = 0;
+- struct icaltimetype itime;
+-
+- now = time(NULL);
+- itime = icaltime_from_timet(now, 0);
+- itime.month = itime.day = 1;
+- itime.hour = itime.minute = itime.second = 0;
+- year_start = icaltime_as_timet(itime);
+-
+- /* Set this by default */
+- *stdidx = (num_trans - 1);
+-
+- for (i = (num_trans - 1); i >= 0; --i) {
+- if (year_start < transitions[i]) {
+- int idx;
+- found = 1;
+- idx = trans_idx[i];
+- (types[idx].isdst) ? (*dstidx = i) : (*stdidx = i);
+- }
+- }
+-
+- /* If the transition found is the last among the list, prepare to use the last two transtions.
+- * Using this will most likely throw the DTSTART of the resulting component off by 1 or 2 days
+- * but it would set right by the adjustment made.
+- * NOTE: We need to use the last two transitions only because there is no data for the future
+- * transitions.
+- */
+- if (found && (*dstidx == -1)) {
+- *dstidx = ((*stdidx) - 1);
+- }
+-
+- return;
+-}
+-
+ static int calculate_pos(icaltimetype icaltime)
+ {
+ static int r_pos[] = {1, 2, 3, -2, -1};
+@@ -251,22 +211,6 @@ static int calculate_pos(icaltimetype ic
+ return r_pos[pos];
+ }
+
+-#if defined(USE_INTEROPERABLE_VTIMEZONES)
+-static int _s_use_exact_timezones = 0;
+-#else
+-static int _s_use_exact_timezones = 1;
+-#endif
+-
+-void icaltzutil_set_exact_vtimezones_support(int on)
+-{
+- _s_use_exact_timezones = (on != 0);
+-}
+-
+-int icaltzutil_get_exact_vtimezones_support(void)
+-{
+- return _s_use_exact_timezones;
+-}
+-
+ static void adjust_dtstart_day_to_rrule(icalcomponent *comp, struct icalrecurrencetype rule)
+ {
+ time_t now, year_start;
+@@ -274,13 +218,13 @@ static void adjust_dtstart_day_to_rrule(
+ icalrecur_iterator *iter;
+
+ now = time(NULL);
+- itime = icaltime_from_timet(now, 0);
++ itime = icaltime_from_timet_with_zone(now, 0, NULL);
+ itime.month = itime.day = 1;
+ itime.hour = itime.minute = itime.second = 0;
+ year_start = icaltime_as_timet(itime);
+
+ comp_start = icalcomponent_get_dtstart(comp);
+- start = icaltime_from_timet(year_start, 0);
++ start = icaltime_from_timet_with_zone(year_start, 0, NULL);
+
+ iter = icalrecur_iterator_new(rule, start);
+ iter_start = icalrecur_iterator_next(iter);
+@@ -298,9 +242,8 @@ icalcomponent *icaltzutil_fetch_timezone
+ size_t i, num_trans, num_chars, num_leaps, num_isstd, num_isgmt;
+ size_t num_types = 0;
+ size_t size;
+- time_t trans;
+- int dstidx = -1, stdidx = -1, pos, sign, zidx, zp_idx;
+- icalcomponent *std_comp = NULL;
++ int pos, sign;
++ time_t now = time(NULL);
+
+ const char *zonedir;
+ FILE *f = NULL;
+@@ -313,12 +256,22 @@ icalcomponent *icaltzutil_fetch_timezone
+ leap *leaps = NULL;
+ char *tzid = NULL;
+
+- time_t start, end;
+ int idx, prev_idx;
+- icalcomponent *tz_comp = NULL, *comp = NULL, *dst_comp;
++ icalcomponent *tz_comp = NULL, *comp = NULL;
+ icalproperty *icalprop;
+- icaltimetype dtstart, icaltime;
+- struct icalrecurrencetype ical_recur;
++ icaltimetype icaltime;
++ struct icalrecurrencetype standard_recur;
++ struct icalrecurrencetype daylight_recur;
++ icaltimetype prev_standard_time = icaltime_null_time();
++ icaltimetype prev_daylight_time = icaltime_null_time();
++ icaltimetype prev_prev_standard_time;
++ icaltimetype prev_prev_daylight_time;
++ long prev_standard_gmtoff;
++ long prev_daylight_gmtoff;
++ icalcomponent *cur_standard_comp = NULL;
++ icalcomponent *cur_daylight_comp = NULL;
++ icalproperty *cur_standard_rrule_property;
++ icalproperty *cur_daylight_rrule_property;
+
+ if (icaltimezone_get_builtin_tzdata()) {
+ goto error;
+@@ -448,15 +401,8 @@ icalcomponent *icaltzutil_fetch_timezone
+ /* Read all the contents now */
+
+ for (i = 0; i < num_types; i++) {
+- types[i].zname = zname_from_stridx(znames, (long)types[i].abbr);
+- }
+-
+- if (!_s_use_exact_timezones) {
+- if (num_trans != 0) {
+- find_transidx(transitions, types, trans_idx, (long int)num_trans, &stdidx, &dstidx);
+- } else {
+- stdidx = 0;
+- }
++ /* coverity[tainted_data] */
++ types[i].zname = zname_from_stridx(znames, types[i].abbr);
+ }
+
+ tz_comp = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
+@@ -476,140 +422,202 @@ icalcomponent *icaltzutil_fetch_timezone
+ icalproperty_set_x_name(icalprop, "X-LIC-LOCATION");
+ icalcomponent_add_property(tz_comp, icalprop);
+
+- if (!_s_use_exact_timezones) {
+- if (stdidx != -1) {
+- if (num_trans != 0) {
+- zidx = trans_idx[stdidx];
++ prev_idx = 0;
++ if (num_trans == 0) {
++ prev_idx = idx = 0;
++ } else {
++ idx = trans_idx[0];
++ }
++
++ for (i = 1; i < num_trans; i++) {
++ int by_day;
++ int is_new_comp = 0;
++ time_t start;
++ struct icalrecurrencetype *recur;
++
++ prev_idx = idx;
++ idx = trans_idx[i];
++ start = transitions[i] + types[prev_idx].gmtoff;
++
++ icaltime = icaltime_from_timet_with_zone(start, 0, NULL);
++ pos = calculate_pos(icaltime);
++ pos < 0 ? (sign = -1): (sign = 1);
++ by_day = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime));
++
++ // Figure out if the rule has changed since the previous year
++ // If it has, update the recurrence rule of the current component and create a new component
++ // If it the current component was only valid for one year then remove the recurrence rule
++ if (types[idx].isdst) {
++ if (cur_daylight_comp) {
++ // Check if the pattern for daylight has changed
++ // If it has, create a new component and update UNTIL of previous component's RRULE
++ if (daylight_recur.by_month[0] != icaltime.month ||
++ daylight_recur.by_day[0] != by_day ||
++ types[prev_idx].gmtoff != prev_daylight_gmtoff) {
++ // Set UNTIL of the previous component's recurrence
++ icaltime_adjust(&prev_daylight_time, 0, 0, 0, -types[prev_idx].gmtoff);
++ prev_daylight_time.is_utc = 1;
++
++ daylight_recur.until = prev_daylight_time;
++ icalproperty_set_rrule(cur_daylight_rrule_property, daylight_recur);
++
++ cur_daylight_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
++ is_new_comp = 1;
++ }
+ } else {
+- zidx = 0;
++ cur_daylight_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
++ is_new_comp = 1;
+ }
+
+- std_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
+- icalprop = icalproperty_new_tzname(types[zidx].zname);
+- icalcomponent_add_property(std_comp, icalprop);
++ comp = cur_daylight_comp;
++ recur = &daylight_recur;
+
+- if (dstidx != -1) {
+- zp_idx = trans_idx[stdidx-1];
++ if (icaltime_is_null_time(prev_daylight_time)) {
++ prev_prev_daylight_time = icaltime;
+ } else {
+- zp_idx = zidx;
++ prev_prev_daylight_time = prev_daylight_time;
+ }
+- /* DTSTART localtime uses TZOFFSETFROM UTC offset */
+- if (num_trans != 0) {
+- trans = transitions[stdidx] + types[zp_idx].gmtoff;
++
++ prev_daylight_time = icaltime;
++ prev_daylight_gmtoff = types[prev_idx].gmtoff;
++ } else {
++ if (cur_standard_comp) {
++ // Check if the pattern for standard has changed
++ // If it has, create a new component and update UNTIL
++ // of the previous component's RRULE
++ if (standard_recur.by_month[0] != icaltime.month ||
++ standard_recur.by_day[0] != by_day ||
++ types[prev_idx].gmtoff != prev_standard_gmtoff) {
++ icaltime_adjust(&prev_standard_time, 0, 0, 0, -types[prev_idx].gmtoff);
++ prev_standard_time.is_utc = 1;
++
++ standard_recur.until = prev_standard_time;
++ icalproperty_set_rrule(cur_standard_rrule_property, standard_recur);
++
++ cur_standard_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
++ is_new_comp = 1;
++
++ // Are we transitioning on the daylight date?
++ // If so, that means the time zone is switching off of DST
++ // We need to set UNTIL for the daylight component
++ if (cur_daylight_comp && daylight_recur.by_month[0] == icaltime.month &&
++ daylight_recur.by_day[0] == by_day) {
++ icaltime_adjust(&prev_daylight_time, 0, 0, 0, -types[prev_idx].gmtoff);
++ prev_daylight_time.is_utc = 1;
++
++ daylight_recur.until = prev_daylight_time;
++ icalproperty_set_rrule(cur_daylight_rrule_property, daylight_recur);
++ }
++ }
+ } else {
+- trans = (time_t)types[zp_idx].gmtoff;
++ cur_standard_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
++ is_new_comp = 1;
+ }
+- icaltime = icaltime_from_timet(trans, 0);
+- dtstart = icaltime;
+- dtstart.year = 1970;
+- dtstart.minute = dtstart.second = 0;
+- icalprop = icalproperty_new_dtstart(dtstart);
+- icalcomponent_add_property(std_comp, icalprop);
+
+- /* If DST changes are present use RRULE */
+- if (dstidx != -1) {
+- icalrecurrencetype_clear(&ical_recur);
+- ical_recur.freq = ICAL_YEARLY_RECURRENCE;
+- ical_recur.by_month[0] = icaltime.month;
+- pos = calculate_pos(icaltime);
+- pos < 0 ? (sign = -1): (sign = 1);
+- ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime));
+- icalprop = icalproperty_new_rrule(ical_recur);
+- icalcomponent_add_property(std_comp, icalprop);
++ comp = cur_standard_comp;
++ recur = &standard_recur;
+
+- adjust_dtstart_day_to_rrule(std_comp, ical_recur);
++ if (icaltime_is_null_time(prev_standard_time)) {
++ prev_prev_standard_time = icaltime;
++ } else {
++ prev_prev_standard_time = prev_standard_time;
+ }
+- icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff);
+- icalcomponent_add_property(std_comp, icalprop);
+- icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff);
+- icalcomponent_add_property(std_comp, icalprop);
+- icalcomponent_add_component(tz_comp, std_comp);
+- } else {
+- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
++
++ prev_standard_time = icaltime;
++ prev_standard_gmtoff = types[prev_idx].gmtoff;
+ }
+
+- if (dstidx != -1) {
+- zidx = trans_idx[dstidx];
+- zp_idx = trans_idx[dstidx-1];
+- dst_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
+- icalprop = icalproperty_new_tzname(types[zidx].zname);
+- icalcomponent_add_property(dst_comp, icalprop);
++ if (is_new_comp) {
++ icalprop = icalproperty_new_tzname(types[idx].zname);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_dtstart(icaltime);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff);
++ icalcomponent_add_property(comp, icalprop);
+
+- /* DTSTART localtime uses TZOFFSETFROM UTC offset */
+- if (num_trans != 0) {
+- trans = transitions[dstidx] + types[zp_idx].gmtoff;
++ // Determine the recurrence rule for the current set of changes
++ icalrecurrencetype_clear(recur);
++ recur->freq = ICAL_YEARLY_RECURRENCE;
++ recur->by_month[0] = icaltime.month;
++ recur->by_day[0] = by_day;
++ icalprop = icalproperty_new_rrule(*recur);
++ icalcomponent_add_property(comp, icalprop);
++
++ if (types[idx].isdst) {
++ cur_daylight_rrule_property = icalprop;
+ } else {
+- trans = (time_t)types[zp_idx].gmtoff;
++ cur_standard_rrule_property = icalprop;
+ }
+
+- icaltime = icaltime_from_timet(trans, 0);
+- dtstart = icaltime;
+- dtstart.year = 1970;
+- dtstart.minute = dtstart.second = 0;
+- icalprop = icalproperty_new_dtstart(dtstart);
+- icalcomponent_add_property(dst_comp, icalprop);
++ adjust_dtstart_day_to_rrule(comp, *recur);
+
+- icalrecurrencetype_clear(&ical_recur);
+- ical_recur.freq = ICAL_YEARLY_RECURRENCE;
+- ical_recur.by_month[0] = icaltime.month;
+- pos = calculate_pos(icaltime);
+- pos < 0 ? (sign = -1): (sign = 1);
+- ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime));
+- icalprop = icalproperty_new_rrule(ical_recur);
+- icalcomponent_add_property(dst_comp, icalprop);
++ icalcomponent_add_component(tz_comp, comp);
++ }
++ }
+
+- adjust_dtstart_day_to_rrule(dst_comp, ical_recur);
++ // Check if the last daylight or standard date was before now
++ // If so, set the UNTIL date to the second-to-last transition date
++ // and then insert a new component to indicate the time zone doesn't transition anymore
++ if (cur_daylight_comp && icaltime_as_timet(prev_daylight_time) < now) {
++ icaltime_adjust(&prev_prev_daylight_time, 0, 0, 0, -prev_daylight_gmtoff);
++ prev_prev_daylight_time.is_utc = 1;
+
+- icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff);
+- icalcomponent_add_property(dst_comp, icalprop);
++ daylight_recur.until = prev_prev_daylight_time;
++ icalproperty_set_rrule(cur_daylight_rrule_property, daylight_recur);
+
+- icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff);
+- icalcomponent_add_property(dst_comp, icalprop);
++ comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
++ icalprop = icalproperty_new_tzname(types[idx].zname);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_dtstart(prev_daylight_time);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff);
++ icalcomponent_add_property(comp, icalprop);
++ icalcomponent_add_component(tz_comp, comp);
++ }
+
+- icalcomponent_add_component(tz_comp, dst_comp);
+- }
+- } else { /*exact vtimezones*/
+- prev_idx = 0;
+- if (num_trans == 0) {
+- prev_idx = idx = 0;
++ if (cur_standard_comp && icaltime_as_timet(prev_standard_time) < now) {
++ icaltime_adjust(&prev_prev_standard_time, 0, 0, 0, -prev_standard_gmtoff);
++ prev_prev_standard_time.is_utc = 1;
++
++ standard_recur.until = prev_prev_standard_time;
++ icalproperty_set_rrule(cur_standard_rrule_property, standard_recur);
++
++ comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
++ icalprop = icalproperty_new_tzname(types[idx].zname);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_dtstart(prev_standard_time);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff);
++ icalcomponent_add_property(comp, icalprop);
++ icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff);
++ icalcomponent_add_property(comp, icalprop);
++ icalcomponent_add_component(tz_comp, comp);
++ }
++
++ if (num_trans <= 1) {
++ time_t start;
++
++ if (num_trans == 1) {
++ start = transitions[0] + types[prev_idx].gmtoff;
+ } else {
+- idx = trans_idx[0];
++ start = 0;
+ }
+- start = 0;
+- for (i = 1; i < num_trans; i++, start = end) {
+- prev_idx = idx;
+- idx = trans_idx[i];
+- end = transitions[i] + types[prev_idx].gmtoff;
+- /* don't bother starting until the epoch */
+- if (0 > end)
+- continue;
+
+- if (types[prev_idx].isdst) {
+- comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
+- } else {
+- comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
+- }
+- icalprop = icalproperty_new_tzname(types[prev_idx].zname);
+- icalcomponent_add_property(comp, icalprop);
+- dtstart = icaltime_from_timet(start, 0);
+- icalprop = icalproperty_new_dtstart(dtstart);
+- icalcomponent_add_property(comp, icalprop);
+- icalprop = icalproperty_new_tzoffsetfrom(types[idx].gmtoff);
+- icalcomponent_add_property(comp, icalprop);
+- icalprop = icalproperty_new_tzoffsetto(types[prev_idx].gmtoff);
+- icalcomponent_add_property(comp, icalprop);
+- icalcomponent_add_component(tz_comp, comp);
+- }
+- /* finally, add a last zone with no end date */
++ // This time zone doesn't transition, insert a single VTIMEZONE component
+ if (types[idx].isdst) {
+ comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
+ } else {
+ comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
+ }
++
+ icalprop = icalproperty_new_tzname(types[idx].zname);
+ icalcomponent_add_property(comp, icalprop);
+- dtstart = icaltime_from_timet(start, 0);
+- icalprop = icalproperty_new_dtstart(dtstart);
++ icaltime = icaltime_from_timet_with_zone(start, 0, NULL);
++ icalprop = icalproperty_new_dtstart(icaltime);
+ icalcomponent_add_property(comp, icalprop);
+ icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff);
+ icalcomponent_add_property(comp, icalprop);
diff --git a/devel/libical/files/patch-src_libical_icaltz-util.h b/devel/libical/files/patch-src_libical_icaltz-util.h
new file mode 100644
index 000000000000..a7f08285e907
--- /dev/null
+++ b/devel/libical/files/patch-src_libical_icaltz-util.h
@@ -0,0 +1,41 @@
+--- src/libical/icaltz-util.h.orig 2018-03-09 22:29:13 UTC
++++ src/libical/icaltz-util.h
+@@ -4,19 +4,16 @@
+ *
+ * Copyright 2007, Novell, Inc.
+ *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of version 2 of the GNU Lesser General Public
+- * License as published by the Free Software Foundation.
++ * This library is free software; you can redistribute it and/or modify
++ * it under the terms of either:
+ *
+- * This program 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 Lesser General Public License for more details.
++ * The LGPL as published by the Free Software Foundation, version
++ * 2.1, available at: http://www.gnu.org/licenses/lgpl-2.1.html
+ *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the
+- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
++ * Or:
++ *
++ * The Mozilla Public License Version 2.0. You may obtain a copy of
++ * the License at http://www.mozilla.org/MPL/
+ */
+
+ #ifndef ICALTZUTIL_H
+@@ -35,10 +32,4 @@ LIBICAL_ICAL_EXPORT const char *icaltzut
+
+ LIBICAL_ICAL_EXPORT icalcomponent *icaltzutil_fetch_timezone(const char *location);
+
+-/* set @p on to 0 if inter-operable vtimezones are desired; else exact timezones are in-effect */
+-LIBICAL_ICAL_EXPORT void icaltzutil_set_exact_vtimezones_support(int on);
+-
+-/* return 1 if exact vtimezones are in-effect; else inter-operable vtimezones are in-effect */
+-LIBICAL_ICAL_EXPORT int icaltzutil_get_exact_vtimezones_support(void);
+-
+ #endif
diff --git a/devel/libical/files/patch-src_test_timezones.c b/devel/libical/files/patch-src_test_timezones.c
new file mode 100644
index 000000000000..40dd7d43b172
--- /dev/null
+++ b/devel/libical/files/patch-src_test_timezones.c
@@ -0,0 +1,82 @@
+--- src/test/timezones.c.orig 2018-03-09 22:35:51 UTC
++++ src/test/timezones.c
+@@ -1,15 +1,16 @@
+ /*
+ ======================================================================
+
+- The contents of this file are subject to the Mozilla Public License
+- Version 1.0 (the "License"); you may not use this file except in
+- compliance with the License. You may obtain a copy of the License at
+- http://www.mozilla.org/MPL/
++ This library is free software; you can redistribute it and/or modify
++ it under the terms of either:
+
+- Software distributed under the License is distributed on an "AS IS"
+- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+- the License for the specific language governing rights and
+- limitations under the License.
++ The LGPL as published by the Free Software Foundation, version
++ 2.1, available at: http://www.gnu.org/licenses/lgpl-2.1.html
++
++ Or:
++
++ The Mozilla Public License Version 2.0. You may obtain a copy of
++ the License at http://www.mozilla.org/MPL/
+
+ ======================================================================*/
+
+@@ -56,6 +57,9 @@ int main()
+ for (i = 0; i < timezones->num_elements; i++) {
+ zone = (icaltimezone *)icalarray_element_at(timezones, i);
+ zone_location = (char *)icaltimezone_get_location(zone);
++ zonedef_printed = 0;
++ if (!zone_location)
++ continue;
+
+ /*
+ * select this location for glibc: needs support for TZ=<location>
+@@ -66,7 +70,7 @@ int main()
+ #else
+ new_tz[0] = '\0';
+ strncat(new_tz, "TZ=", 255);
+- strncat(new_tz, zone_location, 255);
++ strncat(new_tz, zone_location, 255 - strlen(new_tz));
+ putenv(new_tz);
+ #endif
+ tzset();
+@@ -106,7 +110,9 @@ int main()
+ if (verbose || curr_failed != failed) {
+ struct tm utc_tm;
+
+- gmtime_r(&curr_time, &utc_tm);
++ if (!gmtime_r(&curr_time, &utc_tm))
++ memset(&utc_tm, 0, sizeof(utc_tm));
++
+ printf(
+ "%s: day %03d: %s: %04d-%02d-%02d %02d:%02d:%02d UTC = "
+ "libc %04d-%02d-%02d %02d:%02d:%02d dst %d",
+@@ -131,7 +137,7 @@ int main()
+ printf("\n");
+ failed = curr_failed;
+
+- if (!zonedef_printed) {
++ if (failed && !zonedef_printed) {
+ icalcomponent *comp = icaltimezone_get_component(zone);
+
+ if (comp) {
+@@ -153,14 +159,8 @@ int main()
+ percent_failed = total_failed * 100 / (total_failed + total_okay);
+ printf(" *** Summary: %lu zones tested, %u days failed, %u okay => %u%% failed ***\n",
+ (unsigned long)timezones->num_elements, total_failed, total_okay, percent_failed);
+-
+- if (!icaltzutil_get_exact_vtimezones_support()) {
+- if (!percent_failed) {
+- ret = 0;
+- printf(" *** Expect some small error rate with inter-operable vtimezones *** \n");
+- }
+- }
+ }
+
++ icaltimezone_free_builtin_timezones();
+ return ret;
+ }