aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamon Chaplin <damon@ximian.com>2001-06-14 10:50:46 +0800
committerDamon Chaplin <damon@src.gnome.org>2001-06-14 10:50:46 +0800
commitd54f22de6ebd3b8c69468523c0157952bf632eb3 (patch)
tree4849aebae86ee0ce95203cb447a5174fa3f9ff46
parent8c1465a8455b6f4c88c14e95ae786b9b3404c06a (diff)
downloadgsoc2013-evolution-d54f22de6ebd3b8c69468523c0157952bf632eb3.tar.gz
gsoc2013-evolution-d54f22de6ebd3b8c69468523c0157952bf632eb3.tar.zst
gsoc2013-evolution-d54f22de6ebd3b8c69468523c0157952bf632eb3.zip
merged in some new stuff from libical CVS. (icalrecur_add_byrules): If no
2001-06-13 Damon Chaplin <damon@ximian.com> * src/libical/icalrecur.c: merged in some new stuff from libical CVS. (icalrecur_add_byrules): If no sign is given set sign to 1 (i.e. default to positive). (icalrecur_iterator_new): when setting up the year days array, handle the case where a year has no occurrences and we have to skip it. Also initialize the last.day and last.month fields. (expand_by_day): set the last day of the year explicitly rather than adding 1 to year and subtracting 1 from day. It is more efficient, and less prone to bugs. Also rewrote a bit. (expand_year_days): added code to handle BY_MONTH_DAY and BY_DAY + BY_MONTH_DAY, and rewrote code to handle BY_DAY + BY_MONTH. (next_year): handled the case where there are no occurrences in the year. * src/libical/icaltime.c (icaltime_adjust): new function to adjust a time by a number of days/hours/minutes/seconds. (icaltime_day_of_week): rewrote using a single call to mktime(). (icaltime_day_of_year): rewrote using a single call to mktime(). (icaltime_from_day_of_year): rewrote in a simpler way. The old version had a bug in it. * src/libical/icaltime.h (struct icaltimetype): added is_daylight flag, so we can try to distinguish between standard and daylight time when the clocks go back. Though this doesn't always resolve the ambiguity. * src/libical/icalcomponent.c: added some stuff to handle timezone data connected to the calendar component. Unfinished. * src/libical/icalyacc.y: merged in a fix from sourceforge CVS version of libical, so we can handle -ve UTC offsets. * src/libical/Makefile.am (CPPFLAGS): added PACKAGE_DATA_DIR define for finding the VTIMEZONE files. (libical_la_SOURCES): added icalarray.[hc] and icaltimezone.[hc]. (COMBINEDHEADERS): added icalarray.h and icaltimezone.h to the headers to be combined into ical.h. svn path=/trunk/; revision=10220
-rw-r--r--libical/ChangeLog40
-rw-r--r--libical/src/libical/Makefile.am10
-rw-r--r--libical/src/libical/icalcomponent.c124
-rw-r--r--libical/src/libical/icalrecur.c187
-rw-r--r--libical/src/libical/icaltime.c151
-rw-r--r--libical/src/libical/icaltime.h9
-rw-r--r--libical/src/libical/icalyacc.y6
7 files changed, 438 insertions, 89 deletions
diff --git a/libical/ChangeLog b/libical/ChangeLog
index 84aaf6c9f4..7738c42ec0 100644
--- a/libical/ChangeLog
+++ b/libical/ChangeLog
@@ -1,5 +1,45 @@
2001-06-13 Damon Chaplin <damon@ximian.com>
+ * src/libical/icalrecur.c: merged in some new stuff from libical CVS.
+ (icalrecur_add_byrules): If no sign is given set sign to 1 (i.e.
+ default to positive).
+ (icalrecur_iterator_new): when setting up the year days array, handle
+ the case where a year has no occurrences and we have to skip it.
+ Also initialize the last.day and last.month fields.
+ (expand_by_day): set the last day of the year explicitly rather than
+ adding 1 to year and subtracting 1 from day. It is more efficient,
+ and less prone to bugs. Also rewrote a bit.
+ (expand_year_days): added code to handle BY_MONTH_DAY and BY_DAY +
+ BY_MONTH_DAY, and rewrote code to handle BY_DAY + BY_MONTH.
+ (next_year): handled the case where there are no occurrences in the
+ year.
+
+ * src/libical/icaltime.c (icaltime_adjust): new function to adjust a
+ time by a number of days/hours/minutes/seconds.
+ (icaltime_day_of_week): rewrote using a single call to mktime().
+ (icaltime_day_of_year): rewrote using a single call to mktime().
+ (icaltime_from_day_of_year): rewrote in a simpler way. The old version
+ had a bug in it.
+
+ * src/libical/icaltime.h (struct icaltimetype): added is_daylight
+ flag, so we can try to distinguish between standard and daylight time
+ when the clocks go back. Though this doesn't always resolve the
+ ambiguity.
+
+ * src/libical/icalcomponent.c: added some stuff to handle timezone
+ data connected to the calendar component. Unfinished.
+
+ * src/libical/icalyacc.y: merged in a fix from sourceforge CVS version
+ of libical, so we can handle -ve UTC offsets.
+
+ * src/libical/Makefile.am (CPPFLAGS): added PACKAGE_DATA_DIR define
+ for finding the VTIMEZONE files.
+ (libical_la_SOURCES): added icalarray.[hc] and icaltimezone.[hc].
+ (COMBINEDHEADERS): added icalarray.h and icaltimezone.h to the headers
+ to be combined into ical.h.
+
+2001-06-13 Damon Chaplin <damon@ximian.com>
+
* src/libical/icaltimezone.[hc]: new files to contain support for
timezones.
diff --git a/libical/src/libical/Makefile.am b/libical/src/libical/Makefile.am
index 5c2200c7f0..9e1a6da9ca 100644
--- a/libical/src/libical/Makefile.am
+++ b/libical/src/libical/Makefile.am
@@ -2,7 +2,7 @@
# FILE: Makefile.am
# CREATOR: eric
#
-# $Id: Makefile.am,v 1.29 2001/05/16 07:16:31 jpr Exp $
+# $Id: Makefile.am,v 1.30 2001/06/14 02:50:46 damon Exp $
#
#
# (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
@@ -36,6 +36,8 @@ YFLAGS = -d -v -t -pical_yy
LFLAGS = -Pical_yy
LEX_OUTPUT_ROOT = lex.ical_yy
+CPPFLAGS = -DPACKAGE_DATA_DIR=\""$(datadir)/$(PACKAGE)"\"
+
all: ical.h
INCLUDES = \
@@ -48,6 +50,8 @@ libical_la_LDFLAGS = -version-info 0:0:0
libical_la_SOURCES = \
$(BUILT_SOURCES) \
+ icalarray.c \
+ icalarray.h \
icalattendee.h \
icalattendee.c \
icalcomponent.c \
@@ -73,6 +77,8 @@ libical_la_SOURCES = \
icalrestriction.h \
icaltime.c \
icaltime.h \
+ icaltimezone.c \
+ icaltimezone.h \
icalduration.h \
icalduration.c \
icalperiod.h \
@@ -114,7 +120,9 @@ COMBINEDHEADERS = \
$(top_srcdir)/src/libical/icalproperty.h \
$(top_srcdir)/src/libical/icalattendee.h \
$(top_srcdir)/src/libical/pvl.h \
+ $(top_srcdir)/src/libical/icalarray.h \
$(top_srcdir)/src/libical/icalcomponent.h \
+ $(top_srcdir)/src/libical/icaltimezone.h \
$(top_srcdir)/src/libical/icalparser.h \
$(top_srcdir)/src/libical/icalmemory.h \
$(top_srcdir)/src/libical/icalerror.h \
diff --git a/libical/src/libical/icalcomponent.c b/libical/src/libical/icalcomponent.c
index c28c972007..ee4ec54f30 100644
--- a/libical/src/libical/icalcomponent.c
+++ b/libical/src/libical/icalcomponent.c
@@ -33,6 +33,8 @@
#include "icalmemory.h"
#include "icalenums.h"
#include "icaltime.h"
+#include "icalarray.h"
+#include "icaltimezone.h"
#include "icalduration.h"
#include "icalperiod.h"
#include "icalparser.h"
@@ -55,6 +57,7 @@ struct icalcomponent_impl
pvl_list components;
pvl_elem component_iterator;
icalcomponent* parent;
+ icalarray* timezones;
};
/* icalproperty functions that only components get to use */
@@ -65,6 +68,8 @@ void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args);
icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind);
int icalcomponent_property_sorter(void *a, void *b);
+static void icalcomponent_rename_tzids_callback(icalparameter *param,
+ void *data);
void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args)
{
@@ -108,6 +113,7 @@ icalcomponent_new_impl (icalcomponent_kind kind)
comp->component_iterator = 0;
comp->x_name = 0;
comp->parent = 0;
+ comp->timezones = icaltimezone_array_new ();
return comp;
}
@@ -219,6 +225,8 @@ icalcomponent_free (icalcomponent* component)
free(c->x_name);
}
+ icalarray_free (c->timezones);
+
c->kind = ICAL_NO_COMPONENT;
c->properties = 0;
c->property_iterator = 0;
@@ -226,9 +234,11 @@ icalcomponent_free (icalcomponent* component)
c->component_iterator = 0;
c->x_name = 0;
c->id[0] = 'X';
+ c->timezones = NULL;
free(c);
}
+
}
char*
@@ -531,6 +541,10 @@ icalcomponent_add_component (icalcomponent* parent, icalcomponent* child)
cimpl->parent = parent;
pvl_push(impl->components,child);
+
+ /* If the new component is a VTIMEZONE, add it to our array. */
+ if (cimpl->kind == ICAL_VTIMEZONE_COMPONENT)
+ icaltimezone_array_append_from_vtimezone (cimpl->timezones, child);
}
@@ -546,6 +560,20 @@ icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child)
impl = (struct icalcomponent_impl*)parent;
cimpl = (struct icalcomponent_impl*)child;
+ /* If the component is a VTIMEZONE, remove it from our array as well. */
+ if (cimpl->kind == ICAL_VTIMEZONE_COMPONENT) {
+ icaltimezone *zone;
+ int i;
+
+ for (i = 0; i < impl->timezones->num_elements; i++) {
+ zone = icalarray_element_at (impl->timezones, i);
+ if (icaltimezone_get_component (zone) == child) {
+ icalarray_remove_element_at (impl->timezones, i);
+ break;
+ }
+ }
+ }
+
for( itr = pvl_head(impl->components);
itr != 0;
itr = next_itr)
@@ -1485,3 +1513,99 @@ icalcomponent* icalcomponent_new_xdaylight()
{
return icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
}
+
+/* Calls the given function for each TZID parameter found in the component. */
+void icalcomponent_foreach_tzid(icalcomponent* comp,
+ void (*callback)(icalparameter *param, void *data),
+ void *callback_data)
+{
+ icalproperty *prop;
+ icalproperty_kind kind;
+ icalparameter *param;
+ icalcomponent *child;
+
+ /* First rename any TZID parameters used in this component. */
+ prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+ while (prop) {
+ kind = icalproperty_isa (prop);
+
+ /* These are the only properties that can have a TZID. Note that
+ COMPLETED, CREATED, DTSTAMP & LASTMODIFIED must be in UTC. */
+ if (kind == ICAL_DTSTART_PROPERTY || kind == ICAL_DTEND_PROPERTY
+ || kind == ICAL_DUE_PROPERTY || kind == ICAL_EXDATE_PROPERTY
+ || kind == ICAL_RDATE_PROPERTY) {
+ param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
+ if (param)
+ (*callback) (param, callback_data);
+ }
+
+ prop = icalcomponent_get_next_property (comp, ICAL_ANY_PROPERTY);
+ }
+
+ /* Now recursively rename child components. */
+ child = icalcomponent_get_first_component (comp, ICAL_ANY_COMPONENT);
+ while (child) {
+ icalcomponent_foreach_tzid (child, callback, callback_data);
+ child = icalcomponent_get_next_component (comp, ICAL_ANY_COMPONENT);
+ }
+}
+
+
+/* Renames all references to the given TZIDs to a new name. rename_table
+ contains pairs of strings - a current TZID, and the new TZID to rename it
+ to. */
+void icalcomponent_rename_tzids(icalcomponent* comp, icalarray* rename_table)
+{
+ icalcomponent_foreach_tzid (comp, icalcomponent_rename_tzids_callback,
+ rename_table);
+}
+
+
+static void icalcomponent_rename_tzids_callback(icalparameter *param, void *data)
+{
+ icalarray *rename_table = data;
+ const char *tzid;
+ int i;
+
+ tzid = icalparameter_get_tzid (param);
+ if (!tzid)
+ return;
+
+ /* Step through the rename table to see if the current TZID matches
+ any of the ones we want to rename. */
+ for (i = 0; i < rename_table->num_elements - 1; i += 2) {
+ if (!strcmp (tzid, icalarray_element_at (rename_table, i)))
+ icalparameter_set_tzid (param, icalarray_element_at (rename_table, i + 1));
+ }
+}
+
+
+/* Returns the icaltimezone from the component corresponding to the given
+ TZID, or NULL if the component does not have a corresponding VTIMEZONE. */
+icaltimezone* icalcomponent_get_timezone(icalcomponent* comp, const char *tzid)
+{
+ struct icalcomponent_impl *impl;
+ icaltimezone *zone;
+ int lower, upper, middle, cmp;
+
+ impl = (struct icalcomponent_impl*)comp;
+
+ /* Do a simple binary search. */
+ lower = middle = 0;
+ upper = impl->timezones->num_elements;
+
+ while (lower < upper) {
+ middle = (lower + upper) >> 1;
+ zone = icalarray_element_at (impl->timezones, middle);
+ cmp = strcmp (tzid, icaltimezone_get_tzid (zone));
+ if (cmp == 0)
+ return zone;
+ else if (cmp < 0)
+ upper = middle;
+ else
+ lower = middle + 1;
+ }
+
+ return NULL;
+}
+
diff --git a/libical/src/libical/icalrecur.c b/libical/src/libical/icalrecur.c
index 51fdf63a79..99ebf022f6 100644
--- a/libical/src/libical/icalrecur.c
+++ b/libical/src/libical/icalrecur.c
@@ -280,6 +280,8 @@ void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array,
} else if (*t == '+'){
sign = 1;
t++;
+ } else {
+ sign = 1;
}
v = atoi(t) * sign ;
@@ -904,7 +906,20 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
/* For YEARLY rule, begin by setting up the year days array */
if(impl->rule.freq == ICAL_YEARLY_RECURRENCE){
- expand_year_days(impl,impl->last.year);
+ struct icaltimetype next;
+
+ for (;;) {
+ expand_year_days(impl,impl->last.year);
+ if (impl->days[0] != ICAL_RECURRENCE_ARRAY_MAX)
+ break;
+ increment_year(impl,impl->rule.interval);
+ }
+
+ /* Copy the first day into last. */
+ next = icaltime_from_day_of_year(impl->days[0], impl->last.year);
+
+ impl->last.day = next.day;
+ impl->last.month = next.month;
}
@@ -1618,13 +1633,14 @@ int next_week(struct icalrecur_iterator_impl* impl)
}
+/* Expand the BYDAY rule part and return a pointer to a newly allocated list of days. */
pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
{
/* Try to calculate each of the occurrences. */
int i;
pvl_list days_list = pvl_newlist();
- short start_dow, end_dow, end_year_day, start_doy;
+ short start_dow, end_dow, end_year_day;
struct icaltimetype tmp = impl->last;
tmp.year= year;
@@ -1632,35 +1648,34 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
tmp.day = 1;
tmp.is_date = 1;
+ /* Find the day that 1st Jan falls on, 1 (Sun) to 7 (Sat). */
start_dow = icaltime_day_of_week(tmp);
- start_doy = icaltime_start_doy_of_week(tmp);
/* Get the last day of the year*/
- tmp.year++;
- tmp = icaltime_normalize(tmp);
- tmp.day--;
- tmp = icaltime_normalize(tmp);
-
+ tmp.year= year;
+ tmp.month = 12;
+ tmp.day = 31;
+ tmp.is_date = 1;
+
end_dow = icaltime_day_of_week(tmp);
end_year_day = icaltime_day_of_year(tmp);
-
+
for(i = 0; BYDAYPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
+ /* This is 1 (Sun) to 7 (Sat). */
short dow =
icalrecurrencetype_day_day_of_week(BYDAYPTR[i]);
short pos = icalrecurrencetype_day_position(BYDAYPTR[i]);
if(pos == 0){
- /* add all of the days of the year with this day-of-week*/
- int week;
- for(week = 0; week < 52 ; week ++){
- short doy = start_doy + (week * 7) + dow-1;
-
- if(doy > end_year_day){
- break;
- } else {
- pvl_push(days_list,(void*)(int)doy);
- }
- }
+ /* The day was specified without a position -- it is just
+ a bare day of the week ( BYDAY=SU) so add all of the
+ days of the year with this day-of-week*/
+ int doy, tmp_start_doy;
+
+ tmp_start_doy = ((dow + 7 - start_dow) % 7) + 1;
+
+ for (doy = tmp_start_doy; doy <= end_year_day; doy += 7)
+ pvl_push(days_list,(void*)(int)doy);
} else if ( pos > 0) {
int first;
@@ -1674,7 +1689,7 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
pvl_push(days_list,(void*)(first+ (pos-1) * 7));
} else { /* pos < 0 */
- assert(0);
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
}
}
@@ -1693,6 +1708,8 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
struct icaltimetype t;
int flags;
+ t = icaltime_null_time();
+
#define HBD(x) has_by_data(impl,x)
t.is_date = 1; /* Needed to make day_of_year routines work property */
@@ -1706,12 +1723,12 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
(HBD(BY_MONTH) ? 1<<BY_MONTH : 0) +
(HBD(BY_YEAR_DAY) ? 1<<BY_YEAR_DAY : 0);
-
+
switch(flags) {
-
+
case 0: {
/* FREQ=YEARLY; */
-
+
break;
}
case 1<<BY_MONTH: {
@@ -1737,7 +1754,21 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
case 1<<BY_MONTH_DAY: {
/* FREQ=YEARLY; BYMONTHDAY=1,15*/
- assert(0);
+ for(k=0;impl->by_ptrs[BY_MONTH_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++)
+ {
+ short month_day = impl->by_ptrs[BY_MONTH_DAY][k];
+ short doy;
+
+ t = impl->dtstart;
+ t.day = month_day;
+ t.year = year;
+ t.is_date = 1;
+
+ doy = icaltime_day_of_year(t);
+
+ impl->days[days_index++] = doy;
+
+ }
break;
}
@@ -1757,7 +1788,6 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
t.is_date = 1;
doy = icaltime_day_of_year(t);
-
impl->days[days_index++] = doy;
}
@@ -1779,13 +1809,15 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
dow = icaltime_day_of_week(t);
/* HACK Not finished */
+
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
break;
}
case (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): {
/*FREQ=YEARLY; WEEKNO=20,50; BYMONTH= 6,11 */
- assert(0);
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
break;
}
@@ -1801,6 +1833,8 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
impl->days[days_index++] = day;
}
+ pvl_free(days);
+
break;
}
@@ -1811,38 +1845,86 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
short month = impl->by_ptrs[BY_MONTH][j];
short days_in_month = icaltime_days_in_month(month,year);
+ short first_dow, last_dow, doy_offset;
struct icaltimetype t;
memset(&t,0,sizeof(struct icaltimetype));
- t.day = 1;
t.year = year;
t.month = month;
+ t.day = 1;
t.is_date = 1;
- for(t.day = 1; t.day <=days_in_month; t.day++){
-
- short current_dow = icaltime_day_of_week(t);
+ first_dow = icaltime_day_of_week(t);
+
+ /* This holds the day offset used to calculate the day of the year
+ from the month day. Just add the month day to this. */
+ doy_offset = icaltime_day_of_year(t) - 1;
- for(k=0;impl->by_ptrs[BY_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++){
-
- enum icalrecurrencetype_weekday dow =
- icalrecurrencetype_day_day_of_week(impl->by_ptrs[BY_DAY][k]);
-
- if(current_dow == dow){
- short doy = icaltime_day_of_year(t);
- /* HACK, incomplete Nth day of week handling */
- impl->days[days_index++] = doy;
-
- }
+ t.day = days_in_month;
+ last_dow = icaltime_day_of_week(t);
+
+ for(k=0;impl->by_ptrs[BY_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++){
+ short day_coded = impl->by_ptrs[BY_DAY][k];
+ enum icalrecurrencetype_weekday dow =
+ icalrecurrencetype_day_day_of_week(day_coded);
+ short pos = icalrecurrencetype_day_position(day_coded);
+ short first_matching_day, last_matching_day, day, month_day;
+
+ /* Calculate the first day in the month with the given weekday,
+ and the last day. */
+ first_matching_day = ((dow + 7 - first_dow) % 7) + 1;
+ last_matching_day = days_in_month - ((last_dow + 7 - dow) % 7);
+
+ if (pos == 0) {
+ /* Add all of instances of the weekday within the month. */
+ for (day = first_matching_day; day <= days_in_month; day += 7)
+ impl->days[days_index++] = doy_offset + day;
+
+ } else if (pos > 0) {
+ /* Add the nth instance of the weekday within the month. */
+ month_day = first_matching_day + (pos - 1) * 7;
+
+ if (month_day <= days_in_month)
+ impl->days[days_index++] = doy_offset + month_day;
+
+ } else {
+ /* Add the -nth instance of the weekday within the month.*/
+ month_day = last_matching_day + (pos + 1) * 7;
+
+ if (month_day > 0)
+ impl->days[days_index++] = doy_offset + month_day;
}
- }
+ }
}
break;
}
case (1<<BY_DAY) + (1<<BY_MONTH_DAY) : {
/*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=1,15*/
- assert(0);
+
+ int days_index = 0;
+ pvl_elem itr;
+ pvl_list days = expand_by_day(impl,year);
+
+ for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
+ short day = (short)(int)pvl_data(itr);
+ struct icaltimetype tt;
+ short i,j;
+
+ tt = icaltime_from_day_of_year(day,year);
+
+ for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
+ short mday = BYMDPTR[j];
+
+ if(tt.day == mday){
+ impl->days[days_index++] = day;
+ }
+ }
+
+ }
+
+ pvl_free(days);
+
break;
}
@@ -1873,6 +1955,8 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
}
+ pvl_free(days);
+
break;
}
@@ -1900,12 +1984,14 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
}
}
+
+ pvl_free(days);
break;
}
case (1<<BY_DAY) + (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): {
/*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; WEEKNO=20,50; BYMONTHDAY=1,15*/
- assert(0);
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
break;
}
@@ -1918,7 +2004,7 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
}
default: {
- assert(0);
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
break;
}
@@ -1938,8 +2024,13 @@ int next_year(struct icalrecur_iterator_impl* impl)
if (impl->days[++impl->days_index] == ICAL_RECURRENCE_ARRAY_MAX){
impl->days_index = 0;
- increment_year(impl,impl->rule.interval);
- expand_year_days(impl,impl->last.year);
+
+ for (;;) {
+ increment_year(impl,impl->rule.interval);
+ expand_year_days(impl,impl->last.year);
+ if (impl->days[0] != ICAL_RECURRENCE_ARRAY_MAX)
+ break;
+ }
}
next = icaltime_from_day_of_year(impl->days[impl->days_index],impl->last.year);
diff --git a/libical/src/libical/icaltime.c b/libical/src/libical/icaltime.c
index d5b228b089..6a3859c094 100644
--- a/libical/src/libical/icaltime.c
+++ b/libical/src/libical/icaltime.c
@@ -389,17 +389,19 @@ short icaltime_days_in_month(short month,short year)
/* 1-> Sunday, 7->Saturday */
short icaltime_day_of_week(struct icaltimetype t){
+ struct tm stm;
- time_t tt = icaltime_as_timet(t);
- struct tm *tm;
+ stm.tm_year = t.year - 1900;
+ stm.tm_mon = t.month - 1;
+ stm.tm_mday = t.day;
+ stm.tm_hour = 0;
+ stm.tm_min = 0;
+ stm.tm_sec = 0;
+ stm.tm_isdst = -1;
- if(t.is_utc == 1){
- tm = gmtime(&tt);
- } else {
- tm = localtime(&tt);
- }
+ mktime (&stm);
- return tm->tm_wday+1;
+ return stm.tm_wday + 1;
}
/* Day of the year that the first day of the week (Sunday) is on */
@@ -450,41 +452,49 @@ short icaltime_week_number(struct icaltimetype ictt)
short icaltime_day_of_year(struct icaltimetype t){
- time_t tt = icaltime_as_timet(t);
- struct tm *stm;
+ struct tm stm;
- if(t.is_utc==1){
- stm = gmtime(&tt);
- } else {
- stm = localtime(&tt);
- }
+ stm.tm_year = t.year - 1900;
+ stm.tm_mon = t.month - 1;
+ stm.tm_mday = t.day;
+ stm.tm_hour = 0;
+ stm.tm_min = 0;
+ stm.tm_sec = 0;
+ stm.tm_isdst = -1;
- return stm->tm_yday+1;
-
+ mktime (&stm);
+
+ return stm.tm_yday + 1;
}
/* Jan 1 is day #1, not 0 */
struct icaltimetype icaltime_from_day_of_year(short doy, short year)
{
- struct tm stm;
- time_t tt;
- char *old_tz = set_tz("UTC");
-
- /* Get the time of january 1 of this year*/
- memset(&stm,0,sizeof(struct tm));
- stm.tm_year = year-1900;
- stm.tm_mday = 1;
-
- tt = mktime(&stm);
- unset_tz(old_tz);
-
-
- /* Now add in the days */
-
- doy--;
- tt += doy *60*60*24;
+ static const short days_in_year[2][13] =
+ { /* jan feb mar apr may jun jul aug sep oct nov dec */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+ struct icaltimetype tt = { 0 };
+ int is_leap = 0, month;
+
+ tt.year = year;
+ if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
+ is_leap = 1;
+
+ assert(doy > 0);
+ assert(doy <= days_in_year[is_leap][12]);
+
+ for (month = 11; month >= 0; month--) {
+ if (doy > days_in_year[is_leap][month]) {
+ tt.month = month + 1;
+ tt.day = doy - days_in_year[is_leap][month];
+ return tt;
+ }
+ }
- return icaltime_from_timet(tt, 1);
+ /* Shouldn't reach here. */
+ assert (0);
}
struct icaltimetype icaltime_null_time()
@@ -564,3 +574,74 @@ struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
+/* Adds (or subtracts) a time from a icaltimetype.
+ NOTE: This function is exactly the same as icaltimezone_adjust_change()
+ except for the type of the first parameter. */
+void
+icaltime_adjust (struct icaltimetype *tt,
+ int days,
+ int hours,
+ int minutes,
+ int seconds)
+{
+ int second, minute, hour, day;
+ int minutes_overflow, hours_overflow, days_overflow;
+ int days_in_month;
+
+ /* Add on the seconds. */
+ second = tt->second + seconds;
+ tt->second = second % 60;
+ minutes_overflow = second / 60;
+ if (tt->second < 0) {
+ tt->second += 60;
+ minutes_overflow--;
+ }
+
+ /* Add on the minutes. */
+ minute = tt->minute + minutes + minutes_overflow;
+ tt->minute = minute % 60;
+ hours_overflow = minute / 60;
+ if (tt->minute < 0) {
+ tt->minute += 60;
+ hours_overflow--;
+ }
+
+ /* Add on the hours. */
+ hour = tt->hour + hours + hours_overflow;
+ tt->hour = hour % 24;
+ days_overflow = hour / 24;
+ if (tt->hour < 0) {
+ tt->hour += 24;
+ days_overflow--;
+ }
+
+ /* Add on the days. */
+ day = tt->day + days + days_overflow;
+ if (day > 0) {
+ for (;;) {
+ days_in_month = icaltime_days_in_month (tt->month, tt->year);
+ if (day <= days_in_month)
+ break;
+
+ tt->month++;
+ if (tt->month >= 13) {
+ tt->year++;
+ tt->month = 1;
+ }
+
+ day -= days_in_month;
+ }
+ } else {
+ while (day <= 0) {
+ if (tt->month == 1) {
+ tt->year--;
+ tt->month = 12;
+ } else {
+ tt->month--;
+ }
+
+ day += icaltime_days_in_month (tt->month, tt->year);
+ }
+ }
+ tt->day = day;
+}
diff --git a/libical/src/libical/icaltime.h b/libical/src/libical/icaltime.h
index 0f0379b76e..afe8fd4df2 100644
--- a/libical/src/libical/icaltime.h
+++ b/libical/src/libical/icaltime.h
@@ -41,8 +41,8 @@ struct icaltime_span {
struct icaltimetype
{
- int year;
- int month;
+ int year; /* Actual year, e.g. 2001. */
+ int month; /* 1 (Jan) to 12 (Dec). */
int day;
int hour;
int minute;
@@ -51,6 +51,8 @@ struct icaltimetype
int is_utc; /* 1-> time is in UTC timezone */
int is_date; /* 1 -> interpret this as date. */
+
+ int is_daylight; /* 1 -> time is in daylight savings time. */
const char* zone; /*Ptr to Olsen placename. Libical does not own mem*/
};
@@ -138,6 +140,9 @@ int icaltime_compare_date_only(struct icaltimetype a, struct icaltimetype b);
/* Return the number of days in the given month */
short icaltime_days_in_month(short month,short year);
+/* Adds or subtracts a number of days, hours, minutes and seconds. */
+void icaltime_adjust(struct icaltimetype *tt, int days, int hours,
+ int minutes, int seconds);
#endif /* !ICALTIME_H */
diff --git a/libical/src/libical/icalyacc.y b/libical/src/libical/icalyacc.y
index 982682d331..c78299fa2a 100644
--- a/libical/src/libical/icalyacc.y
+++ b/libical/src/libical/icalyacc.y
@@ -6,7 +6,7 @@
DESCRIPTION:
- $Id: icalyacc.y,v 1.11 2001/01/23 20:22:33 jpr Exp $
+ $Id: icalyacc.y,v 1.12 2001/06/14 02:50:46 damon Exp $
$Locker: $
(C) COPYRIGHT 1999 Eric Busboom
@@ -367,12 +367,12 @@ plusminus: '+' { utcsign = 1; }
utcoffset_value:
plusminus INTNUMBER INTNUMBER
{
- icalparser_yy_value = icalvalue_new_utcoffset( utcsign * ($2*3600) + ($3*60) );
+ icalparser_yy_value = icalvalue_new_utcoffset( utcsign * (($2*3600) + ($3*60)) );
}
| plusminus INTNUMBER INTNUMBER INTNUMBER
{
- icalparser_yy_value = icalvalue_new_utcoffset(utcsign * ($2*3600) + ($3*60) +($4));
+ icalparser_yy_value = icalvalue_new_utcoffset(utcsign * (($2*3600) + ($3*60) +($4)));
}
%%