static gboolean check_first_instance_cb (ECalComponent *comp, time_t instance_start, time_t instance_end, gpointer user_data) { CheckFirstInstanceData *ifs = user_data; icalcomponent *icalcomp; struct icaltimetype rid; g_return_val_if_fail (ifs != NULL, FALSE); icalcomp = e_cal_component_get_icalcomponent (comp); if (icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY) != NULL) { rid = icalcomponent_get_recurrenceid (icalcomp); } else { struct icaltimetype dtstart; dtstart = icalcomponent_get_dtstart (icalcomp); if (dtstart.zone) { rid = icaltime_from_timet_with_zone (instance_start, dtstart.is_date, dtstart.zone); } else { rid = icaltime_from_timet (instance_start, dtstart.is_date); } } ifs->matches = icaltime_compare (ifs->rid, rid) == 0; return FALSE; }
NS_IMETHODIMP calDateTime::Compare(calIDateTime * aOther, int32_t * aResult) { NS_ENSURE_ARG_POINTER(aOther); NS_ENSURE_ARG_POINTER(aResult); nsresult rv; nsCOMPtr<calIDateTimeLibical> icalother = do_QueryInterface(aOther, &rv); NS_ENSURE_SUCCESS(rv, rv); bool otherIsDate = false; aOther->GetIsDate(&otherIsDate); icaltimetype a, b; ToIcalTime(&a); icalother->ToIcalTime(&b); // If either this or aOther is floating, both objects are treated // as floating for the comparison. if (!a.zone || !b.zone) { a.zone = nullptr; a.is_utc = 0; b.zone = nullptr; b.is_utc = 0; } if (mIsDate || otherIsDate) { *aResult = icaltime_compare_date_only_tz(a, b, cal::getIcalTimezone(mTimezone)); } else { *aResult = icaltime_compare(a, b); } return NS_OK; }
NS_IMETHODIMP calDateTime::Compare(calIDateTime * aOther, int32_t * aResult) { NS_ENSURE_ARG_POINTER(aOther); NS_ENSURE_ARG_POINTER(aResult); bool otherIsDate = false; aOther->GetIsDate(&otherIsDate); icaltimetype a, b; ToIcalTime(&a); aOther->ToIcalTime(&b); // If either this or aOther is floating, both objects are treated // as floating for the comparison. if (!a.zone || !b.zone) { a.zone = NULL; a.is_utc = 0; b.zone = NULL; b.is_utc = 0; } if (mIsDate || otherIsDate) { *aResult = icaltime_compare_date_only_tz(a, b, cal::getIcalTimezone(mTimezone)); } else { *aResult = icaltime_compare(a, b); } return NS_OK; }
void dates_details_time_end_cb (GtkWidget *source, DatesData *d) { ECalComponentDateTime start, end; struct icaltimetype oend; e_cal_component_get_dtend (d->comp, &end); oend = *end.value; dates_details_time_cb (d, &end); /* If end <= start, adjust start */ e_cal_component_get_dtstart (d->comp, &start); if (icaltime_compare (*end.value, *start.value) <= 0) { struct icaldurationtype duration = icaltime_subtract (*end.value, oend); *start.value = icaltime_add (*end.value, duration); e_cal_component_set_dtstart (d->comp, &start); dates_details_update_time_label (d, d->details_start_label, start.value); } e_cal_component_set_dtend (d->comp, &end); dates_details_update_time_label (d, d->details_end_label, end.value); e_cal_component_free_datetime (&end); e_cal_component_free_datetime (&start); }
/** * e_cal_util_event_dates_match: * @icalcomp1: An #icalcomponent. * @icalcomp2: An #icalcomponent. * * Compare the dates of two #icalcomponent's to check if they match. * * Returns: TRUE if the dates of both components match, FALSE otherwise. */ gboolean e_cal_util_event_dates_match (icalcomponent *icalcomp1, icalcomponent *icalcomp2) { struct icaltimetype c1_dtstart, c1_dtend, c2_dtstart, c2_dtend; g_return_val_if_fail (icalcomp1 != NULL, FALSE); g_return_val_if_fail (icalcomp2 != NULL, FALSE); c1_dtstart = icalcomponent_get_dtstart (icalcomp1); c1_dtend = icalcomponent_get_dtend (icalcomp1); c2_dtstart = icalcomponent_get_dtstart (icalcomp2); c2_dtend = icalcomponent_get_dtend (icalcomp2); /* if either value is NULL, they must both be NULL to match */ if (icaltime_is_valid_time (c1_dtstart) || icaltime_is_valid_time (c2_dtstart)) { if (!(icaltime_is_valid_time (c1_dtstart) && icaltime_is_valid_time (c2_dtstart))) return FALSE; } else { if (icaltime_compare (c1_dtstart, c2_dtstart)) return FALSE; } if (icaltime_is_valid_time (c1_dtend) || icaltime_is_valid_time (c2_dtend)) { if (!(icaltime_is_valid_time (c1_dtend) && icaltime_is_valid_time (c2_dtend))) return FALSE; } else { if (icaltime_compare (c1_dtend, c2_dtend)) return FALSE; } /* now match the timezones */ if (!(!c1_dtstart.zone && !c2_dtstart.zone) || (c1_dtstart.zone && c2_dtstart.zone && !strcmp (icaltimezone_get_tzid ((icaltimezone *) c1_dtstart.zone), icaltimezone_get_tzid ((icaltimezone *) c2_dtstart.zone)))) return FALSE; if (!(!c1_dtend.zone && !c2_dtend.zone) || (c1_dtend.zone && c2_dtend.zone && !strcmp (icaltimezone_get_tzid ((icaltimezone *) c1_dtend.zone), icaltimezone_get_tzid ((icaltimezone *) c2_dtend.zone)))) return FALSE; return TRUE; }
VALUE occurrences( VALUE self, VALUE dtstart, VALUE dtend, VALUE rrule ) { char * _rrule; struct icaltimetype start, end; time_t tt; VALUE tv_sec, occurr = rb_ary_new(); /* Get method ID for Time.tv_sec */ ID time_tv_sec = rb_intern( "tv_sec" ); ID to_string = rb_intern( "to_string" ); if( TYPE( rrule ) != T_STRING && rb_respond_to( rrule, to_string ) ) rrule = rb_funcall( rrule, to_string, 0 ); Check_Type(rrule, T_STRING); _rrule = RSTRING(rrule)->ptr; dtstart = to_time( dtstart, "dtstart" ); dtend = to_time( dtend, "dtend" ); /* Apply .tv_sec to our Time objects (if they are Times ...) */ tv_sec = rb_funcall( dtstart, time_tv_sec, 0 ); tt = NUM2INT( tv_sec ); start = icaltime_from_timet( tt, 0 ); tv_sec = rb_funcall( dtend, time_tv_sec, 0 ); tt = NUM2INT( tv_sec ); end = icaltime_from_timet( tt, 0 ); icalerror_clear_errno(); icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL); struct icalrecurrencetype recur = icalrecurrencetype_from_string( _rrule ); if( icalerrno != ICAL_NO_ERROR ) { rb_raise(rb_eArgError, "Malformed RRule"); return Qnil; } icalrecur_iterator* ritr = icalrecur_iterator_new( recur, start ); while(1) { struct icaltimetype next = icalrecur_iterator_next(ritr); if( icaltime_is_null_time(next) || ( icaltime_compare( next, end ) > 0 ) ) { icalrecur_iterator_free(ritr); return occurr; } rb_ary_push( occurr, rb_time_new( icaltime_as_timet( next ), 0 ) ); }; icalrecur_iterator_free(ritr); return occurr; }
static inline gboolean time_matches_rid (struct icaltimetype itt, struct icaltimetype rid, ECalObjModType mod) { gint compare; compare = icaltime_compare (itt, rid); if (compare == 0) return TRUE; else if (compare < 0 && (mod & E_CAL_OBJ_MOD_THIS_AND_PRIOR)) return TRUE; else if (compare > 0 && (mod & E_CAL_OBJ_MOD_THIS_AND_FUTURE)) return TRUE; return FALSE; }
/** * 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; }
static void e_cal_util_remove_instances_ex (icalcomponent *icalcomp, struct icaltimetype rid, ECalObjModType mod, gboolean keep_rid, gboolean can_add_exrule) { icalproperty *prop; struct icaltimetype itt, recur; struct icalrecurrencetype rule; icalrecur_iterator *iter; GSList *remove_props = NULL, *rrules = NULL, *link; g_return_if_fail (icalcomp != NULL); g_return_if_fail (mod != E_CAL_OBJ_MOD_ALL); /* First remove RDATEs and EXDATEs in the indicated range. */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RDATE_PROPERTY)) { struct icaldatetimeperiodtype period; period = icalproperty_get_rdate (prop); if (time_matches_rid (period.time, rid, mod) && (!keep_rid || icaltime_compare (period.time, rid) != 0)) remove_props = g_slist_prepend (remove_props, prop); } for (prop = icalcomponent_get_first_property (icalcomp, ICAL_EXDATE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_EXDATE_PROPERTY)) { itt = icalproperty_get_exdate (prop); if (time_matches_rid (itt, rid, mod) && (!keep_rid || icaltime_compare (itt, rid) != 0)) remove_props = g_slist_prepend (remove_props, prop); } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); remove_props = NULL; /* If we're only removing one instance, just add an EXDATE. */ if (mod == E_CAL_OBJ_MOD_THIS) { prop = icalproperty_new_exdate (rid); icalcomponent_add_property (icalcomp, prop); return; } /* Otherwise, iterate through RRULEs */ /* FIXME: this may generate duplicate EXRULEs */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) { rrules = g_slist_prepend (rrules, prop); } for (link = rrules; link; link = g_slist_next (link)) { prop = link->data; rule = icalproperty_get_rrule (prop); iter = icalrecur_iterator_new (rule, rid); recur = icalrecur_iterator_next (iter); if (mod & E_CAL_OBJ_MOD_THIS_AND_FUTURE) { /* Truncate the rule at rid. */ if (!icaltime_is_null_time (recur)) { /* Use count if it was used */ if (rule.count > 0) { gint occurrences_count = 0; icalrecur_iterator *count_iter; struct icaltimetype count_recur; count_iter = icalrecur_iterator_new (rule, icalcomponent_get_dtstart (icalcomp)); while (count_recur = icalrecur_iterator_next (count_iter), !icaltime_is_null_time (count_recur) && occurrences_count < rule.count) { if (icaltime_compare (count_recur, rid) >= 0) break; occurrences_count++; } icalrecur_iterator_free (count_iter); if (keep_rid && icaltime_compare (count_recur, rid) == 0) occurrences_count++; /* The caller should make sure that the remove will keep at least one instance */ g_warn_if_fail (occurrences_count > 0); rule.count = occurrences_count; } else { if (keep_rid && icaltime_compare (recur, rid) == 0) rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp)); else rule.until = rid; icaltime_adjust (&rule.until, 0, 0, 0, -1); } icalproperty_set_rrule (prop, rule); icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE"); } } else { /* (If recur == rid, skip to the next occurrence) */ if (!keep_rid && icaltime_compare (recur, rid) == 0) recur = icalrecur_iterator_next (iter); /* If there is a recurrence after rid, add * an EXRULE to block instances up to rid. * Otherwise, just remove the RRULE. */ if (!icaltime_is_null_time (recur)) { if (can_add_exrule) { rule.count = 0; /* iCalendar says we should just use rid * here, but Outlook/Exchange handle * UNTIL incorrectly. */ if (keep_rid && icaltime_compare (recur, rid) == 0) { struct icaldurationtype duration = icalcomponent_get_duration (icalcomp); duration.is_neg = !duration.is_neg; rule.until = icaltime_add (rid, duration); } else rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp)); prop = icalproperty_new_exrule (rule); icalcomponent_add_property (icalcomp, prop); } } else { remove_props = g_slist_prepend (remove_props, prop); } } icalrecur_iterator_free (iter); } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); g_slist_free (rrules); }
static gint compare_datetime (const struct icaltimetype *itt1, const struct icaltimetype *itt2) { return icaltime_compare (*itt1, *itt2); }
static ECellDateEditValue * get_dtend (ECalModelCalendar *model, ECalModelComponent *comp_data) { struct icaltimetype tt_end; if (!comp_data->dtend) { icalproperty *prop; icaltimezone *zone = NULL, *model_zone = NULL; gboolean got_zone = FALSE; prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTEND_PROPERTY); if (!prop) return NULL; tt_end = icalproperty_get_dtend (prop); if (icaltime_get_tzid (tt_end) && e_cal_client_get_timezone_sync (comp_data->client, icaltime_get_tzid (tt_end), &zone, NULL, NULL)) got_zone = TRUE; model_zone = e_cal_model_get_timezone (E_CAL_MODEL (model)); if (got_zone) { tt_end = icaltime_from_timet_with_zone (comp_data->instance_end, tt_end.is_date, zone); if (model_zone) icaltimezone_convert_time (&tt_end, zone, model_zone); } else { tt_end = icaltime_from_timet_with_zone ( comp_data->instance_end, tt_end.is_date, model_zone); } if (!icaltime_is_valid_time (tt_end) || icaltime_is_null_time (tt_end)) return NULL; if (tt_end.is_date && icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTSTART_PROPERTY)) { struct icaltimetype tt_start; icaltimezone *start_zone = NULL; gboolean got_start_zone = FALSE; tt_start = icalproperty_get_dtstart (prop); if (icaltime_get_tzid (tt_start) && e_cal_client_get_timezone_sync (comp_data->client, icaltime_get_tzid (tt_start), &start_zone, NULL, NULL)) got_start_zone = TRUE; if (got_start_zone) { tt_start = icaltime_from_timet_with_zone (comp_data->instance_start, tt_start.is_date, start_zone); if (model_zone) icaltimezone_convert_time (&tt_start, start_zone, model_zone); } else { tt_start = icaltime_from_timet_with_zone ( comp_data->instance_start, tt_start.is_date, model_zone); } icaltime_adjust (&tt_start, 1, 0, 0, 0); /* Decrease by a day only if the DTSTART will still be before, or the same as, DTEND */ if (icaltime_compare (tt_start, tt_end) <= 0) icaltime_adjust (&tt_end, -1, 0, 0, 0); } comp_data->dtend = g_new0 (ECellDateEditValue, 1); comp_data->dtend->tt = tt_end; if (got_zone) comp_data->dtend->zone = zone; else comp_data->dtend->zone = NULL; } return e_cal_model_copy_cell_date_value (comp_data->dtend); }
/* Stores information about actually shown component and * returns whether component in the preview changed */ static gboolean update_comp_info (ECalComponentPreview *preview, ECalClient *client, ECalComponent *comp, icaltimezone *zone, gboolean use_24_hour_format) { ECalComponentPreviewPrivate *priv; gboolean changed; g_return_val_if_fail (preview != NULL, TRUE); g_return_val_if_fail (E_IS_CAL_COMPONENT_PREVIEW (preview), TRUE); priv = preview->priv; if (!E_IS_CAL_COMPONENT (comp) || !E_IS_CAL_CLIENT (client)) { changed = !priv->cal_uid; clear_comp_info (preview); } else { ESource *source; const gchar *uid; gchar *cal_uid; gchar *comp_uid; struct icaltimetype comp_last_modified, *itm = NULL; gint *sequence = NULL; gint comp_sequence; source = e_client_get_source (E_CLIENT (client)); cal_uid = g_strdup (e_source_get_uid (source)); e_cal_component_get_uid (comp, &uid); comp_uid = g_strdup (uid); e_cal_component_get_last_modified (comp, &itm); if (itm) { comp_last_modified = *itm; e_cal_component_free_icaltimetype (itm); } else comp_last_modified = icaltime_null_time (); e_cal_component_get_sequence (comp, &sequence); if (sequence) { comp_sequence = *sequence; e_cal_component_free_sequence (sequence); } else comp_sequence = 0; changed = !priv->cal_uid || !priv->comp_uid || !cal_uid || !comp_uid || !g_str_equal (priv->cal_uid, cal_uid) || !g_str_equal (priv->comp_uid, comp_uid) || priv->comp_sequence != comp_sequence || icaltime_compare (priv->comp_last_modified, comp_last_modified) != 0; clear_comp_info (preview); priv->cal_uid = cal_uid; priv->comp_uid = comp_uid; priv->comp_sequence = comp_sequence; priv->comp_last_modified = comp_last_modified; priv->comp = g_object_ref (comp); priv->client = g_object_ref (client); priv->timezone = icaltimezone_copy (zone); priv->use_24_hour_format = use_24_hour_format; } return changed; }
void parse_iCal(icalcomponent* comp) { icalcomponent * c; icalproperty * rrule; icalproperty * exdate; icalrecur_iterator * data; struct icaldurationtype offset; struct icaltimetype time_start; struct icaltimetype time_end; struct icaltimetype time_next; struct icaltimetype exdatetime; struct icaltimetype now; struct icalrecurrencetype recur; int i = 0; double duration; // Get offset: time_t t = time(NULL); struct tm lt = {0}; localtime_r(&t, <); if (debug_flag) { printf("Offset to GMT is %lds.\n", lt.tm_gmtoff); } offset.days = 0; offset.weeks = 0; offset.hours = 0; offset.minutes = 0; offset.seconds = 0; offset.hours = lt.tm_gmtoff / 3600; if (lt.tm_gmtoff < 0) { offset.is_neg = 1; } else { offset.is_neg = 0; } // Get time now: now = icaltime_today(); // Read each event: for (c = icalcomponent_get_first_component(comp,ICAL_VEVENT_COMPONENT) ; c != 0 ; c = icalcomponent_get_next_component(comp,ICAL_VEVENT_COMPONENT) ) { // Get details about the event: const char * summary = icalcomponent_get_summary(c); const char * description = icalcomponent_get_description(c); // Help: if (debug_flag) { if (summary != NULL) { printf("summary: %s\n", summary); } if (description != NULL) { printf("description: %s\n", description); } } // Ranging time: time_start = icalcomponent_get_dtstart (c); time_end = icalcomponent_get_dtend (c); duration = difftime(icaltime_as_timet(time_end), icaltime_as_timet(time_start)); // Rules: rrule = icalcomponent_get_first_property(c,ICAL_RRULE_PROPERTY); recur = icalproperty_get_rrule(rrule); data = icalrecur_iterator_new (recur, time_start); // Find next event: while (1) { time_next = icalrecur_iterator_next (data); if (icaltime_is_null_time(time_next) == 1) break; if (icaltime_compare(time_next, now) >= 0) break; } // Help: if (debug_flag) { dump_icaltimetype("time start", time_start); dump_icaltimetype("time end", time_end); dump_icaltimetype("until", recur.until); dump_icaltimetype("time next", time_next); } // One shot event: if ( icaltime_is_null_time(time_next) == 1 && icaltime_compare(time_start, now) < 0 ) { if (debug_flag) printf ("event (one shot) is in the past\n"); continue; } // Old event: discard recurent events finished before today... if ( icaltime_is_null_time(recur.until) == 0 && icaltime_compare(recur.until, now) < 0 ) { if (debug_flag) printf ("event is recurent in the past ...\n"); continue; } // Some help: if (debug_flag > 2) { dump_icalrecurrencetype(recur); } // Set time and hours: struct icaltimetype local_time_start = icaltime_add(time_start, offset); printf ("%d %d ", local_time_start.minute, local_time_start.hour); // Set option depending of recurence: switch (recur.freq) { // Weekly: OK but need to remove days not needed... ? case ICAL_WEEKLY_RECURRENCE: printf ("%s", "* * "); for (i = 0; recur.by_day[i] != 32639; i++) { printf ("%02d", icalrecurrencetype_day_day_of_week(recur.by_day[i]) -1); if (recur.by_day[i+1] != 32639) { printf ("%s", ","); } } printf ("%s", " "); break; // Happening each month: case ICAL_MONTHLY_RECURRENCE: // The Xth of the month: if (recur.by_month_day[0] != 32639) { printf ("%02d * * ", recur.by_month_day[0]); } // Day of the week: else { printf ("%d %d * ", time_next.day, time_next.month); } break; // Event happening each year ... OK??? // OK: one shoot. case ICAL_YEARLY_RECURRENCE: case ICAL_NO_RECURRENCE: default: printf ("%02d %02d * ", local_time_start.day, local_time_start.month ); } // How many valid exclude dates: exdate = icalcomponent_get_first_property(c, ICAL_EXDATE_PROPERTY); unsigned int num_ex = 0; if (exdate != NULL) { for (; exdate != NULL; exdate = icalcomponent_get_next_property(c, ICAL_EXDATE_PROPERTY) ) { exdatetime = icalvalue_get_datetime(icalproperty_get_value(exdate)); if (icaltime_compare(exdatetime, now) >= 0) { num_ex++; } } } if (num_ex > 0) { exdate = icalcomponent_get_first_property(c, ICAL_EXDATE_PROPERTY); for (; exdate != NULL; exdate = icalcomponent_get_next_property(c, ICAL_EXDATE_PROPERTY) ) { exdatetime = icalvalue_get_datetime(icalproperty_get_value(exdate)); if (icaltime_compare(exdatetime, now) >= 0) { struct icaltimetype local_exdatetime = icaltime_add(exdatetime, offset); printf ("%s", "[ \"$(date \"+\\\%Y\\\%m\\\%d\")\" = \""); printf ("%04d%02d%02d", local_exdatetime.year, local_exdatetime.month, local_exdatetime.day); printf ("%s", "\" ] || "); } } } // And the action: printf ("%s %.0f\n", summary, duration ); icalrecur_iterator_free (data); } }
/** Gets the TZNAMEs used for the last STANDARD & DAYLIGHT components in a VTIMEZONE. If both STANDARD and DAYLIGHT components use the same TZNAME, it returns that. If they use different TZNAMEs, it formats them like "EST/EDT". The returned string should be freed by the caller. */ static char* icaltimezone_get_tznames_from_vtimezone (icalcomponent *component) { icalcomponent *comp; icalcomponent_kind type; icalproperty *prop; struct icaltimetype dtstart; struct icaldatetimeperiodtype rdate; const char *current_tzname; const char *standard_tzname = NULL, *daylight_tzname = NULL; struct icaltimetype standard_max_date, daylight_max_date; struct icaltimetype current_max_date; standard_max_date = icaltime_null_time(); daylight_max_date = icaltime_null_time(); /* Step through the STANDARD & DAYLIGHT subcomponents. */ comp = icalcomponent_get_first_component (component, ICAL_ANY_COMPONENT); while (comp) { type = icalcomponent_isa (comp); if (type == ICAL_XSTANDARD_COMPONENT || type == ICAL_XDAYLIGHT_COMPONENT) { current_max_date = icaltime_null_time (); current_tzname = NULL; /* Step through the properties. We want to find the TZNAME, and the largest DTSTART or RDATE. */ prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY); while (prop) { switch (icalproperty_isa (prop)) { case ICAL_TZNAME_PROPERTY: current_tzname = icalproperty_get_tzname (prop); break; case ICAL_DTSTART_PROPERTY: dtstart = icalproperty_get_dtstart (prop); if (icaltime_compare (dtstart, current_max_date) > 0) current_max_date = dtstart; break; case ICAL_RDATE_PROPERTY: rdate = icalproperty_get_rdate (prop); if (icaltime_compare (rdate.time, current_max_date) > 0) current_max_date = rdate.time; break; default: break; } prop = icalcomponent_get_next_property (comp, ICAL_ANY_PROPERTY); } if (current_tzname) { if (type == ICAL_XSTANDARD_COMPONENT) { if (!standard_tzname || icaltime_compare (current_max_date, standard_max_date) > 0) { standard_max_date = current_max_date; standard_tzname = current_tzname; } } else { if (!daylight_tzname || icaltime_compare (current_max_date, daylight_max_date) > 0) { daylight_max_date = current_max_date; daylight_tzname = current_tzname; } } } } comp = icalcomponent_get_next_component (component, ICAL_ANY_COMPONENT); } /* Outlook (2000) places "Standard Time" and "Daylight Time" in the TZNAME strings, which is totally useless. So we return NULL in that case. */ if (standard_tzname && !strcmp (standard_tzname, "Standard Time")) return NULL; /* If both standard and daylight TZNAMEs were found, if they are the same we return just one, else we format them like "EST/EDT". */ if (standard_tzname && daylight_tzname) { unsigned int standard_len, daylight_len; char *tznames; if (!strcmp (standard_tzname, daylight_tzname)) return strdup (standard_tzname); standard_len = strlen (standard_tzname); daylight_len = strlen (daylight_tzname); tznames = malloc (standard_len + daylight_len + 2); strcpy (tznames, standard_tzname); tznames[standard_len] = '/'; strcpy (tznames + standard_len + 1, daylight_tzname); return tznames; } else { const char *tznames; /* If either of the TZNAMEs was found just return that, else NULL. */ tznames = standard_tzname ? standard_tzname : daylight_tzname; return tznames ? strdup (tznames) : NULL; } }
static gboolean put_component_to_store (ECalBackendHttp *cb, ECalComponent *comp) { time_t time_start, time_end; ECalBackendHttpPrivate *priv; ECalComponent *cache_comp; const gchar *uid; gchar *rid; priv = cb->priv; e_cal_component_get_uid (comp, &uid); rid = e_cal_component_get_recurid_as_string (comp); cache_comp = e_cal_backend_store_get_component (priv->store, uid, rid); g_free (rid); if (cache_comp) { gboolean changed = TRUE; struct icaltimetype stamp1, stamp2; stamp1 = icaltime_null_time (); stamp2 = icaltime_null_time (); e_cal_component_get_dtstamp (comp, &stamp1); e_cal_component_get_dtstamp (cache_comp, &stamp2); changed = (icaltime_is_null_time (stamp1) && !icaltime_is_null_time (stamp2)) || (!icaltime_is_null_time (stamp1) && icaltime_is_null_time (stamp2)) || (icaltime_compare (stamp1, stamp2) != 0); if (!changed) { struct icaltimetype *last_modified1 = NULL, *last_modified2 = NULL; e_cal_component_get_last_modified (comp, &last_modified1); e_cal_component_get_last_modified (cache_comp, &last_modified2); changed = (last_modified1 != NULL && last_modified2 == NULL) || (last_modified1 == NULL && last_modified2 != NULL) || (last_modified1 != NULL && last_modified2 != NULL && icaltime_compare (*last_modified1, *last_modified2) != 0); if (last_modified1) e_cal_component_free_icaltimetype (last_modified1); if (last_modified2) e_cal_component_free_icaltimetype (last_modified2); if (!changed) { gint *sequence1 = NULL, *sequence2 = NULL; e_cal_component_get_sequence (comp, &sequence1); e_cal_component_get_sequence (cache_comp, &sequence2); changed = (sequence1 != NULL && sequence2 == NULL) || (sequence1 == NULL && sequence2 != NULL) || (sequence1 != NULL && sequence2 != NULL && *sequence1 != *sequence2); if (sequence1) e_cal_component_free_sequence (sequence1); if (sequence2) e_cal_component_free_sequence (sequence2); } } g_object_unref (cache_comp); if (!changed) return FALSE; } e_cal_util_get_component_occur_times ( comp, &time_start, &time_end, resolve_tzid, cb, icaltimezone_get_utc_timezone (), e_cal_backend_get_kind (E_CAL_BACKEND (cb))); e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end); return TRUE; }