diff options
-rw-r--r-- | CMakeLists.txt | 14 | ||||
-rw-r--r-- | Install.txt | 7 | ||||
-rw-r--r-- | appveyor.yml | 2 | ||||
-rw-r--r-- | config.h.cmake | 3 | ||||
-rwxr-xr-x | scripts/buildtests.sh | 4 | ||||
-rw-r--r-- | src/libical/icaltz-util.c | 364 | ||||
-rw-r--r-- | src/libical/icaltz-util.h | 6 | ||||
-rw-r--r-- | src/test/timezones.c | 10 |
8 files changed, 193 insertions, 217 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e0001e6..61adad9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,13 +52,6 @@ # Set to build using a 32bit time_t (ignored unless building with MSVC on Windows) # Default=false (use the default size of time_t) # -# -DUSE_INTEROPERABLE_VTIMEZONES=[true|false] -# Unset to use exact rather than inter-operable VTIMEZONEs. -# Default=True (inter-operable VTIMEZONEs) -# Notes: -# Change the behavior at runtime using the icaltzutil_set_exact_vtimezones_support() function. -# Query the behavior at runtime using the icaltzutil_get_exact_vtimezones_support() function. -# ## Special CMake Options for Developers # @@ -222,13 +215,6 @@ if(WIN32 OR WINCE) endif() endif() -option(USE_INTEROPERABLE_VTIMEZONES "use inter-operable rather than exact vtimezones." True) -if(USE_INTEROPERABLE_VTIMEZONES) - set(USE_INTEROPERABLE_VTIMEZONES 1) -else() - set(USE_INTEROPERABLE_VTIMEZONES 0) -endif() - include(ConfigureChecks.cmake) add_definitions(-DHAVE_CONFIG_H) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/Install.txt b/Install.txt index cb6c6380..9b8e0141 100644 --- a/Install.txt +++ b/Install.txt @@ -124,13 +124,6 @@ Use these CMake options to adjust the library behavior as follows: Default=false (use the system timezone data on non-Windows systems) ALWAYS true on Windows systems - * USE_INTEROPERABLE_VTIMEZONES=[true|false] - Unset to use exact rather than inter-operable VTIMEZONEs. - Default=True (inter-operable VTIMEZONEs) - Notes: - Change the behavior at runtime using the icaltzutil_set_exact_vtimezones_support() function. - Query the behavior at runtime using the icaltzutil_get_exact_vtimezones_support() function. - == Tweaking the Installation Directories == By default, the installation layout is according to the GNU standard installation directories. http://www.gnu.org/prep/standards/html_node/Directory-Variables.html diff --git a/appveyor.yml b/appveyor.yml index dc59a2c6..77e10c2b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,7 +46,7 @@ build_script: - call scripts\set_compiler_env.bat - mkdir build - cd build - - if "%configuration%" EQU "MinGW" ( cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DICAL_GLIB=False -DUSE_INTEROPERABLE_VTIMEZONES=true .. ) else ( cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DICAL_GLIB=False -DUSE_INTEROPERABLE_VTIMEZONES=true .. ) + - if "%configuration%" EQU "MinGW" ( cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DICAL_GLIB=False .. ) else ( cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DICAL_GLIB=False .. ) - nmake # to disable automatic builds diff --git a/config.h.cmake b/config.h.cmake index 14914bb0..8fd3421b 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -193,9 +193,6 @@ /* whether we should bring our own TZ-Data */ #cmakedefine USE_BUILTIN_TZDATA -/* whether we should use operable vtimezones */ -#cmakedefine USE_INTEROPERABLE_VTIMEZONES - /* Define to empty if `const' does not conform to ANSI C. */ #cmakedefine const diff --git a/scripts/buildtests.sh b/scripts/buildtests.sh index 128378fe..ce34b4cf 100755 --- a/scripts/buildtests.sh +++ b/scripts/buildtests.sh @@ -432,7 +432,7 @@ cd .. TOP=`pwd` BDIR="" -CMAKEOPTS="-DCMAKE_BUILD_TYPE=Debug -DUSE_INTEROPERABLE_VTIMEZONES=True -DGOBJECT_INTROSPECTION=True -DICAL_GLIB=True" +CMAKEOPTS="-DCMAKE_BUILD_TYPE=Debug -DGOBJECT_INTROSPECTION=True -DICAL_GLIB=True" #Static code checkers KRAZY @@ -454,6 +454,6 @@ CLANG_BUILD test1cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i6 CLANG_BUILD test2cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake $CMAKEOPTS" #Address sanitizer -ASAN_BUILD test "-DUSE_INTEROPERABLE_VTIMEZONES=True" +ASAN_BUILD test "" echo "ALL TESTS COMPLETED SUCCESSFULLY" diff --git a/src/libical/icaltz-util.c b/src/libical/icaltz-util.c index 1fdcb377..d837b430 100644 --- a/src/libical/icaltz-util.c +++ b/src/libical/icaltz-util.c @@ -196,45 +196,6 @@ const char *icaltzutil_get_zone_directory(void) 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_with_zone(now, 0, NULL); - 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}; @@ -250,22 +211,6 @@ static int calculate_pos(icaltimetype icaltime) 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; @@ -297,9 +242,8 @@ 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 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; @@ -312,12 +256,22 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location) 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; @@ -451,14 +405,6 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location) types[i].zname = zname_from_stridx(znames, 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; - } - } - tz_comp = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT); /* Add tzid property */ @@ -476,136 +422,202 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location) 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_with_zone(trans, 0, NULL); - 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); - - adjust_dtstart_day_to_rrule(std_comp, ical_recur); - } - 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); - } - 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); - - /* DTSTART localtime uses TZOFFSETFROM UTC offset */ - trans = transitions[dstidx] + types[zp_idx].gmtoff; - - icaltime = icaltime_from_timet_with_zone(trans, 0, NULL); - dtstart = icaltime; - dtstart.year = 1970; - dtstart.minute = dtstart.second = 0; - icalprop = icalproperty_new_dtstart(dtstart); - icalcomponent_add_property(dst_comp, icalprop); - - 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); - - adjust_dtstart_day_to_rrule(dst_comp, ical_recur); - - icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff); - icalcomponent_add_property(dst_comp, icalprop); - - icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff); - icalcomponent_add_property(dst_comp, icalprop); - - icalcomponent_add_component(tz_comp, dst_comp); - } - } else { /*exact vtimezones*/ - prev_idx = 0; - if (num_trans == 0) { - prev_idx = idx = 0; - } else { - idx = trans_idx[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); + comp = cur_standard_comp; + recur = &standard_recur; + + if (icaltime_is_null_time(prev_standard_time)) { + prev_prev_standard_time = icaltime; } else { - comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); + prev_prev_standard_time = prev_standard_time; } - icalprop = icalproperty_new_tzname(types[prev_idx].zname); + + prev_standard_time = icaltime; + prev_standard_gmtoff = types[prev_idx].gmtoff; + } + + if (is_new_comp) { + icalprop = icalproperty_new_tzname(types[idx].zname); icalcomponent_add_property(comp, icalprop); - dtstart = icaltime_from_timet_with_zone(start, 0, NULL); - icalprop = icalproperty_new_dtstart(dtstart); + icalprop = icalproperty_new_dtstart(icaltime); icalcomponent_add_property(comp, icalprop); - icalprop = icalproperty_new_tzoffsetfrom(types[idx].gmtoff); + icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff); icalcomponent_add_property(comp, icalprop); - icalprop = icalproperty_new_tzoffsetto(types[prev_idx].gmtoff); + icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff); icalcomponent_add_property(comp, icalprop); + + // 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 { + cur_standard_rrule_property = icalprop; + } + + adjust_dtstart_day_to_rrule(comp, *recur); + icalcomponent_add_component(tz_comp, comp); } - /* finally, add a last zone with no end date */ + } + + // 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; + + daylight_recur.until = prev_prev_daylight_time; + icalproperty_set_rrule(cur_daylight_rrule_property, daylight_recur); + + 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); + } + + 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 { + start = 0; + } + + // 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_with_zone(start, 0, NULL); - 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/src/libical/icaltz-util.h b/src/libical/icaltz-util.h index 0a4c3c1b..e35aff25 100644 --- a/src/libical/icaltz-util.h +++ b/src/libical/icaltz-util.h @@ -32,10 +32,4 @@ LIBICAL_ICAL_EXPORT const char *icaltzutil_get_zone_directory(void); 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/src/test/timezones.c b/src/test/timezones.c index 74d9fc33..661c008f 100644 --- a/src/test/timezones.c +++ b/src/test/timezones.c @@ -57,6 +57,7 @@ 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; @@ -136,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) { @@ -158,13 +159,6 @@ 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(); |