Line 0
Link Here
|
|
|
1 |
--- src/libical/icaltz-util.c.orig 2018-03-09 22:23:47 UTC |
2 |
+++ src/libical/icaltz-util.c |
3 |
@@ -4,20 +4,18 @@ |
4 |
* |
5 |
* Copyright 2007, Novell, Inc. |
6 |
* |
7 |
- * This program is free software; you can redistribute it and/or |
8 |
- * modify it under the terms of version 2 of the GNU Lesser General Public |
9 |
- * License as published by the Free Software Foundation. |
10 |
+ * This library is free software; you can redistribute it and/or modify |
11 |
+ * it under the terms of either: |
12 |
* |
13 |
- * This program is distributed in the hope that it will be useful, |
14 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
- * GNU Lesser General Public License for more details. |
17 |
+ * The LGPL as published by the Free Software Foundation, version |
18 |
+ * 2.1, available at: http://www.gnu.org/licenses/lgpl-2.1.html |
19 |
* |
20 |
- * * You should have received a copy of the GNU Lesser General Public |
21 |
- * License along with this library; if not, write to the |
22 |
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
23 |
- * Boston, MA 02110-1301, USA. |
24 |
+ * Or: |
25 |
+ * |
26 |
+ * The Mozilla Public License Version 2.0. You may obtain a copy of |
27 |
+ * the License at http://www.mozilla.org/MPL/ |
28 |
*/ |
29 |
+//krazy:excludeall=cpp |
30 |
|
31 |
#ifdef HAVE_CONFIG_H |
32 |
#include <config.h> |
33 |
@@ -93,9 +91,9 @@ typedef struct |
34 |
char charcnt[4]; |
35 |
} tzinfo; |
36 |
|
37 |
-static char *zdir = NULL; |
38 |
+static const char *zdir = NULL; |
39 |
|
40 |
-static char *search_paths[] = { |
41 |
+static const char *search_paths[] = { |
42 |
"/usr/share/zoneinfo", |
43 |
"/usr/lib/zoneinfo", |
44 |
"/etc/zoneinfo", |
45 |
@@ -144,6 +142,7 @@ static int decode(const void *ptr) |
46 |
const unsigned char *p = ptr; |
47 |
int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0; |
48 |
|
49 |
+ /* cppcheck-suppress shiftNegative */ |
50 |
result = (result << 8) | *p++; |
51 |
result = (result << 8) | *p++; |
52 |
result = (result << 8) | *p++; |
53 |
@@ -153,9 +152,9 @@ static int decode(const void *ptr) |
54 |
} |
55 |
} |
56 |
|
57 |
-static char *zname_from_stridx(char *str, long idx) |
58 |
+static char *zname_from_stridx(char *str, size_t idx) |
59 |
{ |
60 |
- long i; |
61 |
+ size_t i; |
62 |
size_t size; |
63 |
char *ret; |
64 |
|
65 |
@@ -164,7 +163,7 @@ static char *zname_from_stridx(char *str |
66 |
i++; |
67 |
} |
68 |
|
69 |
- size = (size_t)(i - idx); |
70 |
+ size = i - idx; |
71 |
str += idx; |
72 |
ret = (char *)malloc(size + 1); |
73 |
ret = strncpy(ret, str, size); |
74 |
@@ -197,45 +196,6 @@ const char *icaltzutil_get_zone_director |
75 |
return zdir; |
76 |
} |
77 |
|
78 |
-static void find_transidx(time_t *transitions, ttinfo *types, |
79 |
- int *trans_idx, long int num_trans, |
80 |
- int *stdidx, int *dstidx) |
81 |
-{ |
82 |
- time_t now, year_start; |
83 |
- int i, found = 0; |
84 |
- struct icaltimetype itime; |
85 |
- |
86 |
- now = time(NULL); |
87 |
- itime = icaltime_from_timet(now, 0); |
88 |
- itime.month = itime.day = 1; |
89 |
- itime.hour = itime.minute = itime.second = 0; |
90 |
- year_start = icaltime_as_timet(itime); |
91 |
- |
92 |
- /* Set this by default */ |
93 |
- *stdidx = (num_trans - 1); |
94 |
- |
95 |
- for (i = (num_trans - 1); i >= 0; --i) { |
96 |
- if (year_start < transitions[i]) { |
97 |
- int idx; |
98 |
- found = 1; |
99 |
- idx = trans_idx[i]; |
100 |
- (types[idx].isdst) ? (*dstidx = i) : (*stdidx = i); |
101 |
- } |
102 |
- } |
103 |
- |
104 |
- /* If the transition found is the last among the list, prepare to use the last two transtions. |
105 |
- * Using this will most likely throw the DTSTART of the resulting component off by 1 or 2 days |
106 |
- * but it would set right by the adjustment made. |
107 |
- * NOTE: We need to use the last two transitions only because there is no data for the future |
108 |
- * transitions. |
109 |
- */ |
110 |
- if (found && (*dstidx == -1)) { |
111 |
- *dstidx = ((*stdidx) - 1); |
112 |
- } |
113 |
- |
114 |
- return; |
115 |
-} |
116 |
- |
117 |
static int calculate_pos(icaltimetype icaltime) |
118 |
{ |
119 |
static int r_pos[] = {1, 2, 3, -2, -1}; |
120 |
@@ -251,22 +211,6 @@ static int calculate_pos(icaltimetype ic |
121 |
return r_pos[pos]; |
122 |
} |
123 |
|
124 |
-#if defined(USE_INTEROPERABLE_VTIMEZONES) |
125 |
-static int _s_use_exact_timezones = 0; |
126 |
-#else |
127 |
-static int _s_use_exact_timezones = 1; |
128 |
-#endif |
129 |
- |
130 |
-void icaltzutil_set_exact_vtimezones_support(int on) |
131 |
-{ |
132 |
- _s_use_exact_timezones = (on != 0); |
133 |
-} |
134 |
- |
135 |
-int icaltzutil_get_exact_vtimezones_support(void) |
136 |
-{ |
137 |
- return _s_use_exact_timezones; |
138 |
-} |
139 |
- |
140 |
static void adjust_dtstart_day_to_rrule(icalcomponent *comp, struct icalrecurrencetype rule) |
141 |
{ |
142 |
time_t now, year_start; |
143 |
@@ -274,13 +218,13 @@ static void adjust_dtstart_day_to_rrule( |
144 |
icalrecur_iterator *iter; |
145 |
|
146 |
now = time(NULL); |
147 |
- itime = icaltime_from_timet(now, 0); |
148 |
+ itime = icaltime_from_timet_with_zone(now, 0, NULL); |
149 |
itime.month = itime.day = 1; |
150 |
itime.hour = itime.minute = itime.second = 0; |
151 |
year_start = icaltime_as_timet(itime); |
152 |
|
153 |
comp_start = icalcomponent_get_dtstart(comp); |
154 |
- start = icaltime_from_timet(year_start, 0); |
155 |
+ start = icaltime_from_timet_with_zone(year_start, 0, NULL); |
156 |
|
157 |
iter = icalrecur_iterator_new(rule, start); |
158 |
iter_start = icalrecur_iterator_next(iter); |
159 |
@@ -298,9 +242,8 @@ icalcomponent *icaltzutil_fetch_timezone |
160 |
size_t i, num_trans, num_chars, num_leaps, num_isstd, num_isgmt; |
161 |
size_t num_types = 0; |
162 |
size_t size; |
163 |
- time_t trans; |
164 |
- int dstidx = -1, stdidx = -1, pos, sign, zidx, zp_idx; |
165 |
- icalcomponent *std_comp = NULL; |
166 |
+ int pos, sign; |
167 |
+ time_t now = time(NULL); |
168 |
|
169 |
const char *zonedir; |
170 |
FILE *f = NULL; |
171 |
@@ -313,12 +256,22 @@ icalcomponent *icaltzutil_fetch_timezone |
172 |
leap *leaps = NULL; |
173 |
char *tzid = NULL; |
174 |
|
175 |
- time_t start, end; |
176 |
int idx, prev_idx; |
177 |
- icalcomponent *tz_comp = NULL, *comp = NULL, *dst_comp; |
178 |
+ icalcomponent *tz_comp = NULL, *comp = NULL; |
179 |
icalproperty *icalprop; |
180 |
- icaltimetype dtstart, icaltime; |
181 |
- struct icalrecurrencetype ical_recur; |
182 |
+ icaltimetype icaltime; |
183 |
+ struct icalrecurrencetype standard_recur; |
184 |
+ struct icalrecurrencetype daylight_recur; |
185 |
+ icaltimetype prev_standard_time = icaltime_null_time(); |
186 |
+ icaltimetype prev_daylight_time = icaltime_null_time(); |
187 |
+ icaltimetype prev_prev_standard_time; |
188 |
+ icaltimetype prev_prev_daylight_time; |
189 |
+ long prev_standard_gmtoff; |
190 |
+ long prev_daylight_gmtoff; |
191 |
+ icalcomponent *cur_standard_comp = NULL; |
192 |
+ icalcomponent *cur_daylight_comp = NULL; |
193 |
+ icalproperty *cur_standard_rrule_property; |
194 |
+ icalproperty *cur_daylight_rrule_property; |
195 |
|
196 |
if (icaltimezone_get_builtin_tzdata()) { |
197 |
goto error; |
198 |
@@ -448,15 +401,8 @@ icalcomponent *icaltzutil_fetch_timezone |
199 |
/* Read all the contents now */ |
200 |
|
201 |
for (i = 0; i < num_types; i++) { |
202 |
- types[i].zname = zname_from_stridx(znames, (long)types[i].abbr); |
203 |
- } |
204 |
- |
205 |
- if (!_s_use_exact_timezones) { |
206 |
- if (num_trans != 0) { |
207 |
- find_transidx(transitions, types, trans_idx, (long int)num_trans, &stdidx, &dstidx); |
208 |
- } else { |
209 |
- stdidx = 0; |
210 |
- } |
211 |
+ /* coverity[tainted_data] */ |
212 |
+ types[i].zname = zname_from_stridx(znames, types[i].abbr); |
213 |
} |
214 |
|
215 |
tz_comp = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT); |
216 |
@@ -476,140 +422,202 @@ icalcomponent *icaltzutil_fetch_timezone |
217 |
icalproperty_set_x_name(icalprop, "X-LIC-LOCATION"); |
218 |
icalcomponent_add_property(tz_comp, icalprop); |
219 |
|
220 |
- if (!_s_use_exact_timezones) { |
221 |
- if (stdidx != -1) { |
222 |
- if (num_trans != 0) { |
223 |
- zidx = trans_idx[stdidx]; |
224 |
+ prev_idx = 0; |
225 |
+ if (num_trans == 0) { |
226 |
+ prev_idx = idx = 0; |
227 |
+ } else { |
228 |
+ idx = trans_idx[0]; |
229 |
+ } |
230 |
+ |
231 |
+ for (i = 1; i < num_trans; i++) { |
232 |
+ int by_day; |
233 |
+ int is_new_comp = 0; |
234 |
+ time_t start; |
235 |
+ struct icalrecurrencetype *recur; |
236 |
+ |
237 |
+ prev_idx = idx; |
238 |
+ idx = trans_idx[i]; |
239 |
+ start = transitions[i] + types[prev_idx].gmtoff; |
240 |
+ |
241 |
+ icaltime = icaltime_from_timet_with_zone(start, 0, NULL); |
242 |
+ pos = calculate_pos(icaltime); |
243 |
+ pos < 0 ? (sign = -1): (sign = 1); |
244 |
+ by_day = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime)); |
245 |
+ |
246 |
+ // Figure out if the rule has changed since the previous year |
247 |
+ // If it has, update the recurrence rule of the current component and create a new component |
248 |
+ // If it the current component was only valid for one year then remove the recurrence rule |
249 |
+ if (types[idx].isdst) { |
250 |
+ if (cur_daylight_comp) { |
251 |
+ // Check if the pattern for daylight has changed |
252 |
+ // If it has, create a new component and update UNTIL of previous component's RRULE |
253 |
+ if (daylight_recur.by_month[0] != icaltime.month || |
254 |
+ daylight_recur.by_day[0] != by_day || |
255 |
+ types[prev_idx].gmtoff != prev_daylight_gmtoff) { |
256 |
+ // Set UNTIL of the previous component's recurrence |
257 |
+ icaltime_adjust(&prev_daylight_time, 0, 0, 0, -types[prev_idx].gmtoff); |
258 |
+ prev_daylight_time.is_utc = 1; |
259 |
+ |
260 |
+ daylight_recur.until = prev_daylight_time; |
261 |
+ icalproperty_set_rrule(cur_daylight_rrule_property, daylight_recur); |
262 |
+ |
263 |
+ cur_daylight_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); |
264 |
+ is_new_comp = 1; |
265 |
+ } |
266 |
} else { |
267 |
- zidx = 0; |
268 |
+ cur_daylight_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); |
269 |
+ is_new_comp = 1; |
270 |
} |
271 |
|
272 |
- std_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); |
273 |
- icalprop = icalproperty_new_tzname(types[zidx].zname); |
274 |
- icalcomponent_add_property(std_comp, icalprop); |
275 |
+ comp = cur_daylight_comp; |
276 |
+ recur = &daylight_recur; |
277 |
|
278 |
- if (dstidx != -1) { |
279 |
- zp_idx = trans_idx[stdidx-1]; |
280 |
+ if (icaltime_is_null_time(prev_daylight_time)) { |
281 |
+ prev_prev_daylight_time = icaltime; |
282 |
} else { |
283 |
- zp_idx = zidx; |
284 |
+ prev_prev_daylight_time = prev_daylight_time; |
285 |
} |
286 |
- /* DTSTART localtime uses TZOFFSETFROM UTC offset */ |
287 |
- if (num_trans != 0) { |
288 |
- trans = transitions[stdidx] + types[zp_idx].gmtoff; |
289 |
+ |
290 |
+ prev_daylight_time = icaltime; |
291 |
+ prev_daylight_gmtoff = types[prev_idx].gmtoff; |
292 |
+ } else { |
293 |
+ if (cur_standard_comp) { |
294 |
+ // Check if the pattern for standard has changed |
295 |
+ // If it has, create a new component and update UNTIL |
296 |
+ // of the previous component's RRULE |
297 |
+ if (standard_recur.by_month[0] != icaltime.month || |
298 |
+ standard_recur.by_day[0] != by_day || |
299 |
+ types[prev_idx].gmtoff != prev_standard_gmtoff) { |
300 |
+ icaltime_adjust(&prev_standard_time, 0, 0, 0, -types[prev_idx].gmtoff); |
301 |
+ prev_standard_time.is_utc = 1; |
302 |
+ |
303 |
+ standard_recur.until = prev_standard_time; |
304 |
+ icalproperty_set_rrule(cur_standard_rrule_property, standard_recur); |
305 |
+ |
306 |
+ cur_standard_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); |
307 |
+ is_new_comp = 1; |
308 |
+ |
309 |
+ // Are we transitioning on the daylight date? |
310 |
+ // If so, that means the time zone is switching off of DST |
311 |
+ // We need to set UNTIL for the daylight component |
312 |
+ if (cur_daylight_comp && daylight_recur.by_month[0] == icaltime.month && |
313 |
+ daylight_recur.by_day[0] == by_day) { |
314 |
+ icaltime_adjust(&prev_daylight_time, 0, 0, 0, -types[prev_idx].gmtoff); |
315 |
+ prev_daylight_time.is_utc = 1; |
316 |
+ |
317 |
+ daylight_recur.until = prev_daylight_time; |
318 |
+ icalproperty_set_rrule(cur_daylight_rrule_property, daylight_recur); |
319 |
+ } |
320 |
+ } |
321 |
} else { |
322 |
- trans = (time_t)types[zp_idx].gmtoff; |
323 |
+ cur_standard_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); |
324 |
+ is_new_comp = 1; |
325 |
} |
326 |
- icaltime = icaltime_from_timet(trans, 0); |
327 |
- dtstart = icaltime; |
328 |
- dtstart.year = 1970; |
329 |
- dtstart.minute = dtstart.second = 0; |
330 |
- icalprop = icalproperty_new_dtstart(dtstart); |
331 |
- icalcomponent_add_property(std_comp, icalprop); |
332 |
|
333 |
- /* If DST changes are present use RRULE */ |
334 |
- if (dstidx != -1) { |
335 |
- icalrecurrencetype_clear(&ical_recur); |
336 |
- ical_recur.freq = ICAL_YEARLY_RECURRENCE; |
337 |
- ical_recur.by_month[0] = icaltime.month; |
338 |
- pos = calculate_pos(icaltime); |
339 |
- pos < 0 ? (sign = -1): (sign = 1); |
340 |
- ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime)); |
341 |
- icalprop = icalproperty_new_rrule(ical_recur); |
342 |
- icalcomponent_add_property(std_comp, icalprop); |
343 |
+ comp = cur_standard_comp; |
344 |
+ recur = &standard_recur; |
345 |
|
346 |
- adjust_dtstart_day_to_rrule(std_comp, ical_recur); |
347 |
+ if (icaltime_is_null_time(prev_standard_time)) { |
348 |
+ prev_prev_standard_time = icaltime; |
349 |
+ } else { |
350 |
+ prev_prev_standard_time = prev_standard_time; |
351 |
} |
352 |
- icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff); |
353 |
- icalcomponent_add_property(std_comp, icalprop); |
354 |
- icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff); |
355 |
- icalcomponent_add_property(std_comp, icalprop); |
356 |
- icalcomponent_add_component(tz_comp, std_comp); |
357 |
- } else { |
358 |
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); |
359 |
+ |
360 |
+ prev_standard_time = icaltime; |
361 |
+ prev_standard_gmtoff = types[prev_idx].gmtoff; |
362 |
} |
363 |
|
364 |
- if (dstidx != -1) { |
365 |
- zidx = trans_idx[dstidx]; |
366 |
- zp_idx = trans_idx[dstidx-1]; |
367 |
- dst_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); |
368 |
- icalprop = icalproperty_new_tzname(types[zidx].zname); |
369 |
- icalcomponent_add_property(dst_comp, icalprop); |
370 |
+ if (is_new_comp) { |
371 |
+ icalprop = icalproperty_new_tzname(types[idx].zname); |
372 |
+ icalcomponent_add_property(comp, icalprop); |
373 |
+ icalprop = icalproperty_new_dtstart(icaltime); |
374 |
+ icalcomponent_add_property(comp, icalprop); |
375 |
+ icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff); |
376 |
+ icalcomponent_add_property(comp, icalprop); |
377 |
+ icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff); |
378 |
+ icalcomponent_add_property(comp, icalprop); |
379 |
|
380 |
- /* DTSTART localtime uses TZOFFSETFROM UTC offset */ |
381 |
- if (num_trans != 0) { |
382 |
- trans = transitions[dstidx] + types[zp_idx].gmtoff; |
383 |
+ // Determine the recurrence rule for the current set of changes |
384 |
+ icalrecurrencetype_clear(recur); |
385 |
+ recur->freq = ICAL_YEARLY_RECURRENCE; |
386 |
+ recur->by_month[0] = icaltime.month; |
387 |
+ recur->by_day[0] = by_day; |
388 |
+ icalprop = icalproperty_new_rrule(*recur); |
389 |
+ icalcomponent_add_property(comp, icalprop); |
390 |
+ |
391 |
+ if (types[idx].isdst) { |
392 |
+ cur_daylight_rrule_property = icalprop; |
393 |
} else { |
394 |
- trans = (time_t)types[zp_idx].gmtoff; |
395 |
+ cur_standard_rrule_property = icalprop; |
396 |
} |
397 |
|
398 |
- icaltime = icaltime_from_timet(trans, 0); |
399 |
- dtstart = icaltime; |
400 |
- dtstart.year = 1970; |
401 |
- dtstart.minute = dtstart.second = 0; |
402 |
- icalprop = icalproperty_new_dtstart(dtstart); |
403 |
- icalcomponent_add_property(dst_comp, icalprop); |
404 |
+ adjust_dtstart_day_to_rrule(comp, *recur); |
405 |
|
406 |
- icalrecurrencetype_clear(&ical_recur); |
407 |
- ical_recur.freq = ICAL_YEARLY_RECURRENCE; |
408 |
- ical_recur.by_month[0] = icaltime.month; |
409 |
- pos = calculate_pos(icaltime); |
410 |
- pos < 0 ? (sign = -1): (sign = 1); |
411 |
- ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime)); |
412 |
- icalprop = icalproperty_new_rrule(ical_recur); |
413 |
- icalcomponent_add_property(dst_comp, icalprop); |
414 |
+ icalcomponent_add_component(tz_comp, comp); |
415 |
+ } |
416 |
+ } |
417 |
|
418 |
- adjust_dtstart_day_to_rrule(dst_comp, ical_recur); |
419 |
+ // Check if the last daylight or standard date was before now |
420 |
+ // If so, set the UNTIL date to the second-to-last transition date |
421 |
+ // and then insert a new component to indicate the time zone doesn't transition anymore |
422 |
+ if (cur_daylight_comp && icaltime_as_timet(prev_daylight_time) < now) { |
423 |
+ icaltime_adjust(&prev_prev_daylight_time, 0, 0, 0, -prev_daylight_gmtoff); |
424 |
+ prev_prev_daylight_time.is_utc = 1; |
425 |
|
426 |
- icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff); |
427 |
- icalcomponent_add_property(dst_comp, icalprop); |
428 |
+ daylight_recur.until = prev_prev_daylight_time; |
429 |
+ icalproperty_set_rrule(cur_daylight_rrule_property, daylight_recur); |
430 |
|
431 |
- icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff); |
432 |
- icalcomponent_add_property(dst_comp, icalprop); |
433 |
+ comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); |
434 |
+ icalprop = icalproperty_new_tzname(types[idx].zname); |
435 |
+ icalcomponent_add_property(comp, icalprop); |
436 |
+ icalprop = icalproperty_new_dtstart(prev_daylight_time); |
437 |
+ icalcomponent_add_property(comp, icalprop); |
438 |
+ icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff); |
439 |
+ icalcomponent_add_property(comp, icalprop); |
440 |
+ icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff); |
441 |
+ icalcomponent_add_property(comp, icalprop); |
442 |
+ icalcomponent_add_component(tz_comp, comp); |
443 |
+ } |
444 |
|
445 |
- icalcomponent_add_component(tz_comp, dst_comp); |
446 |
- } |
447 |
- } else { /*exact vtimezones*/ |
448 |
- prev_idx = 0; |
449 |
- if (num_trans == 0) { |
450 |
- prev_idx = idx = 0; |
451 |
+ if (cur_standard_comp && icaltime_as_timet(prev_standard_time) < now) { |
452 |
+ icaltime_adjust(&prev_prev_standard_time, 0, 0, 0, -prev_standard_gmtoff); |
453 |
+ prev_prev_standard_time.is_utc = 1; |
454 |
+ |
455 |
+ standard_recur.until = prev_prev_standard_time; |
456 |
+ icalproperty_set_rrule(cur_standard_rrule_property, standard_recur); |
457 |
+ |
458 |
+ comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); |
459 |
+ icalprop = icalproperty_new_tzname(types[idx].zname); |
460 |
+ icalcomponent_add_property(comp, icalprop); |
461 |
+ icalprop = icalproperty_new_dtstart(prev_standard_time); |
462 |
+ icalcomponent_add_property(comp, icalprop); |
463 |
+ icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff); |
464 |
+ icalcomponent_add_property(comp, icalprop); |
465 |
+ icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff); |
466 |
+ icalcomponent_add_property(comp, icalprop); |
467 |
+ icalcomponent_add_component(tz_comp, comp); |
468 |
+ } |
469 |
+ |
470 |
+ if (num_trans <= 1) { |
471 |
+ time_t start; |
472 |
+ |
473 |
+ if (num_trans == 1) { |
474 |
+ start = transitions[0] + types[prev_idx].gmtoff; |
475 |
} else { |
476 |
- idx = trans_idx[0]; |
477 |
+ start = 0; |
478 |
} |
479 |
- start = 0; |
480 |
- for (i = 1; i < num_trans; i++, start = end) { |
481 |
- prev_idx = idx; |
482 |
- idx = trans_idx[i]; |
483 |
- end = transitions[i] + types[prev_idx].gmtoff; |
484 |
- /* don't bother starting until the epoch */ |
485 |
- if (0 > end) |
486 |
- continue; |
487 |
|
488 |
- if (types[prev_idx].isdst) { |
489 |
- comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); |
490 |
- } else { |
491 |
- comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); |
492 |
- } |
493 |
- icalprop = icalproperty_new_tzname(types[prev_idx].zname); |
494 |
- icalcomponent_add_property(comp, icalprop); |
495 |
- dtstart = icaltime_from_timet(start, 0); |
496 |
- icalprop = icalproperty_new_dtstart(dtstart); |
497 |
- icalcomponent_add_property(comp, icalprop); |
498 |
- icalprop = icalproperty_new_tzoffsetfrom(types[idx].gmtoff); |
499 |
- icalcomponent_add_property(comp, icalprop); |
500 |
- icalprop = icalproperty_new_tzoffsetto(types[prev_idx].gmtoff); |
501 |
- icalcomponent_add_property(comp, icalprop); |
502 |
- icalcomponent_add_component(tz_comp, comp); |
503 |
- } |
504 |
- /* finally, add a last zone with no end date */ |
505 |
+ // This time zone doesn't transition, insert a single VTIMEZONE component |
506 |
if (types[idx].isdst) { |
507 |
comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); |
508 |
} else { |
509 |
comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); |
510 |
} |
511 |
+ |
512 |
icalprop = icalproperty_new_tzname(types[idx].zname); |
513 |
icalcomponent_add_property(comp, icalprop); |
514 |
- dtstart = icaltime_from_timet(start, 0); |
515 |
- icalprop = icalproperty_new_dtstart(dtstart); |
516 |
+ icaltime = icaltime_from_timet_with_zone(start, 0, NULL); |
517 |
+ icalprop = icalproperty_new_dtstart(icaltime); |
518 |
icalcomponent_add_property(comp, icalprop); |
519 |
icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff); |
520 |
icalcomponent_add_property(comp, icalprop); |