/* The default implementation is looking for timezone in the ical's builtin timezones, * and if that fails, then it tries to extract the location from the tzid and get the * timezone based on it. If even that fails, then it's returning UTC timezone. * That means, that any object deriving from ECalBackendSync is supposed to implement * this function for checking for a timezone in its own timezone cache, and if that * fails, then call parent's object internal_get_timezone, and that's all. */ static icaltimezone * cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid) { icaltimezone *zone = NULL; if (!tzid || !*tzid) return NULL; zone = icaltimezone_get_builtin_timezone_from_tzid (tzid); if (!zone) { const gchar *s, *slash1 = NULL, *slash2 = NULL; /* get builtin by a location, if any */ for (s = tzid; *s; s++) { if (*s == '/') { slash1 = slash2; slash2 = s; } } if (slash1) zone = icaltimezone_get_builtin_timezone (slash1 + 1); else if (slash2) zone = icaltimezone_get_builtin_timezone (tzid); } if (!zone) zone = icaltimezone_get_utc_timezone (); return zone; }
/* * Matches a location to a system timezone definition via a fuzzy * search and returns the matching TZID, or NULL if none found. * * Currently simply strips a suffix introduced by a hyphen, * as in "America/Denver-(Standard)". */ static const gchar * e_cal_match_location (const gchar *location) { icaltimezone *icomp; const gchar *tail; gsize len; gchar *buffer; icomp = icaltimezone_get_builtin_timezone (location); if (icomp) { return icaltimezone_get_tzid (icomp); } /* try a bit harder by stripping trailing suffix */ tail = strrchr (location, '-'); len = tail ? (tail - location) : strlen (location); buffer = g_malloc (len + 1); if (buffer) { memcpy (buffer, location, len); buffer[len] = 0; icomp = icaltimezone_get_builtin_timezone (buffer); g_free (buffer); if (icomp) { return icaltimezone_get_tzid (icomp); } } return NULL; }
//TODO: should not call libical functions directly -- better to make // a new libkcal abstraction method. QDateTime WebdavHandler::utcAsZone( const QDateTime& utc, const QString& timeZoneId ) { int daylight; QDateTime epoch; epoch.setTime_t( 0 ); time_t v = epoch.secsTo( utc ); struct icaltimetype tt = icaltime_from_timet_with_zone( v, 0 /*is_date*/, icaltimezone_get_builtin_timezone( "UTC" ) ); int offset = icaltimezone_get_utc_offset( icaltimezone_get_builtin_timezone( timeZoneId.latin1() ), &tt, &daylight ); kdDebug() << "Calculated offset of: " << offset << " of timezone: " << timeZoneId << endl; return utc.addSecs( offset ); }
static icaltimezone * get_users_timezone (void) { /* more or less copy&paste of calendar_config_get_icaltimezone */ GSettings *settings; icaltimezone *zone = NULL; gchar *location; settings = e_util_ref_settings ("org.gnome.evolution.calendar"); if (g_settings_get_boolean (settings, "use-system-timezone")) { location = e_cal_util_get_system_timezone_location (); } else { location = g_settings_get_string (settings, "timezone"); } g_object_unref (settings); if (location) { zone = icaltimezone_get_builtin_timezone (location); g_free (location); } return zone; }
/** * @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 }
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; }
/** * @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 }
//TODO: should not call libical functions directly -- better to make // a new libkcal abstraction method. QDateTime WebdavHandler::zoneAsUtc( const QDateTime& zone, const QString& timeZoneId ) { int daylight; QDateTime epoch; epoch.setTime_t( 0 ); time_t v = epoch.secsTo( zone ); struct icaltimetype tt = icaltime_from_timet( v, 0 ); // 0: is_date=false int offset = icaltimezone_get_utc_offset( icaltimezone_get_builtin_timezone( timeZoneId.latin1() ), &tt, &daylight ); return zone.addSecs( - offset ); }
//TODO: should not call libical functions directly -- better to make // a new libkcal abstraction method. QDateTime utcAsZone( const QDateTime& utc, const QString& timeZoneId ) { int daylight; QDateTime epoch; epoch.setTime_t( 0 ); time_t v = epoch.secsTo( utc ); struct icaltimetype tt = icaltime_from_timet( v, 0 ); // 0: is_date=false int offset = icaltimezone_get_utc_offset( icaltimezone_get_builtin_timezone( timeZoneId.latin1() ), &tt, &daylight ); return utc.addSecs( offset ); }
GSList* EDSCalendarStorage::toICalComponentsList(const std::vector<std::string> & iCals, const OpenAB::PIMItem::IDs& ids, std::vector<icaltimezone*>& timezones) { GSList * events = NULL; currentEventTimeZones.clear(); for(unsigned int i = 0; i < iCals.size(); ++i) { std::stringstream ss(iCals[i]); //In case of recurring events one iCalendar can contain couple of VEVENT objects, get them all while (1) { std::string event = EDSCalendarStorageCommon::cutVObject(ss); if (event.empty()) { break; } icalcomponent* newEvent = icalcomponent_new_from_string(event.c_str()); if (!newEvent) { LOG_DEBUG() << "Cannot parse vevent" << std::endl; g_slist_free_full(events, (GDestroyNotify) icalcomponent_free); return NULL; } icalcomponent_foreach_tzid(newEvent, EDSCalendarStorage::findTimeZonesCb, newEvent); icalcomponent_strip_errors(newEvent); if (ids.size() > i) icalcomponent_set_uid(newEvent, ids[i].c_str()); events = g_slist_append(events, newEvent); } } std::set<std::string>::iterator it; for(it = currentEventTimeZones.begin(); it != currentEventTimeZones.end(); ++it) { icaltimezone* tz = icaltimezone_get_builtin_timezone((*it).c_str()); if (tz) { timezones.push_back(tz); } } return events; }
/** * e_cal_util_get_system_timezone: * * Fetches system timezone icaltimezone object. * * The returned pointer is part of the built-in timezones and should not be freed. * * Returns: (transfer none): The icaltimezone object of the system timezone, or %NULL on an error. * * Since: 2.28 **/ icaltimezone * e_cal_util_get_system_timezone (void) { gchar *location; icaltimezone *zone; location = e_cal_system_timezone_get_location (); g_return_val_if_fail (location != NULL, NULL); zone = icaltimezone_get_builtin_timezone (location); g_free (location); return zone; }
icaltimezone * calendar_config_get_icaltimezone (void) { gchar *location; icaltimezone *zone = NULL; calendar_config_init (); location = calendar_config_get_timezone (); if (location) { zone = icaltimezone_get_builtin_timezone (location); g_free (location); } return zone; }
static void app_update_timezone (App *app) { gchar *location; location = e_cal_system_timezone_get_location (); if (g_strcmp0 (location, app->timezone_location) != 0) { if (location == NULL) app->zone = icaltimezone_get_utc_timezone (); else app->zone = icaltimezone_get_builtin_timezone (location); g_free (app->timezone_location); app->timezone_location = location; print_debug ("Using timezone %s", app->timezone_location); } }
/** Returns a single builtin timezone, given its TZID. */ icaltimezone* icaltimezone_get_builtin_timezone_from_tzid (const char *tzid) { int num_slashes = 0; const char *p, *zone_tzid; icaltimezone *zone; if (!tzid || !tzid[0]) return NULL; /* Check that the TZID starts with our unique prefix. */ if (strncmp (tzid, TZID_PREFIX, TZID_PREFIX_LEN)) return NULL; /* Get the location, which is after the 3rd '/' character. */ p = tzid; for (p = tzid; *p; p++) { if (*p == '/') { num_slashes++; if (num_slashes == 3) break; } } if (num_slashes != 3) return NULL; p++; /* Now we can use the function to get the builtin timezone from the location string. */ zone = icaltimezone_get_builtin_timezone (p); if (!zone) return NULL; /* Check that the builtin TZID matches exactly. We don't want to return a different version of the VTIMEZONE. */ zone_tzid = icaltimezone_get_tzid (zone); if (!strcmp (zone_tzid, tzid)) return zone; else return NULL; }
static icaltimezone * get_default_timezone (void) { EConfigListener *listener; icaltimezone *timezone = NULL; char *location; listener = e_config_listener_new (); location = e_config_listener_get_string_with_default (listener, "/apps/evolution/calendar/display/timezone", "UTC", NULL); if (!location || !location[0]) { g_free (location); location = g_strdup ("UTC"); } timezone = icaltimezone_get_builtin_timezone (location); g_free (location); g_object_unref (listener); return timezone; }
void calendar_config_select_day_second_zone (void) { icaltimezone *zone = NULL; ETimezoneDialog *tzdlg; GtkWidget *dialog; gchar *second_location; second_location = calendar_config_get_day_second_zone (); if (second_location && *second_location) zone = icaltimezone_get_builtin_timezone (second_location); g_free (second_location); if (!zone) zone = calendar_config_get_icaltimezone (); tzdlg = e_timezone_dialog_new (); e_timezone_dialog_set_timezone (tzdlg, zone); dialog = e_timezone_dialog_get_toplevel (tzdlg); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { const gchar *location = NULL; zone = e_timezone_dialog_get_timezone (tzdlg); if (zone == icaltimezone_get_utc_timezone ()) { location = "UTC"; } else if (zone) { location = icaltimezone_get_location (zone); } calendar_config_set_day_second_zone (location); } g_object_unref (tzdlg); }
/** Test icalcomponent_get_span() * */ void test_icalcomponent_get_span() { time_t tm1 = 973378800; /*Sat Nov 4 23:00:00 UTC 2000, Sat Nov 4 15:00:00 PST 2000 */ time_t tm2 = 973382400; /*Sat Nov 5 00:00:00 UTC 2000 Sat Nov 4 16:00:00 PST 2000 */ struct icaldurationtype dur; struct icaltime_span span; icalcomponent *c; icaltimezone *azone, *bzone; int tnum = 0; /** test 0 * Direct assigning time_t means they will be interpreted as UTC */ span.start = tm1; span.end = tm2; if (VERBOSE) print_span(tnum++,span); /** test 1 * We specify times in a timezone, the returned span is in UTC */ azone = icaltimezone_get_builtin_timezone("America/Los_Angeles"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/Los_Angeles"),0), icalproperty_vanew_dtend( icaltime_from_timet_with_zone(tm2,0,azone), icalparameter_new_tzid("America/Los_Angeles"),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/Los_Angeles", span.start, 973407600); icalcomponent_free(c); /** test 2 * We specify times as floating, the returned span is in UTC * with no conversion applied - so result should be as test 0 */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0),0), icalproperty_vanew_dtend(icaltime_from_timet(tm2,0),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("floating time", span.start, tm1); icalcomponent_free(c); /** test 3 * We specify times in a timezone, the returned span is in UTC */ azone = icaltimezone_get_builtin_timezone("America/New_York"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/New_York"),0), icalproperty_vanew_dtend( icaltime_from_timet_with_zone(tm2,0,azone), icalparameter_new_tzid("America/New_York"),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/New_York", span.start, 973396800); icalcomponent_free(c); /** test 4 * We specify times in two different timezones, the returned span * is in UTC */ azone = icaltimezone_get_builtin_timezone("America/New_York"); bzone = icaltimezone_get_builtin_timezone("America/Los_Angeles"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/New_York"),0), icalproperty_vanew_dtend( icaltime_from_timet_with_zone(tm2,0,bzone), icalparameter_new_tzid("America/Los_Angeles"),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/New_York", span.start, 973396800); icalcomponent_free(c); /** test 5 * We specify start time in a timezone and a duration, the returned span * is in UTC */ azone = icaltimezone_get_builtin_timezone("America/Los_Angeles"); memset(&dur,0,sizeof(dur)); dur.minutes = 30; c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/Los_Angeles"),0), icalproperty_new_duration(dur), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/Los_Angeles w/ duration", span.end, 973409400); icalcomponent_free(c); icalerror_errors_are_fatal = 0; /** test 6 * We specify only start time, should return a null span with no error */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,0)), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("null span", span.start, 0); icalcomponent_free(c); /** test 7 * We specify start and end date */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,1)), icalproperty_new_dtend(icaltime_from_timet(tm1,1)), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("UTC", span.start, 973296000); icalcomponent_free(c); /** test 8 * We specify start and end date */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,1)), icalproperty_new_dtend(icaltime_from_timet(tm2,1)), 0 ); span = icalcomponent_get_span(c); int_is("UTC #2", span.start, 973296000); if (VERBOSE) print_span(tnum++,span); icalcomponent_free(c); /** test 9 * We specify start date */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,1)), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("start date only", span.end, 973382399); icalcomponent_free(c); /* assert(icalerrno == ICAL_MALFORMEDDATA_ERROR); */ icalerror_errors_are_fatal = 1; }
static void cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzid) { GError *error = NULL; gchar *object = NULL; e_cal_backend_sync_get_timezone (E_CAL_BACKEND_SYNC (backend), cal, cancellable, tzid, &object, &error); if (!object && tzid) { /* fallback if tzid contains only the location of timezone */ gint i, slashes = 0; for (i = 0; tzid[i]; i++) { if (tzid[i] == '/') slashes++; } if (slashes == 1) { icalcomponent *icalcomp = NULL, *free_comp = NULL; icaltimezone *zone = icaltimezone_get_builtin_timezone (tzid); if (!zone) { /* Try fetching the timezone from zone directory. There are some timezones like MST, US/Pacific etc. which do not appear in zone.tab, so they will not be available in the libical builtin timezone */ icalcomp = free_comp = icaltzutil_fetch_timezone (tzid); } if (zone) icalcomp = icaltimezone_get_component (zone); if (icalcomp) { icalcomponent *clone = icalcomponent_new_clone (icalcomp); icalproperty *prop; prop = icalcomponent_get_first_property (clone, ICAL_TZID_PROPERTY); if (prop) { /* change tzid to our, because the component has the buildin tzid */ icalproperty_set_tzid (prop, tzid); object = icalcomponent_as_ical_string_r (clone); g_clear_error (&error); } icalcomponent_free (clone); } if (free_comp) icalcomponent_free (free_comp); } /* also cache this timezone to backend */ if (object) e_cal_backend_sync_add_timezone (E_CAL_BACKEND_SYNC (backend), cal, cancellable, object, NULL); } e_data_cal_respond_get_timezone (cal, opid, error, object); g_free (object); }
int main() { icalarray *builtin_timezones; icaltimetype tt; int dd, hh, zz, tried = 0; long zz2 = -1; set_zone_directory("../../zoneinfo"); icaltimezone_set_tzid_prefix("/softwarestudio.org/"); tt = icaltime_current_time_with_zone(icaltimezone_get_builtin_timezone("America/New_York")); tt.year = 2038; (void)icaltime_as_timet_with_zone(tt, icaltimezone_get_builtin_timezone("PST")); tried++; tt.year = 2050; (void)icaltime_as_timet_with_zone(tt, icaltimezone_get_builtin_timezone("PST")); tried++; tt.year = 1958; (void)icaltime_as_timet_with_zone(tt, icaltimezone_get_builtin_timezone("PST")); tried++; builtin_timezones = icaltimezone_get_builtin_timezones(); printf("got %lu zones\n", (unsigned long)builtin_timezones->num_elements); if (builtin_timezones->num_elements == 0) { printf("YIKES. Try running from the build/bin directory\n"); return(1); } for (zz = -1; zz < (int)builtin_timezones->num_elements; zz++) { icaltimezone *zone; if (zz < 0) { zone = icaltimezone_get_utc_timezone(); } else { zone = icalarray_element_at(builtin_timezones, (size_t)zz); } tt = icaltime_current_time_with_zone(zone); for (dd = 0; dd < 370; dd += 17) { for (hh = 0; hh < 60 * 60 * 24; hh += 567) { int zz2cnt; icaltime_adjust(&tt, 0, 0, 0, 1); for (zz2cnt = 0; zz2cnt < 15; zz2cnt++) { icaltimezone *zone2; if (zz2 < 0) { zone2 = icaltimezone_get_utc_timezone(); } else { zone2 = icalarray_element_at(builtin_timezones, (size_t)zz2); } (void)icaltime_as_timet_with_zone(tt, zone2); tried++; zz2++; if (zz2 >= (long)builtin_timezones->num_elements) zz2 = -1; } } } printf("\r%lu %% done", (zz >= 0 ? zz : 0) * 100 / (unsigned long)builtin_timezones->num_elements); fflush(stdout); } printf("\ntried %d times\n", tried); return 0; }
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; }
/** * @brief * Check if a recurrence rule is valid and consistent. * The recurrence rule is verified against a start date and checks * that the frequency of the recurrence matches the duration of the * submitted reservation. If the duration of a reservation exceeds the * granularity of the frequency then an error message is displayed. * * @par The recurrence rule is checked to contain a COUNT or an UNTIL. * * @par Note that the PBS_TZID environment variable HAS to be set for the occurrence's * dates to be correctly computed. * * @param[in] rrule - The recurrence rule to unroll * @param[in] dtstart - The start time associated to the reservation (1st occurrence) * @param[in] dtend - The end time associated to the reservation (1st occurrence) * @param[in] duration - The duration of an occurrence. This is used when a reservation is * submitted using the -D (duration) param instead of an end time * @param[in] tz - The timezone associated to the recurrence rule * @param[in] err_code - A pointer to the error code to return. Codes are defined in pbs_error.h * * @return int * @retval The total number of occurrences that the recurrence rule and start date * * define. 1 for an advance reservation. * */ int check_rrule(char *rrule, time_t dtstart, time_t dtend, char *tz, int *err_code) { #ifdef LIBICAL /* Standing Reservation Recurrence */ int count = 1; struct icalrecurrencetype rt; struct icaltimetype start; struct icaltimetype next; struct icaltimetype first; struct icaltimetype prev; struct icalrecur_iterator_impl *itr; icaltimezone *localzone; int time_err = 0; int i; long min_occr_duration = -1; long tmp_occr_duration = 0; long duration; *err_code = 0; icalerror_clear_errno(); icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); icalerror_errors_are_fatal = 0; if (tz == NULL || rrule == NULL) return 0; localzone = icaltimezone_get_builtin_timezone(tz); /* If the timezone info directory is not accessible * then bail */ if (localzone == NULL) { *err_code = PBSE_BAD_ICAL_TZ; return 0; } rt = icalrecurrencetype_from_string(rrule); /* Check if by_day rules are defined and valid * the first item in the array of by_* rule * determines whether the item exists or not. */ for (i = 0; rt.by_day[i] < 8; i++) { if (rt.by_day[i] <= 0) { *err_code = PBSE_BAD_RRULE_SYNTAX; return 0; } } /* Check if by_hour rules are defined and valid * the first item in the array of by_* rule * determines whether the item exists or not. */ for (i = 0; rt.by_hour[i] < 25; i++) { if (rt.by_hour[i] < 0) { *err_code = PBSE_BAD_RRULE_SYNTAX; return 0; } } /* Check if the rest of the by_* rules are defined * and valid. * currently no support for * BYMONTHDAY, BYYEARDAY, BYSECOND, * BYMINUTE, BYWEEKNO, or BYSETPOS * */ if (rt.by_second[0] < 61 || /* by_second is negative such as in -10 */ rt.by_minute[0] < 61 || /* by_minute is negative such as in -10 */ rt.by_year_day[0] < 367 || /* a year day is defined */ rt.by_month_day[0] < 31 || /* a month day is defined */ rt.by_week_no[0] < 52 || /* a week number is defined */ rt.by_set_pos[0] < 367) { /* a set pos is defined */ *err_code = PBSE_BAD_RRULE_SYNTAX; return 0; } /* Require that either a COUNT or UNTIL be passed. But not both. */ if ((rt.count == 0 && icaltime_is_null_time(rt.until)) || (rt.count != 0 && !icaltime_is_null_time(rt.until))) { *err_code = PBSE_BAD_RRULE_SYNTAX2; /* Undefined iCalendar synax. A valid COUNT or UNTIL is required */ return 0; } 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); duration = dtend -dtstart; /* First check if the syntax of the iCalendar rule is valid */ next = icalrecur_iterator_next(itr); /* Catch case where first occurrence date is in the past */ if (icaltime_is_null_time(next)) { *err_code = PBSE_BADTSPEC; icalrecur_iterator_free(itr); return 0; } first = next; prev = first; for (next=icalrecur_iterator_next(itr); !icaltime_is_null_time(next); next=icalrecur_iterator_next(itr), count++) { /* The interval duration between two occurrences * is the time between the end of an occurrence and the * start of the next one */ tmp_occr_duration = icaltime_as_timet(next) - icaltime_as_timet(prev); /* Set the minimum time interval between occurrences */ if (min_occr_duration == -1) min_occr_duration = tmp_occr_duration; else if (tmp_occr_duration > 0 && tmp_occr_duration < min_occr_duration) min_occr_duration = tmp_occr_duration; prev = next; } /* clean up */ icalrecur_iterator_free(itr); if (icalerrno != ICAL_NO_ERROR) { *err_code = PBSE_BAD_RRULE_SYNTAX; /* Undefined iCalendar syntax */ return 0; } /* Then check if the duration fits in the frequency rule */ switch (rt.freq) { case ICAL_SECONDLY_RECURRENCE: { if (duration > 1) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_SECONDLY; /* SECONDLY recurrence duration cannot exceed 1 second */ time_err++; } break; } case ICAL_MINUTELY_RECURRENCE: { if (duration > 60) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_MINUTELY; /* MINUTELY recurrence duration cannot exceed 1 minute */ time_err++; } break; } case ICAL_HOURLY_RECURRENCE: { if (duration > (60*60)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno =1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_HOURLY; /* HOURLY recurrence duration cannot exceed 1 hour */ time_err++; } break; } case ICAL_DAILY_RECURRENCE: { if (duration > (60*60*24)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_DAILY; /* DAILY recurrence duration cannot exceed 24 hours */ time_err++; } break; } case ICAL_WEEKLY_RECURRENCE: { if (duration > (60*60*24*7)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_WEEKLY; /* WEEKLY recurrence duration cannot exceed 1 week */ time_err++; } break; } case ICAL_MONTHLY_RECURRENCE: { if (duration > (60*60*24*30)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_MONTHLY; /* MONTHLY recurrence duration cannot exceed 1 month */ time_err++; } break; } case ICAL_YEARLY_RECURRENCE: { if (duration > (60*60*24*30*365)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_YEARLY; /* YEARLY recurrence duration cannot exceed 1 year */ time_err++; } break; } default: { icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return 0; } } if (time_err) return 0; /* If the requested reservation duration exceeds * the occurrence's duration then print an error * message and return */ if (count != 1 && duration > min_occr_duration) { *err_code = PBSE_BADTSPEC; /* Bad Time Specification(s) */ return 0; } return count; #else *err_code = PBSE_BAD_RRULE_SYNTAX; /* iCalendar is undefined */ return 0; #endif }
/** * build_component_from_details: * @summary: * @initial_date: * @final_date: * * Create a component with the provided details * * Returns: (Transfer full): an {@link ECalComponent} object **/ ECalComponent* build_component_from_details (const gchar *summary, GDateTime *initial_date, GDateTime *final_date) { ECalComponent *event; ECalComponentDateTime dt; ECalComponentText summ; icaltimezone *zone; gboolean all_day; event = e_cal_component_new (); e_cal_component_set_new_vtype (event, E_CAL_COMPONENT_EVENT); /* * Check if the event is all day. Notice that it can be all day even * without the final date. */ all_day = datetime_is_date (initial_date) && (final_date ? datetime_is_date (final_date) : TRUE); /* * When the event is all day, we consider UTC timezone by default. Otherwise, * we always use the system timezone to create new events */ if (all_day) { zone = icaltimezone_get_utc_timezone (); } else { gchar *system_tz = e_cal_system_timezone_get_location (); zone = icaltimezone_get_builtin_timezone (system_tz); g_free (system_tz); } /* Start date */ dt.value = datetime_to_icaltime (initial_date); icaltime_set_timezone (dt.value, zone); dt.value->is_date = all_day; dt.tzid = icaltimezone_get_tzid (zone); e_cal_component_set_dtstart (event, &dt); g_free (dt.value); /* End date */ if (!final_date) final_date = g_date_time_add_days (initial_date, 1); dt.value = datetime_to_icaltime (final_date); icaltime_set_timezone (dt.value, zone); dt.value->is_date = all_day; dt.tzid = icaltimezone_get_tzid (zone); e_cal_component_set_dtend (event, &dt); g_free (dt.value); /* Summary */ summ.altrep = NULL; summ.value = summary; e_cal_component_set_summary (event, &summ); e_cal_component_commit_sequence (event); return event; }
icaltimezone * calendar_config_get_icaltimezone (void) { char *location; icaltimezone *zone = NULL; calendar_config_init (); location = calendar_config_get_timezone (); if (location) { icalcomponent *icalcomp, *dl_comp; zone = icaltimezone_get_builtin_timezone (location); icalcomp = icaltimezone_get_component (zone); if (!(dl_comp = icalcomponent_get_first_component (icalcomp, ICAL_XDAYLIGHT_COMPONENT))) { g_free (location); return zone; } if (!calendar_config_get_daylight_saving () && zone) { icalcomponent *zone_comp, *s_comp; icalproperty *tz_prop, *offset_to; icaltimezone *st_zone = NULL; int offset; char *n_tzid, *tzid; tzid = icaltimezone_get_tzid (zone); n_tzid = g_strconcat (tzid, "-(Standard)", NULL); if (!custom_zones) { custom_zones = g_hash_table_new (g_str_hash, g_str_equal); } else if ((st_zone = g_hash_table_lookup (custom_zones, n_tzid))) { g_free (n_tzid); g_free (location); return st_zone; } zone_comp = icalcomponent_new_clone (icalcomp); s_comp = icalcomponent_get_first_component (zone_comp, ICAL_XSTANDARD_COMPONENT); if (!s_comp) { g_free (n_tzid); icalcomponent_free (zone_comp); g_free (location); return zone; } offset_to = icalcomponent_get_first_property (s_comp, ICAL_TZOFFSETTO_PROPERTY); offset = icalproperty_get_tzoffsetto (offset_to); set_standard_offsets (zone_comp, offset); tz_prop = icalcomponent_get_first_property (zone_comp, ICAL_TZID_PROPERTY); if (tz_prop) { icalcomponent_remove_property (zone_comp, tz_prop); } tz_prop = icalproperty_new_tzid (n_tzid); icalcomponent_add_property (zone_comp, tz_prop); st_zone = icaltimezone_new (); icaltimezone_set_component (st_zone, zone_comp); zone = st_zone; g_hash_table_insert (custom_zones, n_tzid, zone); } g_free (location); } return zone; }