int icaltime_compare_date_only_tz(const struct icaltimetype a_in, const struct icaltimetype b_in, icaltimezone *tz) { struct icaltimetype a, b; a = icaltime_convert_to_zone(a_in, tz); b = icaltime_convert_to_zone(b_in, tz); if (a.year > b.year) { return 1; } else if (a.year < b.year) { return -1; } if (a.month > b.month) { return 1; } else if (a.month < b.month) { return -1; } if (a.day > b.day) { return 1; } else if (a.day < b.day) { return -1; } return 0; }
int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in) { struct icaltimetype a, b; /* We only need to perform time zone conversion if times aren't in the same time zone */ if (a_in.zone != b_in.zone || a_in.is_utc != b_in.is_utc) { a = icaltime_convert_to_zone(a_in, icaltimezone_get_utc_timezone()); b = icaltime_convert_to_zone(b_in, icaltimezone_get_utc_timezone()); } else { a = a_in; b = b_in; } if (a.year > b.year) { return 1; } else if (a.year < b.year) { return -1; } else if (a.month > b.month) { return 1; } else if (a.month < b.month) { return -1; } else if (a.day > b.day) { return 1; } else if (a.day < b.day) { return -1; } /* if both are dates, we are done */ if (a.is_date && b.is_date) { return 0; /* else, if only one is a date (and we already know the date part is equal), then the other is greater */ } else if (b.is_date) { return 1; } else if (a.is_date) { return -1; } else if (a.hour > b.hour) { return 1; } else if (a.hour < b.hour) { return -1; } else if (a.minute > b.minute) { return 1; } else if (a.minute < b.minute) { return -1; } else if (a.second > b.second) { return 1; } else if (a.second < b.second) { return -1; } return 0; }
/** * e_cal_util_construct_instance: * @icalcomp: A recurring #icalcomponent * @rid: The RECURRENCE-ID to construct a component for * * This checks that @rid indicates a valid recurrence of @icalcomp, and * if so, generates a copy of @comp containing a RECURRENCE-ID of @rid. * * Returns: the instance, or %NULL. **/ icalcomponent * e_cal_util_construct_instance (icalcomponent *icalcomp, struct icaltimetype rid) { struct instance_data instance; struct icaltimetype start, end; g_return_val_if_fail (icalcomp != NULL, NULL); /* Make sure this is really recurring */ if (!icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY) && !icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY)) return NULL; /* Make sure the specified instance really exists */ start = icaltime_convert_to_zone (rid, icaltimezone_get_utc_timezone ()); end = start; icaltime_adjust (&end, 0, 0, 0, 1); instance.start = icaltime_as_timet (start); instance.found = FALSE; icalcomponent_foreach_recurrence (icalcomp, start, end, check_instance, &instance); if (!instance.found) return NULL; /* Make the instance */ icalcomp = icalcomponent_new_clone (icalcomp); icalcomponent_set_recurrenceid (icalcomp, rid); return icalcomp; }
PRTime calDateTime::IcaltimeToPRTime(icaltimetype const* icalt, icaltimezone const* tz) { icaltimetype tt; PRExplodedTime et; /* If the time is the special null time, return 0. */ if (icaltime_is_null_time(*icalt)) { return 0; } if (tz) { // use libical for timezone conversion, as it can handle all ics // timezones. having nspr do it is much harder. tt = icaltime_convert_to_zone(*icalt, const_cast<icaltimezone *>(tz)); } else { tt = *icalt; } /* Empty the destination */ memset(&et, 0, sizeof(struct PRExplodedTime)); /* Fill the fields */ if (icaltime_is_date(tt)) { et.tm_sec = et.tm_min = et.tm_hour = 0; } else { et.tm_sec = tt.second; et.tm_min = tt.minute; et.tm_hour = tt.hour; } et.tm_mday = static_cast<int16_t>(tt.day); et.tm_month = static_cast<int16_t>(tt.month-1); et.tm_year = static_cast<int16_t>(tt.year); return PR_ImplodeTime(&et); }
int main (int argc, char **argv) { gint error = 0; JanaTime *jtime; icaltimetype itime; icaltimezone *zone = icaltimezone_get_builtin_timezone ( "Europe/London"); /* Test DST conversions */ itime = icaltime_null_time (); itime.second = 0; itime.minute = 0; itime.hour = 2; itime.day = 1; itime.month = 1; itime.year = 2007; itime = icaltime_convert_to_zone (itime, zone); g_type_init (); jtime = jana_ecal_time_new_from_icaltime (&itime); /*g_debug ("%s time: %d/%d/%d, %d:%02d %s", jana_time_get_tzname (jtime), jana_time_get_day (jtime), jana_time_get_month (jtime), jana_time_get_year (jtime), jana_time_get_hours (jtime), jana_time_get_minutes (jtime), jana_time_get_daylight (jtime) ? "DST" : ""); g_debug ("Setting time forward to BST");*/ jana_time_set_month (jtime, 7); if ((jana_time_get_hours (jtime) != 3) || (!jana_time_get_daylight (jtime))) error = 1; /*g_debug ("%s time: %d/%d/%d, %d:%02d %s", jana_time_get_tzname (jtime), jana_time_get_day (jtime), jana_time_get_month (jtime), jana_time_get_year (jtime), jana_time_get_hours (jtime), jana_time_get_minutes (jtime), jana_time_get_daylight (jtime) ? "DST" : "");*/ g_object_unref (jtime); if (error) g_warning ("Error (%d)", error); else g_message ("Success"); return error; }
/* Builds a static string out of an exception date */ static gchar * get_exception_string (EDateTimeList *date_time_list, struct icaltimetype *itt) { static gchar buf[256]; struct icaltimetype tt; struct tm tmp_tm; icaltimezone *zone; gboolean use_24_hour_format; use_24_hour_format = e_date_time_list_get_use_24_hour_format (date_time_list); zone = e_date_time_list_get_timezone (date_time_list); tt = *itt; if (zone) tt = icaltime_convert_to_zone (tt, zone); tmp_tm.tm_year = tt.year - 1900; tmp_tm.tm_mon = tt.month - 1; tmp_tm.tm_mday = tt.day; tmp_tm.tm_hour = tt.hour; tmp_tm.tm_min = tt.minute; tmp_tm.tm_sec = tt.second; tmp_tm.tm_isdst = -1; tmp_tm.tm_wday = time_day_of_week ( tt.day, tt.month - 1, tt.year); e_time_format_date_and_time ( &tmp_tm, use_24_hour_format, FALSE, FALSE, buf, sizeof (buf)); return buf; }
/** * e_cal_util_split_at_instance: * @icalcomp: A (recurring) #icalcomponent * @rid: The base RECURRENCE-ID to remove * @master_dtstart: The DTSTART of the master object * * Splits a recurring @icalcomp into two at time @rid. The returned icalcomponent * is modified @icalcomp which contains recurrences beginning at @rid, inclusive. * The instance identified by @rid should exist. The @master_dtstart can be * a null time, then it is read from the @icalcomp. * * Use e_cal_util_remove_instances() with E_CAL_OBJ_MOD_THIS_AND_FUTURE mode * on the @icalcomp to remove the overlapping interval from it, if needed. * * Returns: the split icalcomponent, or %NULL. * * Since: 3.16 **/ icalcomponent * e_cal_util_split_at_instance (icalcomponent *icalcomp, struct icaltimetype rid, struct icaltimetype master_dtstart) { icalproperty *prop; struct instance_data instance; struct icaltimetype start, end; struct icaldurationtype duration; GSList *remove_props = NULL, *link; g_return_val_if_fail (icalcomp != NULL, NULL); g_return_val_if_fail (!icaltime_is_null_time (rid), NULL); /* Make sure this is really recurring */ if (!icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY) && !icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY)) return NULL; /* Make sure the specified instance really exists */ start = icaltime_convert_to_zone (rid, icaltimezone_get_utc_timezone ()); end = start; icaltime_adjust (&end, 0, 0, 0, 1); instance.start = icaltime_as_timet (start); instance.found = FALSE; icalcomponent_foreach_recurrence (icalcomp, start, end, check_instance, &instance); /* Make the copy */ icalcomp = icalcomponent_new_clone (icalcomp); e_cal_util_remove_instances_ex (icalcomp, rid, E_CAL_OBJ_MOD_THIS_AND_PRIOR, TRUE, FALSE); start = rid; if (icaltime_is_null_time (master_dtstart)) master_dtstart = icalcomponent_get_dtstart (icalcomp); duration = icalcomponent_get_duration (icalcomp); /* Expect that DTSTART and DTEND are already set when the instance could not be found */ if (instance.found) { icalcomponent_set_dtstart (icalcomp, start); /* Update either DURATION or DTEND */ if (icaltime_is_null_time (icalcomponent_get_dtend (icalcomp))) { icalcomponent_set_duration (icalcomp, duration); } else { end = start; if (duration.is_neg) icaltime_adjust (&end, -duration.days - 7 * duration.weeks, -duration.hours, -duration.minutes, -duration.seconds); else icaltime_adjust (&end, duration.days + 7 * duration.weeks, duration.hours, duration.minutes, duration.seconds); icalcomponent_set_dtend (icalcomp, end); } } /* any RRULE with 'count' should be shortened */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) { struct icaltimetype recur; struct icalrecurrencetype rule; rule = icalproperty_get_rrule (prop); if (rule.count != 0) { gint occurrences_count = 0; icalrecur_iterator *iter; iter = icalrecur_iterator_new (rule, master_dtstart); while (recur = icalrecur_iterator_next (iter), !icaltime_is_null_time (recur) && occurrences_count < rule.count) { if (icaltime_compare (recur, rid) >= 0) break; occurrences_count++; } icalrecur_iterator_free (iter); if (icaltime_is_null_time (recur)) { remove_props = g_slist_prepend (remove_props, prop); } else { rule.count -= occurrences_count; icalproperty_set_rrule (prop, rule); icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE"); } } } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); return icalcomp; }
icalcomponent *icalbdbsetiter_to_next(icalset *set, icalsetiter *i) { icalcomponent *comp = NULL; struct icaltimetype start, next; icalproperty *dtstart, *rrule, *prop, *due; struct icalrecurrencetype recur; icaltimezone *u_zone; int g = 0; int orig_time_was_utc = 0; _unused(set); do { /* no pending occurrence, read the next component */ if (i->last_component == NULL) { comp = icalcompiter_next(&(i->iter)); } else { comp = i->last_component; } /* no next component, simply return */ if (comp == 0) { return NULL; } if (i->gauge == 0) { return comp; } /* finding the next matched component and return it to the caller */ rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); g = icalgauge_get_expand(i->gauge); /* a recurring component with expand query */ if (rrule != 0 && g == 1) { u_zone = icaltimezone_get_builtin_timezone(i->tzid); /* use UTC, if that's all we have. */ if (!u_zone) { u_zone = icaltimezone_get_utc_timezone(); } recur = icalproperty_get_rrule(rrule); start = icaltime_from_timet(time(0), 0); if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) { dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY); if (dtstart) { start = icalproperty_get_dtstart(dtstart); } } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) { due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY); if (due) { start = icalproperty_get_due(due); } } /* Convert to the user's timezone in order to be able to compare * the results from the rrule iterator. */ if (icaltime_is_utc(start)) { start = icaltime_convert_to_zone(start, u_zone); orig_time_was_utc = 1; } if (i->ritr == NULL) { i->ritr = icalrecur_iterator_new(recur, start); next = icalrecur_iterator_next(i->ritr); i->last_component = comp; } else { next = icalrecur_iterator_next(i->ritr); if (icaltime_is_null_time(next)) { i->last_component = NULL; icalrecur_iterator_free(i->ritr); i->ritr = NULL; /* no more occurrence, should go to get next component */ continue; } else { i->last_component = comp; } } /* if it is excluded, do next one */ if (icalproperty_recurrence_is_excluded(comp, &start, &next)) { next = icalrecur_iterator_next(i->ritr); continue; } /* set recurrence-id value to the property if the property already exist; * add the recurrence id property and the value if the property does not exist */ prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY); if (prop == 0) { icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next)); } else { icalproperty_set_recurrenceid(prop, next); } if (orig_time_was_utc) { next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone()); } } /* end of recurring event with expand query */ if (comp != 0 && (i->gauge == 0 || icalgauge_compare(i->gauge, comp) == 1)) { /* found a matched, return it */ return comp; } } while (comp != 0); return NULL; /*unreachable */ }
icalcomponent *icalbdbset_form_a_matched_recurrence_component(icalsetiter *itr) { icalcomponent *comp = NULL; struct icaltimetype start, next; icalproperty *dtstart, *rrule, *prop, *due; struct icalrecurrencetype recur; icaltimezone *u_zone; int orig_time_was_utc = 0; comp = itr->last_component; if (comp == NULL || itr->gauge == NULL) { return NULL; } rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); /* if there is no RRULE, simply return to the caller */ if (rrule == NULL) { return NULL; } u_zone = icaltimezone_get_builtin_timezone(itr->tzid); /* use UTC, if that's all we have. */ if (!u_zone) { u_zone = icaltimezone_get_utc_timezone(); } recur = icalproperty_get_rrule(rrule); start = icaltime_from_timet(time(0), 0); if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) { dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY); if (dtstart) { start = icalproperty_get_dtstart(dtstart); } } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) { due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY); if (due) { start = icalproperty_get_due(due); } } /* Convert to the user's timezone in order to be able to compare the results * from the rrule iterator. */ if (icaltime_is_utc(start)) { start = icaltime_convert_to_zone(start, u_zone); orig_time_was_utc = 1; } if (itr->ritr == NULL) { itr->ritr = icalrecur_iterator_new(recur, start); next = icalrecur_iterator_next(itr->ritr); itr->last_component = comp; } else { next = icalrecur_iterator_next(itr->ritr); if (icaltime_is_null_time(next)) { /* no more recurrence, returns */ itr->last_component = NULL; icalrecur_iterator_free(itr->ritr); itr->ritr = NULL; /* no more pending matched occurrence, * all the pending matched occurrences have been returned */ return NULL; } else { itr->last_component = comp; } } /* if it is excluded, return NULL to the caller */ if (icalproperty_recurrence_is_excluded(comp, &start, &next)) { (void)icalrecur_iterator_next(itr->ritr); return NULL; } /* set recurrence-id value to the property if the property already exist; * add the recurrence id property and the value if the property does not exist */ prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY); if (prop == 0) { icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next)); } else { icalproperty_set_recurrenceid(prop, next); } if (orig_time_was_utc) { next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone()); } if (itr->gauge == 0 || icalgauge_compare(itr->gauge, comp) == 1) { /* find a matched and return it */ return comp; } /* not matched */ return NULL; }
icalsetiter icalbdbset_begin_component(icalset *set, icalcomponent_kind kind, icalgauge *gauge, const char *tzid) { icalsetiter itr = icalsetiter_null; icalcomponent *comp = NULL; icalcompiter citr; icalbdbset *bset; struct icaltimetype start, next; icalproperty *dtstart, *rrule, *prop, *due; struct icalrecurrencetype recur; icaltimezone *u_zone; int g = 0; int orig_time_was_utc = 0; icalerror_check_arg_re((set != 0), "set", icalsetiter_null); bset = (icalbdbset *) set; itr.gauge = gauge; itr.tzid = tzid; citr = icalcomponent_begin_component(bset->cluster, kind); comp = icalcompiter_deref(&citr); if (gauge == 0) { itr.iter = citr; return itr; } /* if there is a gauge, the first matched component is returned */ while (comp != 0) { /* check if it is a recurring component and with guage expand, if so * we need to add recurrence-id property to the given component */ rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); g = icalgauge_get_expand(gauge); if (rrule != 0 && g == 1) { /* it is a recurring event */ u_zone = icaltimezone_get_builtin_timezone(itr.tzid); /* use UTC, if that's all we have. */ if (!u_zone) { u_zone = icaltimezone_get_utc_timezone(); } recur = icalproperty_get_rrule(rrule); start = icaltime_from_timet(time(0), 0); if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) { dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY); if (dtstart) { start = icalproperty_get_dtstart(dtstart); } } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) { due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY); if (due) { start = icalproperty_get_due(due); } } /* Convert to the user's timezone in order to be able to compare * the results from the rrule iterator. */ if (icaltime_is_utc(start)) { start = icaltime_convert_to_zone(start, u_zone); orig_time_was_utc = 1; } if (itr.last_component == NULL) { itr.ritr = icalrecur_iterator_new(recur, start); next = icalrecur_iterator_next(itr.ritr); itr.last_component = comp; } else { next = icalrecur_iterator_next(itr.ritr); if (icaltime_is_null_time(next)) { itr.last_component = NULL; icalrecur_iterator_free(itr.ritr); itr.ritr = NULL; /* no matched occurrence */ goto getNextComp; } else { itr.last_component = comp; } } /* if it is excluded, do next one */ if (icalproperty_recurrence_is_excluded(comp, &start, &next)) { next = icalrecur_iterator_next(itr.ritr); continue; } /* add recurrence-id value to the property if the property already exist; * add the recurrence id property and the value if the property does not exist */ prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY); if (prop == 0) { icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next)); } else { icalproperty_set_recurrenceid(prop, next); } /* convert the next recurrence time into the user's timezone */ if (orig_time_was_utc) { next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone()); } } /* end of a recurring event */ if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) { /* find a matched and return it */ itr.iter = citr; return itr; } /* if it is a recurring but no matched occurrence has been found OR * it is not a recurring and no matched component has been found, * read the next component to find out */ getNextComp: if ((rrule != NULL && itr.last_component == NULL) || (rrule == NULL)) { (void)icalcompiter_next(&citr); comp = icalcompiter_deref(&citr); } } /* while */ /* no matched component has found */ return icalsetiter_null; }
int main() { icalarray *timezones; icaltimezone *zone, *utc_zone; char *zone_location; size_t i; int ret = 0; unsigned int total_failed = 0; unsigned int total_okay = 0; unsigned int percent_failed = 0; int verbose = 0; int day; time_t start_time; struct tm start_tm; time_t curr_time; struct tm curr_tm; struct icaltimetype curr_tt; int failed = 0; int curr_failed; int zonedef_printed = 0; #if !defined(HAVE_SETENV) static char new_tz[256]; #endif set_zone_directory("../../zoneinfo"); icaltimezone_set_tzid_prefix("/softwarestudio.org/"); timezones = icaltimezone_get_builtin_timezones(); utc_zone = icaltimezone_get_utc_timezone(); /* for all known time zones... */ for (i = 0; i < timezones->num_elements; i++) { zone = (icaltimezone *)icalarray_element_at(timezones, i); zone_location = (char *)icaltimezone_get_location(zone); if (!zone_location) continue; /* * select this location for glibc: needs support for TZ=<location> * which is not POSIX */ #if defined(HAVE_SETENV) setenv("TZ", zone_location, 1); #else new_tz[0] = '\0'; strncat(new_tz, "TZ=", 255); strncat(new_tz, zone_location, 255 - strlen(new_tz)); putenv(new_tz); #endif tzset(); /* * determine current local time and date: always use midday in * the current zone and first day of first month in the year */ start_time = time(NULL); localtime_r(&start_time, &start_tm); start_tm.tm_hour = 12; start_tm.tm_min = 0; start_tm.tm_sec = 0; start_tm.tm_mday = 1; start_tm.tm_mon = 0; start_time = mktime(&start_tm); /* check time conversion for the next 365 days */ for (day = 0, curr_time = start_time; day < 365; day++, curr_time += 24 * 60 * 60) { /* determine date/time with glibc */ localtime_r(&curr_time, &curr_tm); /* determine date/time with libical */ curr_tt = icaltime_from_timet_with_zone(curr_time, 0, utc_zone); curr_tt.zone = utc_zone; /* workaround: icaltime_from_timet_with_zone() should do this, but doesn't! */ curr_tt = icaltime_convert_to_zone(curr_tt, zone); /* compare... */ curr_failed = curr_tm.tm_year + 1900 != curr_tt.year || curr_tm.tm_mon + 1 != curr_tt.month || curr_tm.tm_mday != curr_tt.day || curr_tm.tm_hour != curr_tt.hour || curr_tm.tm_min != curr_tt.minute || curr_tm.tm_sec != curr_tt.second; /* only print first failed day and first day which is okay again */ if (verbose || curr_failed != failed) { struct tm 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", zone_location, day, verbose ? (curr_failed ? "failed" : "okay") : (curr_failed ? "first failed" : "okay again"), utc_tm.tm_year + 1900, utc_tm.tm_mon + 1, utc_tm.tm_mday, utc_tm.tm_hour, utc_tm.tm_min, utc_tm.tm_sec, curr_tm.tm_year + 1900, curr_tm.tm_mon + 1, curr_tm.tm_mday, curr_tm.tm_hour, curr_tm.tm_min, curr_tm.tm_sec, curr_tm.tm_isdst); if (curr_failed) { printf(" != libical %04d-%02d-%02d %02d:%02d:%02d dst %d", curr_tt.year, curr_tt.month, curr_tt.day, curr_tt.hour, curr_tt.minute, curr_tt.second, curr_tt.is_daylight); ret = 1; } printf("\n"); failed = curr_failed; if (!zonedef_printed) { icalcomponent *comp = icaltimezone_get_component(zone); if (comp) { printf("%s\n", icalcomponent_as_ical_string(comp)); } zonedef_printed = 1; } } if (curr_failed) { total_failed++; } else { total_okay++; } } } if (total_failed || total_okay) { 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; }