summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKen Murchison <murch@fastmail.com>2021-03-18 17:04:52 -0400
committerAllen Winter <allen.winter@kdab.com>2021-04-11 14:29:45 -0400
commitf779f1979dd5617e47308ad861ff030a94d71082 (patch)
tree1c4529e92c98a8fee9d217a4dcb6c4b41c683bbd /src
parent18db00b1e945832761dd8080e1f6b67a05bfc2df (diff)
downloadlibical-git-f779f1979dd5617e47308ad861ff030a94d71082.tar.gz
icaltz-util.c: properly handle zones that don't terminate with an RRULE
Diffstat (limited to 'src')
-rw-r--r--src/libical/icaltz-util.c93
1 files changed, 19 insertions, 74 deletions
diff --git a/src/libical/icaltz-util.c b/src/libical/icaltz-util.c
index baa5d5ef..76e54690 100644
--- a/src/libical/icaltz-util.c
+++ b/src/libical/icaltz-util.c
@@ -386,7 +386,6 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
size_t i, num_trans, num_chars, num_leaps, num_isstd, num_isgmt;
size_t num_types = 0;
size_t size;
- time_t now = time(NULL);
int trans_size = 4;
const char *zonedir;
@@ -403,7 +402,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
char footer[100], *tzstr = NULL;
int idx, prev_idx;
- icalcomponent *tz_comp = NULL, *comp = NULL;
+ icalcomponent *tz_comp = NULL;
icalproperty *icalprop;
icaltimetype icaltime;
@@ -717,11 +716,20 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
start = transitions[i] + types[prev_idx].gmtoff;
icaltime = icaltime_from_timet_with_zone(start, 0, NULL);
- if (tzstr && (i >= num_trans - 2)) {
+ /* Flag this as the last transition time for the zone, if:
+ this is the last transition time overall, OR
+ this is the penultimate transition time, AND either
+ we have a TZ string for future transitions, OR
+ the last two transitions have different time types
+ */
+ if ((i == num_trans - 1) ||
+ ((i == num_trans - 2) &&
+ (tzstr || (types[idx].isdst != types[trans_idx[i+1]].isdst)))) {
last_trans = 1;
}
else {
- by_day = nth_weekday(calculate_pos(icaltime), icaltime_day_of_week(icaltime));
+ by_day = nth_weekday(calculate_pos(icaltime),
+ icaltime_day_of_week(icaltime));
}
if (types[idx].isdst) {
@@ -826,12 +834,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
0);
icalcomponent_add_component(tz_comp, zone->rrule_comp);
- if (last_trans) {
- /* This rule will take us into the future */
- zone->time = icaltime_from_day_of_year(1, 9999);
- zone->rrule_prop = icalproperty_new_rrule(zone->final_recur);
- }
- else {
+ if (!last_trans) {
// Create a recurrence rule for the current set of changes
icalrecurrencetype_clear(&zone->recur);
zone->recur.freq = ICAL_YEARLY_RECURRENCE;
@@ -839,72 +842,14 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
zone->recur.by_month[0] = icaltime.month;
zone->recur.by_month_day[0] = icaltime.day;
zone->rrule_prop = icalproperty_new_rrule(zone->recur);
+ icalcomponent_add_property(zone->rrule_comp, zone->rrule_prop);
+ }
+ else if (tzstr) {
+ // Use the recurrence rule derived from the TZ string
+ zone->rrule_prop = icalproperty_new_rrule(zone->final_recur);
+ icalcomponent_add_property(zone->rrule_comp, zone->rrule_prop);
}
- icalcomponent_add_property(zone->rrule_comp, zone->rrule_prop);
- }
- }
-
- // 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 (daylight.rrule_comp && icaltime_as_timet(daylight.time) < now) {
- icaltime_adjust(&daylight.prev_time, 0, 0, 0, -daylight.gmtoff_from);
- daylight.prev_time.zone = icaltimezone_get_utc_timezone();
-
- daylight.recur.until = daylight.prev_time;
- icalproperty_set_rrule(daylight.rrule_prop, daylight.recur);
-
- comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
- icalprop = icalproperty_new_tzname(types[idx].zname);
- icalcomponent_add_property(comp, icalprop);
- icalprop = icalproperty_new_dtstart(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);
- }
-
- if (standard.rrule_comp && icaltime_as_timet(standard.time) < now) {
- icaltime_adjust(&standard.prev_time, 0, 0, 0, -standard.gmtoff_from);
- standard.prev_time.zone = icaltimezone_get_utc_timezone();
-
- standard.recur.until = standard.prev_time;
- icalproperty_set_rrule(standard.rrule_prop, standard.recur);
-
- comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
- icalprop = icalproperty_new_tzname(types[idx].zname);
- icalcomponent_add_property(comp, icalprop);
- icalprop = icalproperty_new_dtstart(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 = transitions[0] + types[prev_idx].gmtoff;
-
- // 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);
- 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);
- icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff);
- icalcomponent_add_property(comp, icalprop);
- icalcomponent_add_component(tz_comp, comp);
}
error: