/** * e_cal_util_is_first_instance: * @comp: an #ECalComponent instance * @rid: a recurrence ID * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneFn to call * @tz_cb_data: (closure): User data to be passed to the @tz_cb callback * * Returns whether the given @rid is the first instance of * the recurrence defined in the @comp. * * Return: Whether the @rid identifies the first instance of @comp. * * Since: 3.16 **/ gboolean e_cal_util_is_first_instance (ECalComponent *comp, struct icaltimetype rid, ECalRecurResolveTimezoneFn tz_cb, gpointer tz_cb_data) { CheckFirstInstanceData ifs; icalcomponent *icalcomp; time_t start, end; g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE); g_return_val_if_fail (!icaltime_is_null_time (rid), FALSE); ifs.rid = rid; ifs.matches = FALSE; icalcomp = e_cal_component_get_icalcomponent (comp); start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)) - 24 * 60 * 60; end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)) + 24 * 60 * 60; e_cal_recur_generate_instances (comp, start, end, check_first_instance_cb, &ifs, tz_cb, tz_cb_data, icaltimezone_get_utc_timezone ()); return ifs.matches; }
struct icaldurationtype icaltime_subtract(struct icaltimetype t1, struct icaltimetype t2) { time_t t1t = icaltime_as_timet(t1); time_t t2t = icaltime_as_timet(t2); return icaldurationtype_from_int((int)(t1t - t2t)); }
/** * @brief * Get the occurrence as defined by the given recurrence rule, * index, and start time. This function assumes that the * time dtsart passed in is the one to start the occurrence from. * * @par NOTE: This function should be made reentrant such that * it can be looped over without having to loop over every occurrence * over and over again. * * @param[in] rrule - The recurrence rule as defined by the user * @param[in] dtstart - The start time from which to start * @param[in] tz - The timezone associated to the recurrence rule * @param[in] idx - The index of the occurrence to start counting from * * @return time_t * @retval The date of the next occurrence or -1 if the date exceeds libical's * Unix time in 2038 * */ time_t get_occurrence(char *rrule, time_t dtstart, char *tz, int idx) { #ifdef LIBICAL struct icalrecurrencetype rt; struct icaltimetype start; icaltimezone *localzone; struct icaltimetype next; struct icalrecur_iterator_impl *itr; int i; time_t next_occr = dtstart; if (rrule == NULL) return dtstart; if (tz == NULL) return -1; icalerror_clear_errno(); icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); #ifdef LIBICAL_API2 icalerror_set_errors_are_fatal(0); #else icalerror_errors_are_fatal = 0; #endif localzone = icaltimezone_get_builtin_timezone(tz); if (localzone == NULL) return -1; rt = icalrecurrencetype_from_string(rrule); start = icaltime_from_timet_with_zone(dtstart, 0, NULL); icaltimezone_convert_time(&start, icaltimezone_get_utc_timezone(), localzone); next = start; itr = (struct icalrecur_iterator_impl*) icalrecur_iterator_new(rt, start); /* Skip as many occurrences as specified by idx */ for (i = 0; i < idx && !icaltime_is_null_time(next); i++) next = icalrecur_iterator_next(itr); if (!icaltime_is_null_time(next)) { icaltimezone_convert_time(&next, localzone, icaltimezone_get_utc_timezone()); next_occr = icaltime_as_timet(next); } else next_occr = -1; /* If reached end of possible date-time return -1 */ icalrecur_iterator_free(itr); return next_occr; #else return dtstart; #endif }
/** * 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; }
static void adjust_dtstart_day_to_rrule (icalcomponent *comp, struct icalrecurrencetype rule) { time_t now, year_start; struct icaltimetype start, comp_start, iter_start, itime; icalrecur_iterator *iter; now = time (NULL); itime = icaltime_from_timet (now, 0); itime.month = itime.day = 1; itime.hour = itime.minute = itime.second = 0; year_start = icaltime_as_timet(itime); comp_start = icalcomponent_get_dtstart (comp); start = icaltime_from_timet (year_start, 0); iter = icalrecur_iterator_new (rule, start); iter_start = icalrecur_iterator_next (iter); icalrecur_iterator_free (iter); if (iter_start.day != comp_start.day) { comp_start.day = iter_start.day; icalcomponent_set_dtstart (comp, comp_start); } }
static gpointer alter_cal_client (gpointer user_data) { ECalClient *cal_client = user_data; GError *error = NULL; icalcomponent *icalcomp; struct icaltimetype now; gchar *uid = NULL; g_return_val_if_fail (cal_client != NULL, NULL); now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()); icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT); icalcomponent_set_summary (icalcomp, "Initial event summary"); icalcomponent_set_dtstart (icalcomp, now); icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0)); if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) g_error ("create object sync: %s", error->message); icalcomponent_set_uid (icalcomp, uid); icalcomponent_set_summary (icalcomp, "Modified event summary"); if (!e_cal_client_modify_object_sync (cal_client, icalcomp, CALOBJ_MOD_ALL, NULL, &error)) g_error ("modify object sync: %s", error->message); if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, CALOBJ_MOD_ALL, NULL, &error)) g_error ("remove object sync: %s", error->message); g_free (uid); icalcomponent_free (icalcomp); return FALSE; }
/** * @brief * Returns the number of occurrences defined by a recurrence rule. * * @par The total number of occurrences is currently limited to a hardcoded * 3 years limit from the current date. * * @par NOTE: Determine whether 3 years limit is the right way to go about setting * a limit on the total number of occurrences. * * @param[in] rrule - The recurrence rule as defined by the user * @param[in] tt - The start time of the first occurrence * @param[in] tz - The timezone associated to the recurrence rule * * @return int * @retval the total number of occurrences * */ int get_num_occurrences(char *rrule, time_t dtstart, char *tz) { #ifdef LIBICAL struct icalrecurrencetype rt; struct icaltimetype start; icaltimezone *localzone; struct icaltimetype next; struct icalrecur_iterator_impl *itr; time_t now; time_t date_limit; int num_resv = 0; /* if any of the argument is NULL, we are dealing with * advance reservation, so return 1 occurrence */ if (rrule == NULL || tz == NULL) return 1; icalerror_clear_errno(); icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); icalerror_errors_are_fatal = 0; localzone = icaltimezone_get_builtin_timezone(tz); if (localzone == NULL) return 0; now = time((time_t *)0); date_limit = now + DATE_LIMIT; rt = icalrecurrencetype_from_string(rrule); start = icaltime_from_timet(dtstart, 0); icaltimezone_convert_time(&start, icaltimezone_get_utc_timezone(), localzone); itr = (struct icalrecur_iterator_impl*) icalrecur_iterator_new(rt, start); next = icalrecur_iterator_next(itr); /* Compute the total number of occurrences. * Breaks out if the total number of allowed occurrences is exceeded */ while (!icaltime_is_null_time(next) && (icaltime_as_timet(next) < date_limit)) { num_resv++; next = icalrecur_iterator_next(itr); } icalrecur_iterator_free(itr); return num_resv; #else if (rrule == NULL) return 1; return 0; #endif }
struct icalperiodtype icalspanlist_next_free_time(icalspanlist *sl, struct icaltimetype t) { pvl_elem itr; struct icalperiodtype period; struct icaltime_span *s; time_t rangett = icaltime_as_timet(t); period.start = icaltime_null_time(); period.end = icaltime_null_time(); itr = pvl_head(sl->spans); s = (struct icaltime_span *)pvl_data(itr); if (s == 0) { /* No elements in span */ return period; } /* Is the reference time before the first span? If so, assume that the reference time is free */ if (rangett < s->start) { /* End of period is start of first span if span is busy, end of the span if it is free */ period.start = t; if (s->is_busy == 1) { period.end = icaltime_from_timet(s->start, 0); } else { period.end = icaltime_from_timet(s->end, 0); } return period; } /* Otherwise, find the first free span that contains the reference time. */ for (itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) { s = (struct icaltime_span *)pvl_data(itr); if (s->is_busy == 0 && s->start >= rangett && (rangett < s->end || s->end == s->start)) { if (rangett < s->start) { period.start = icaltime_from_timet(s->start, 0); } else { period.start = icaltime_from_timet(rangett, 0); } period.end = icaltime_from_timet(s->end, 0); return period; } } period.start = icaltime_null_time(); period.end = icaltime_null_time(); return period; }
gint main (gint argc, gchar **argv) { ECalClient *cal_client; GError *error = NULL; icalcomponent *icalcomp; struct icaltimetype now; gchar *uid = NULL; main_initialize (); cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL); g_return_val_if_fail (cal_client != NULL, FALSE); if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) { report_error ("client open sync", &error); g_object_unref (cal_client); return 1; } now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()); icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT); icalcomponent_set_summary (icalcomp, "Test event summary"); icalcomponent_set_dtstart (icalcomp, now); icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0)); if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) { report_error ("create object sync", &error); icalcomponent_free (icalcomp); g_object_unref (cal_client); return 1; } icalcomponent_free (icalcomp); g_free (uid); /* synchronously without main-loop */ if (!test_sync (cal_client)) { g_object_unref (cal_client); return 1; } start_in_thread_with_main_loop (test_sync_in_thread, cal_client); if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) { report_error ("client remove sync", &error); g_object_unref (cal_client); return 1; } g_object_unref (cal_client); if (get_main_loop_stop_result () == 0) g_print ("Test finished successfully.\n"); return get_main_loop_stop_result (); }
char *icaltime_as_ctime(struct icaltimetype t) { time_t tt; tt = icaltime_as_timet(t); snprintf(ictt_str, sizeof(ictt_str), "%s", ctime(&tt)); return ictt_str; }
void tmplput_ICalTime_Time(StrBuf *Target, WCTemplputParams *TP) { long len; char buf[256]; struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME); time_t tt; tt = icaltime_as_timet(*t); len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL); StrBufAppendBufPlain(Target, buf, len, 0); }
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; }
int main() { const char *rrule = "FREQ=DAILY;UNTIL=20080820T143500Z"; icaltimetype dtstart = icaltime_from_timet(time(0) - (2*24*3600), 0); time_t viewend; struct icalrecurrencetype recur; time_t utc_tim; time_t dtst_utc; bool loopexit = false; recur = icalrecurrencetype_from_string(rrule); printf ("date is given by %d:%d:%d\n\n", dtstart.year, dtstart.month, dtstart.day); dtst_utc = icaltime_as_timet(dtstart); icalrecur_iterator *ritr; ritr = icalrecur_iterator_new(recur, dtstart); struct icaltimetype next; next = icalrecur_iterator_next(ritr); while ((!icaltime_is_null_time(next)) && (!loopexit)) { utc_tim = icaltime_as_timet(next); if (time (0) < utc_tim) { printf ("Recurrent time : %s\n", ctime(&utc_tim)); loopexit = true; } next = icalrecur_iterator_next(ritr); } icalrecur_iterator_free(ritr); }
void tmplput_CtxICalPropertyDate(StrBuf *Target, WCTemplputParams *TP) { icalproperty *p = (icalproperty *) CTX(CTX_ICALPROPERTY); struct icaltimetype t; time_t tt; char buf[256]; long len; t = icalproperty_get_dtend(p); tt = icaltime_as_timet(t); len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL); StrBufAppendBufPlain(Target, buf, len, 0); }
static icalcomponent * create_object (void) { icalcomponent *icalcomp; struct icaltimetype now; now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()); icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT); icalcomponent_set_summary (icalcomp, "To-be-sent event summary"); icalcomponent_set_dtstart (icalcomp, now); icalcomponent_set_dtend (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 * 60, 0, NULL)); return icalcomp; }
glong evo_cal_component_get_modified(ECalComponent *obj) { struct icaltimetype *tt; tt = g_malloc0 (sizeof (struct icaltimetype)); e_cal_component_get_last_modified(obj, &tt); if (tt) return icaltime_as_timet(*tt); else return 0; }
void tmplput_ICalDate(StrBuf *Target, WCTemplputParams *TP) { icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL); icalproperty *p; icalproperty_kind Kind; struct icaltimetype t; time_t tt; char buf[256]; Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 0, ICAL_ANY_PROPERTY); p = icalcomponent_get_first_property(cal, Kind); if (p != NULL) { long len; t = icalproperty_get_dtend(p); tt = icaltime_as_timet(t); len = webcit_fmt_date(buf, 256, tt, DATEFMT_FULL); StrBufAppendBufPlain(Target, buf, len, 0); } }
static void setup_cal (ECalClient *cal_client) { GError *error = NULL; icalcomponent *icalcomp; struct icaltimetype now; gchar *uid = NULL; now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()); icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT); icalcomponent_set_summary (icalcomp, "Test event summary"); icalcomponent_set_dtstart (icalcomp, now); icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0)); if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) g_error ("create object sync: %s", error->message); icalcomponent_free (icalcomp); g_free (uid); }
static void get_revision_compare_cycle (ECalClient *client) { icalcomponent *icalcomp; struct icaltimetype now; gchar *revision_before = NULL, *revision_after = NULL, *uid = NULL; GError *error = NULL; /* Build up new component */ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()); icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT); icalcomponent_set_summary (icalcomp, "Test event summary"); icalcomponent_set_dtstart (icalcomp, now); icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0)); if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION, &revision_before, NULL, &error)) g_error ("Error getting book revision: %s", error->message); if (!e_cal_client_create_object_sync (client, icalcomp, &uid, NULL, &error)) g_error ("Error creating object: %s", error->message); if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION, &revision_after, NULL, &error)) g_error ("Error getting book revision: %s", error->message); g_assert (revision_before); g_assert (revision_after); g_assert (strcmp (revision_before, revision_after) != 0); g_message ("Passed cycle, revision before '%s' revision after '%s'", revision_before, revision_after); g_free (revision_before); g_free (revision_after); g_free (uid); icalcomponent_free (icalcomp); }
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; }
struct icaltimetype icaltime_as_local(struct icaltimetype tt) { time_t t; struct tm *tm; struct icaltimetype h; struct tm buft; t = icaltime_as_timet(tt); /* Convert to epoch */ #ifdef G_OS_WIN32 if (t < 0) t = 1; #endif tm = localtime_r(&t, &buft); /* Convert to local time */ h.year = tm->tm_year + 1900; /* Make an icaltimetype */ h.month = tm->tm_mon + 1; h.day = tm->tm_mday; h.hour = tt.is_date ? 0 : tm->tm_hour; h.minute = tt.is_date ? 0 : tm->tm_min; h.second = tt.is_date ? 0 : tm->tm_sec; h.is_utc = 0; h.is_date = tt.is_date; return h; }
static gchar * create_object (ECalClient *cal_client) { icalcomponent *icalcomp; struct icaltimetype now; gchar *uid = NULL; GError *error = NULL; g_return_val_if_fail (cal_client != NULL, NULL); now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()); icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT); icalcomponent_set_summary (icalcomp, "To-be-removed event summary"); icalcomponent_set_dtstart (icalcomp, now); icalcomponent_set_dtend (icalcomp, icaltime_from_timet_with_zone (icaltime_as_timet (now) + 60 * 60 * 60, 0, NULL)); if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) g_error ("create object sync: %s", error->message); icalcomponent_free (icalcomp); return uid; }
/** * e_cal_util_get_component_occur_times: * @comp: an #ECalComponent * @start: (out): Location to store the start time * @end: (out): Location to store the end time * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneFn to call * @tz_cb_data: (closure): User data to be passed to the @tz_cb callback * @default_timezone: The default timezone * @kind: the type of component, indicated with an icalcomponent_kind * * Find out when the component starts and stops, being careful about * recurrences. * * Since: 2.32 **/ void e_cal_util_get_component_occur_times (ECalComponent *comp, time_t *start, time_t *end, ECalRecurResolveTimezoneFn tz_cb, gpointer tz_cb_data, const icaltimezone *default_timezone, icalcomponent_kind kind) { struct icalrecurrencetype ir; ECalComponentDateTime dt_start, dt_end; g_return_if_fail (comp != NULL); g_return_if_fail (start != NULL); g_return_if_fail (end != NULL); e_cal_recur_ensure_end_dates (comp, FALSE, tz_cb, tz_cb_data); /* Get dtstart of the component and convert it to UTC */ e_cal_component_get_dtstart (comp, &dt_start); if ((*start = componenttime_to_utc_timet (&dt_start, tz_cb, tz_cb_data, default_timezone)) == -1) *start = _TIME_MIN; e_cal_component_free_datetime (&dt_start); /* find out end date of component */ *end = _TIME_MAX; if (kind == ICAL_VTODO_COMPONENT) { /* max from COMPLETED and DUE properties */ struct icaltimetype *tt = NULL; time_t completed_time = -1, due_time = -1, max_time; ECalComponentDateTime dt_due; e_cal_component_get_completed (comp, &tt); if (tt) { /* COMPLETED must be in UTC. */ completed_time = icaltime_as_timet_with_zone ( *tt, icaltimezone_get_utc_timezone ()); e_cal_component_free_icaltimetype (tt); } e_cal_component_get_due (comp, &dt_due); if (dt_due.value != NULL) due_time = componenttime_to_utc_timet ( &dt_due, tz_cb, tz_cb_data, default_timezone); e_cal_component_free_datetime (&dt_due); max_time = MAX (completed_time, due_time); if (max_time != -1) *end = max_time; } else { /* ALARMS, EVENTS: DTEND and reccurences */ if (e_cal_component_has_recurrences (comp)) { GSList *rrules = NULL; GSList *exrules = NULL; GSList *elem; GSList *rdates = NULL; /* Do the RRULEs, EXRULEs and RDATEs*/ e_cal_component_get_rrule_property_list (comp, &rrules); e_cal_component_get_exrule_property_list (comp, &exrules); e_cal_component_get_rdate_list (comp, &rdates); for (elem = rrules; elem; elem = elem->next) { time_t rule_end; icaltimezone *utc_zone; icalproperty *prop = elem->data; ir = icalproperty_get_rrule (prop); utc_zone = icaltimezone_get_utc_timezone (); rule_end = e_cal_recur_obtain_enddate ( &ir, prop, utc_zone, TRUE); if (rule_end == -1) /* repeats forever */ *end = _TIME_MAX; else if (rule_end > *end) /* new maximum */ *end = rule_end; } /* Do the EXRULEs. */ for (elem = exrules; elem; elem = elem->next) { icalproperty *prop = elem->data; time_t rule_end; icaltimezone *utc_zone; ir = icalproperty_get_exrule (prop); utc_zone = icaltimezone_get_utc_timezone (); rule_end = e_cal_recur_obtain_enddate ( &ir, prop, utc_zone, TRUE); if (rule_end == -1) /* repeats forever */ *end = _TIME_MAX; else if (rule_end > *end) *end = rule_end; } /* Do the RDATEs */ for (elem = rdates; elem; elem = elem->next) { ECalComponentPeriod *p = elem->data; time_t rdate_end = _TIME_MAX; /* FIXME: We currently assume RDATEs are in the same timezone * as DTSTART. We should get the RDATE timezone and convert * to the DTSTART timezone first. */ /* Check if the end date or duration is set, libical seems to set * second to -1 to denote an unset time */ if (p->type != E_CAL_COMPONENT_PERIOD_DATETIME || p->u.end.second != -1) rdate_end = icaltime_as_timet (icaltime_add (p->start, p->u.duration)); else rdate_end = icaltime_as_timet (p->u.end); if (rdate_end == -1) /* repeats forever */ *end = _TIME_MAX; else if (rdate_end > *end) *end = rdate_end; } e_cal_component_free_period_list (rdates); } /* Get dtend of the component and convert it to UTC */ e_cal_component_get_dtend (comp, &dt_end); if (dt_end.value) { time_t dtend_time; dtend_time = componenttime_to_utc_timet ( &dt_end, tz_cb, tz_cb_data, default_timezone); if (dtend_time == -1 || (dtend_time > *end)) *end = dtend_time; } e_cal_component_free_datetime (&dt_end); } }
/** * 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; }
int main(int argc, char *argv[]) { icalset *cin; struct icaltimetype next; icalcomponent *itr; icalproperty *desc, *dtstart, *rrule; struct icalrecurrencetype recur; icalrecur_iterator* ritr; time_t tt; char* file; icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); #ifndef WIN32 signal(SIGALRM,sig_alrm); #endif if (argc <= 1) { file = "../../test-data/recur.txt"; } else if (argc == 2) { file = argv[1]; } else { fprintf(stderr,"usage: recur [input file]\n"); exit(1); } #ifndef WIN32 alarm(300); /* to get file lock */ #endif cin = icalfileset_new(file); #ifndef WIN32 alarm(0); #endif if(cin == 0) { fprintf(stderr,"recur: can't open file %s\n",file); exit(1); } for (itr = icalfileset_get_first_component(cin); itr != 0; itr = icalfileset_get_next_component(cin)) { struct icaltimetype start = icaltime_from_timet(1,0); struct icaltimetype end = icaltime_today(); desc = icalcomponent_get_first_property(itr,ICAL_DESCRIPTION_PROPERTY); dtstart = icalcomponent_get_first_property(itr,ICAL_DTSTART_PROPERTY); rrule = icalcomponent_get_first_property(itr,ICAL_RRULE_PROPERTY); if (desc == 0 || dtstart == 0 || rrule == 0) { printf("\n******** Error in input component ********\n"); printf("The following component is malformed:\n %s\n", icalcomponent_as_ical_string(itr)); continue; } printf("\n\n#### %s\n",icalproperty_get_description(desc)); printf("#### %s\n",icalvalue_as_ical_string(icalproperty_get_value(rrule))); recur = icalproperty_get_rrule(rrule); start = icalproperty_get_dtstart(dtstart); ritr = icalrecur_iterator_new(recur,start); tt = icaltime_as_timet(start); printf("#### %s\n",ctime(&tt )); icalrecur_iterator_free(ritr); for(ritr = icalrecur_iterator_new(recur,start), next = icalrecur_iterator_next(ritr); !icaltime_is_null_time(next); next = icalrecur_iterator_next(ritr)) { tt = icaltime_as_timet(next); printf(" %s",ctime(&tt )); } icalrecur_iterator_free(ritr); icalcomponent_foreach_recurrence(itr, start, end, recur_callback, NULL); } icalset_free(cin); icaltimezone_free_builtin_timezones(); icalmemory_free_ring(); free_zone_directory(); return 0; }
static ESExpResult * func_due_in_time_range (ESExp *esexp, gint argc, ESExpResult **argv, gpointer data) { SearchContext *ctx = data; time_t start, end; ESExpResult *result; icaltimezone *zone; ECalComponentDateTime dt; time_t due_t; gboolean retval; /* Check argument types */ if (argc != 2) { e_sexp_fatal_error ( esexp, _("\"%s\" expects two arguments"), "due-in-time-range"); return NULL; } if (argv[0]->type != ESEXP_RES_TIME) { e_sexp_fatal_error ( esexp, _("\"%s\" expects the first " "argument to be a time_t"), "due-in-time-range"); return NULL; } start = argv[0]->value.time; if (argv[1]->type != ESEXP_RES_TIME) { e_sexp_fatal_error ( esexp, _("\"%s\" expects the second " "argument to be a time_t"), "due-in-time-range"); return NULL; } end = argv[1]->value.time; e_cal_component_get_due (ctx->comp, &dt); if (dt.value != NULL) { zone = resolve_tzid (dt.tzid, ctx); if (zone) due_t = icaltime_as_timet_with_zone (*dt.value,zone); else due_t = icaltime_as_timet (*dt.value); } if (dt.value != NULL && (due_t <= end && due_t >= start)) retval = TRUE; else retval = FALSE; result = e_sexp_result_new (esexp, ESEXP_RES_BOOL); result->value.boolean = retval; e_cal_component_free_datetime (&dt); return result; }
void e_sendoptions_utils_set_default_data (ESendOptionsDialog *sod, ESource *source, char * type) { ESendOptionsGeneral *gopts = NULL; ESendOptionsStatusTracking *sopts; GConfClient *gconf = gconf_client_get_default (); ESourceList *source_list; const char *uid; const char *value; gopts = sod->data->gopts; sopts = sod->data->sopts; if (!strcmp (type, "calendar")) source_list = e_source_list_new_for_gconf (gconf, "/apps/evolution/calendar/sources"); else source_list = e_source_list_new_for_gconf (gconf, "/apps/evolution/tasks/sources"); uid = e_source_peek_uid (source); source = e_source_list_peek_source_by_uid (source_list, uid); /* priority */ value = e_source_get_property (source, "priority"); if (value) { if (!strcmp (value, "high")) gopts->priority = E_PRIORITY_HIGH; else if (!strcmp (value, "standard")) gopts->priority = E_PRIORITY_STANDARD; else if (!strcmp (value, "low")) gopts->priority = E_PRIORITY_LOW; else gopts->priority = E_PRIORITY_UNDEFINED; } /* Reply requested */ value = e_source_get_property (source, "reply-requested"); if (value) { if (!strcmp (value, "none")) gopts->reply_enabled = FALSE; else if (!strcmp (value, "convinient")) { gopts->reply_enabled = TRUE; gopts->reply_convenient = TRUE; } else { gint i = atoi (value); gopts->reply_within = i; } } /* Delay delivery */ value = e_source_get_property (source, "delay-delivery"); if (value) { if (!strcmp (value, "none")) gopts->delay_enabled = FALSE; else { gopts->delay_enabled = TRUE; gopts->delay_until = icaltime_as_timet (icaltime_from_string (value)); } } /* Expiration Date */ value = e_source_get_property (source, "expiration"); if (value) { if (!strcmp (value, "none")) gopts->expiration_enabled = FALSE; else { gint i = atoi (value); if (i == 0) gopts->expiration_enabled = FALSE; else gopts->expiration_enabled = TRUE; gopts->expire_after = i; } } /* status tracking */ value = e_source_get_property (source, "status-tracking"); if (value) { if (!strcmp (value, "none")) sopts->tracking_enabled = FALSE; else { sopts->tracking_enabled = TRUE; if (!strcmp (value, "delivered")) sopts->track_when = E_DELIVERED; else if (!strcmp (value, "delivered-opened")) sopts->track_when = E_DELIVERED_OPENED; else sopts->track_when = E_ALL; } } /* Return Notifications */ value = e_source_get_property (source, "return-open"); if (value) { if (!strcmp (value, "none")) sopts->opened = E_RETURN_NOTIFY_NONE; else sopts->opened = E_RETURN_NOTIFY_MAIL; } value = e_source_get_property (source, "return-accept"); if (value) { if (!strcmp (value, "none")) sopts->accepted = E_RETURN_NOTIFY_NONE; else sopts->accepted = E_RETURN_NOTIFY_MAIL; } value = e_source_get_property (source, "return-decline"); if (value) { if (!strcmp (value, "none")) sopts->declined = E_RETURN_NOTIFY_NONE; else sopts->declined = E_RETURN_NOTIFY_MAIL; } value = e_source_get_property (source, "return-complete"); if (value) { if (!strcmp (value, "none")) sopts->completed = E_RETURN_NOTIFY_NONE; else sopts->completed = E_RETURN_NOTIFY_MAIL; } g_object_unref (gconf); }
void test_recur_file() { icalset *cin = 0; struct icaltimetype next; icalcomponent *itr; icalproperty *desc, *dtstart, *rrule; struct icalrecurrencetype recur; icalrecur_iterator* ritr; time_t tt; char* file; int num_recurs_found = 0; icalfileset_options options = {O_RDONLY, 0644, 0}; icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); #ifndef WIN32 signal(SIGALRM,sig_alrm); #endif file = getenv("ICAL_RECUR_FILE"); if (!file) file = TEST_DATADIR "/recur.txt"; #ifndef WIN32 alarm(15); /* to get file lock */ #endif cin = icalset_new(ICAL_FILE_SET, file, &options); #ifndef WIN32 alarm(0); #endif ok("opening file with recurring events", (cin!=NULL)); assert(cin!=NULL); for (itr = icalfileset_get_first_component(cin); itr != 0; itr = icalfileset_get_next_component(cin)){ int badcomp = 0; int expected_events = 0; char msg[128]; struct icaltimetype start = icaltime_null_time(); struct icaltimetype startmin = icaltime_from_timet(1,0); struct icaltimetype endmax = icaltime_null_time(); const char *desc_str = "malformed component"; desc = icalcomponent_get_first_property(itr,ICAL_DESCRIPTION_PROPERTY); dtstart = icalcomponent_get_first_property(itr,ICAL_DTSTART_PROPERTY); rrule = icalcomponent_get_first_property(itr,ICAL_RRULE_PROPERTY); if (desc) { desc_str = icalproperty_get_description(desc); } ok((char*)desc_str, !(desc == 0 || dtstart == 0 || rrule == 0)); if (desc == 0 || dtstart == 0 || rrule == 0) { badcomp = 1; if (VERBOSE) { printf("\n******** Error in input component ********\n"); printf("The following component is malformed:\n %s\n", desc_str); } continue; } if (VERBOSE) { printf("\n\n#### %s\n",desc_str); printf("#### %s\n",icalvalue_as_ical_string(icalproperty_get_value(rrule))); } recur = icalproperty_get_rrule(rrule); start = icalproperty_get_dtstart(dtstart); ritr = icalrecur_iterator_new(recur,start); tt = icaltime_as_timet(start); if (VERBOSE) printf("#### %s\n",ctime(&tt )); icalrecur_iterator_free(ritr); for(ritr = icalrecur_iterator_new(recur,start), next = icalrecur_iterator_next(ritr); !icaltime_is_null_time(next); next = icalrecur_iterator_next(ritr)){ tt = icaltime_as_timet(next); if (VERBOSE) printf(" %s",ctime(&tt )); } icalrecur_iterator_free(ritr); num_recurs_found = 0; expected_events = get_expected_numevents(itr); icalcomponent_foreach_recurrence(itr, startmin, endmax, recur_callback, &num_recurs_found); sprintf(msg," expecting total of %d events", expected_events); int_is(msg, num_recurs_found, expected_events); } icalset_free(cin); }
/* Add all ZONEs and LINKs in the given directory to the hash table */ void do_zonedir(const char *dir, struct hash_table *tzentries, struct zoneinfo *info) { DIR *dirp; struct dirent *dirent; signals_poll(); if (verbose) printf("Rebuilding %s\n", dir); dirp = opendir(dir); if (!dirp) { fprintf(stderr, "can't open zoneinfo directory %s\n", dir); } while ((dirent = readdir(dirp))) { char path[2048], *tzid; int plen; struct stat sbuf; struct zoneinfo *zi; if (*dirent->d_name == '.') continue; plen = snprintf(path, sizeof(path), "%s/%s", dir, dirent->d_name); lstat(path, &sbuf); if (S_ISDIR(sbuf.st_mode)) { /* Path is a directory (region) */ do_zonedir(path, tzentries, info); } else if (S_ISLNK(sbuf.st_mode)) { /* Path is a symlink (alias) */ char link[1024], *alias; ssize_t llen; /* Isolate tzid in path */ if ((llen = readlink(path, link, sizeof(link))) < 0) continue; link[llen-4] = '\0'; /* Trim ".ics" */ for (tzid = link; !strncmp(tzid, "../", 3); tzid += 3); /* Isolate alias in path */ path[plen-4] = '\0'; /* Trim ".ics" */ alias = path + strlen(config_dir) + strlen("zoneinfo") + 2; if (verbose) printf("\tLINK: %s -> %s\n", alias, tzid); /* Create hash entry for alias */ if (!(zi = hash_lookup(alias, tzentries))) { zi = xzmalloc(sizeof(struct zoneinfo)); hash_insert(alias, zi, tzentries); } zi->type = ZI_LINK; appendstrlist(&zi->data, tzid); /* Create/update hash entry for tzid */ if (!(zi = hash_lookup(tzid, tzentries))) { zi = xzmalloc(sizeof(struct zoneinfo)); hash_insert(tzid, zi, tzentries); } zi->type = ZI_ZONE; appendstrlist(&zi->data, alias); } else if (S_ISREG(sbuf.st_mode)) { /* Path is a regular file (zone) */ int fd; const char *base = NULL; size_t len = 0; icalcomponent *ical, *comp; icalproperty *prop; /* Parse the iCalendar file for important properties */ if ((fd = open(path, O_RDONLY)) == -1) continue; map_refresh(fd, 1, &base, &len, MAP_UNKNOWN_LEN, path, NULL); close(fd); ical = icalparser_parse_string(base); map_free(&base, &len); if (!ical) continue; /* skip non-iCalendar files */ comp = icalcomponent_get_first_component(ical, ICAL_VTIMEZONE_COMPONENT); prop = icalcomponent_get_first_property(comp, ICAL_TZID_PROPERTY); tzid = (char *) icalproperty_get_value_as_string(prop); if (verbose) printf("\tZONE: %s\n", tzid); /* Create/update hash entry for tzid */ if (!(zi = hash_lookup(tzid, tzentries))) { zi = xzmalloc(sizeof(struct zoneinfo)); hash_insert(tzid, zi, tzentries); } zi->type = ZI_ZONE; prop = icalcomponent_get_first_property(comp, ICAL_LASTMODIFIED_PROPERTY); zi->dtstamp = icaltime_as_timet(icalproperty_get_lastmodified(prop)); icalcomponent_free(ical); /* Check overall lastmod */ if (zi->dtstamp > info->dtstamp) info->dtstamp = zi->dtstamp; } else { fprintf(stderr, "unknown path type %s\n", path); } } closedir(dirp); }
icalspanlist* icalspanlist_new(icalset *set, struct icaltimetype start, struct icaltimetype end) { struct icaltime_span range; pvl_elem itr; icalcomponent *c,*inner; icalcomponent_kind kind, inner_kind; icalspanlist *sl; struct icaltime_span *freetime; if ( ( sl = (struct icalspanlist_impl*) malloc(sizeof(struct icalspanlist_impl))) == 0) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } sl->spans = pvl_newlist(); sl->start = start; sl->end = end; range.start = icaltime_as_timet(start); range.end = icaltime_as_timet(end); /* Get a list of spans of busy time from the events in the set and order the spans based on the start time */ for(c = icalset_get_first_component(set); c != 0; c = icalset_get_next_component(set)){ kind = icalcomponent_isa(c); inner = icalcomponent_get_inner(c); if(!inner){ continue; } inner_kind = icalcomponent_isa(inner); if( kind != ICAL_VEVENT_COMPONENT && inner_kind != ICAL_VEVENT_COMPONENT){ continue; } icalerror_clear_errno(); icalcomponent_foreach_recurrence(c, start, end, icalspanlist_new_callback, (void*)sl); } /* Now Fill in the free time spans. loop through the spans. if the start of the range is not within the span, create a free entry that runs from the start of the range to the start of the span. */ for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) { struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr); if ((freetime=(struct icaltime_span *) malloc(sizeof(struct icaltime_span))) == 0){ icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } if(range.start < s->start){ freetime->start = range.start; freetime->end = s->start; freetime->is_busy = 0; pvl_insert_ordered(sl->spans,compare_span,(void*)freetime); } else { free(freetime); } range.start = s->end; } /* If the end of the range is null, then assume that everything after the last item in the calendar is open and add a span that indicates this */ if( icaltime_is_null_time(end)){ struct icaltime_span* last_span; last_span = (struct icaltime_span*)pvl_data(pvl_tail(sl->spans)); if (last_span != 0){ if ((freetime=(struct icaltime_span *) malloc(sizeof(struct icaltime_span))) == 0){ icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } freetime->is_busy = 0; freetime->start = last_span->end; freetime->end = freetime->start; pvl_insert_ordered(sl->spans,compare_span,(void*)freetime); } } return sl; }