[evolution-patches] Evolution Multi Calendar patch !
- From: Mohammad Reza Ghorbani <ghorbani bluehome net>
- To: evolution-hackers lists ximian com
- Cc: evolution-patches lists ximian com
- Subject: [evolution-patches] Evolution Multi Calendar patch !
- Date: Thu, 07 Jul 2005 19:26:36 +0430
Hello...
According to previous emails, We're on our way to make the evolution
compatible with multi calendar systems.
FIRST stable patch is ready now.
It'll take 2 more patches to achieve a multi calendar evolution.
Here, some notes about the patch(s) :
* Since, the evolution doesn't use a single backend to get date/time
(GDATE, icaltimetype, tm, time_t, etc) we were forced to change all time
layers and modules, in order to make them work with multi calendar
systems.
* We named the new function set, IMcal...IMprovedcal. New functions
are accessible from
'/evolution-data-server/calendar/libical/src/libical/'. Added routines
start with 'imcaltime*' prefix
* All added routines have a similar prototype to the original libical
functions, except that we add them a additional argument, which is a
'imcaltimeobj'. This type is used to improve flexibility of the new time
routines and contains some function pointers to time/date calculating
routines, according to IN-USE calendar system (like Gregorian, Jalali,
Hijri etc) which is declared in the structure. for more info on
'imcaltimeobj' see 'imcaltime.h'.
* Using 'imcaltimeobj' we're able to use calendar systems in two
order:
1) As a module, which is loaded with some shared library loading
library like libdl (Requires some fixes on Makefile).
2) As a Internal part of code.
* Currently there are two available calendars which is made as
module:
0) Gregorian : Default.
1) Jalali : Used in Iran.
2) Hijri : Mostly used in Arabic countries.
* We'll change the evolution with 3 different patches:
1)Patch on "libical", which contains our major multi calendar
routines. (data-server)
2)Next patch will be the "libecal". Uses independent, or libical
dependent routines. (data-server)
3)Finally, 3rd path is for the evolution client. (client)
Note: since, we've added some new files to data-server, we have NOT use
'cvs diff' to make the patch. The attached patch is created with
ordinary 'diff'.
diff -u -p -N evolution-data-server/calendar/libical/src/libical/Makefile.am evolution-data-server-wd/calendar/libical/src/libical/Makefile.am
--- evolution-data-server/calendar/libical/src/libical/Makefile.am 2005-07-05 19:24:13.000000000 +0430
+++ evolution-data-server-wd/calendar/libical/src/libical/Makefile.am 2005-07-05 20:09:37.000000000 +0430
@@ -53,6 +53,16 @@ libical_evolution_la_LDFLAGS = -version-
libical_evolution_la_SOURCES = \
$(BUILT_SOURCES) \
+ imcaltime.c \
+ imcaltime.h \
+ imcaltimeobj_gregorian.c \
+ imcaltimeobj_gregorian.h \
+ imcaltimeobj_hijri.c \
+ imcaltimeobj_hijri.h \
+ imcaltimeobj_jalali.c \
+ imcaltimeobj_jalali.h \
+ imcaltimezone.c \
+ imcaltimezone.h \
icalarray.c \
icalarray.h \
icalattach.h \
@@ -118,31 +128,37 @@ endif
libical_evolutionincludedir = $(privincludedir)/libical
libical_evolutioninclude_HEADERS = \
- ical.h \
- icalarray.h \
- icalattach.h \
- icalcomponent.h \
- icalderivedparameter.h \
- icalderivedproperty.h \
- icalderivedvalue.h \
- icalduration.h \
- icalenums.h \
- icalerror.h \
- icallangbind.h \
- icalmemory.h \
- icalmime.h \
- icalparameter.h \
- icalparser.h \
- icalperiod.h \
- icalproperty.h \
- icalrecur.h \
- icalrestriction.h \
- icaltime.h \
- icaltimezone.h \
- icaltypes.h \
- icalvalue.h \
- pvl.h \
- sspm.h \
+ ical.h \
+ icalarray.h \
+ icalattach.h \
+ icalcomponent.h \
+ icalderivedparameter.h \
+ icalderivedproperty.h \
+ icalderivedvalue.h \
+ icalduration.h \
+ icalenums.h \
+ icalerror.h \
+ icallangbind.h \
+ icalmemory.h \
+ icalmime.h \
+ icalparameter.h \
+ icalparser.h \
+ icalperiod.h \
+ icalproperty.h \
+ icalrecur.h \
+ icalrestriction.h \
+ icaltime.h \
+ icaltimezone.h \
+ icaltypes.h \
+ icalvalue.h \
+ imcaltime.c \
+ imcaltime.h \
+ imcaltimeobj_gregorian.h \
+ imcaltimeobj_hijri.h \
+ imcaltimeobj_jalali.h \
+ imcaltimezone.h \
+ pvl.h \
+ sspm.h \
$(cxx_headers)
# ORDERING OF HEADERS IS SIGNIFICANT. Don't change this ordering. It
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltime.c evolution-data-server-wd/calendar/libical/src/libical/imcaltime.c
--- evolution-data-server/calendar/libical/src/libical/imcaltime.c 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltime.c 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,1187 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: imcaltime.c
+ CREATOR: eric 02 June 2000
+
+ $Id: icaltime.c,v 1.34 2004/12/22 11:54:39 rodrigo Exp $
+ $Locker: $
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+ ======================================================================*/
+ /***********************************************************************
+ * @file imcaltime.c *
+ * *
+ * @This file contains some modified libical routines, which has been *
+ * added, in order to make it compatible with multi calendar purposes. *
+ ***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imcaltime.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "astime.h" /* Julian data handling routines */
+
+#include "icalerror.h"
+#include "icalmemory.h"
+
+#include "imcaltimezone.h"
+#include "icalvalue.h"
+
+#ifdef WIN32
+#include <Windows.h>
+
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#endif
+
+/*
+ * Function to convert a struct tm time specification
+ * to an ANSI time_t using the specified time zone.
+ * This is different from the standard mktime() function
+ * in that we dont want the automatic adjustments for
+ * local daylight savings time applied to the result.
+ * This function expects well-formed input.
+ */
+static time_t make_time(struct tm *tm, int tzm)
+{
+ time_t tim;
+ static int days[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
+
+ /* check that year specification within range */
+
+ if (tm->tm_year < 70 || tm->tm_year > 138)
+ return((time_t) -1);
+
+ /* check that month specification within range */
+
+ if (tm->tm_mon < 0 || tm->tm_mon > 11)
+ return((time_t) -1);
+
+ /* check for upper bound of Jan 17, 2038 (to avoid possibility of
+ 32-bit arithmetic overflow) */
+
+ if (tm->tm_year == 138) {
+ if (tm->tm_mon > 0)
+ return((time_t) -1);
+ else if (tm->tm_mday > 17)
+ return((time_t) -1);
+ }
+
+ /*
+ * calculate elapsed days since start of the epoch (midnight Jan
+ * 1st, 1970 UTC) 17 = number of leap years between 1900 and 1970
+ * (number of leap days to subtract)
+ */
+
+ tim = (tm->tm_year - 70) * 365 + ((tm->tm_year - 1) / 4) - 17;
+
+ /* add number of days elapsed in the current year */
+ tim += days[tm->tm_mon];
+
+ /* check and adjust for leap years (the leap year check only valid
+ during the 32-bit era */
+
+ if ((tm->tm_year & 3) == 0 && tm->tm_mon > 1)
+ tim += 1;
+
+ /* elapsed days to current date */
+
+ tim += tm->tm_mday;
+
+
+ /* calculate elapsed hours since start of the epoch */
+
+ tim = tim * 24 + tm->tm_hour;
+
+ /* calculate elapsed minutes since start of the epoch */
+
+ tim = tim * 60 + tm->tm_min;
+
+ /* adjust per time zone specification */
+
+ tim -= tzm;
+
+ /* calculate elapsed seconds since start of the epoch */
+
+ tim = tim * 60 + tm->tm_sec;
+
+ /* return number of seconds since start of the epoch */
+
+ return(tim);
+}
+
+/** @brief Constructor (deprecated).
+ *
+ * Convert seconds past UNIX epoch to a timetype.
+ *
+ * @deprecated This constructor is deprecated and shouldn't be used in
+ * new software. Use imcaltime_from_timet_with_zone(time_t, int,
+ * imcaltimezone *) instead. In the meantime, calls to this method
+ * return a floating time, which can always be converted to a local
+ * time with an appropriate call to imcaltime_convert_to_zone().
+ */
+
+struct icaltimetype
+imcaltime_from_timet(const time_t tm, const int is_date,
+ const struct imcaltimeobj *cal)
+{
+#ifndef NO_WARN_DEPRECATED
+ icalerror_warn("imcaltime_from_timet() is DEPRECATED, use imcaltime_from_timet_with_zone() instead");
+#endif
+
+ return imcaltime_from_timet_with_zone(tm, is_date, 0, cal);
+}
+
+
+/** @brief Constructor.
+ *
+ * @param tm The time
+ * @param is_date Boolean: 1 means we should treat tm as a DATE
+ * @param zone The timezone tm is in, NULL means to treat tm as a
+ * floating time
+ *
+ * Return a new imcaltime instance, initialized to the given time
+ * expressed as seconds past UNIX epoch, optionally using the given
+ * timezone.
+ *
+ * If the caller specifies the is_date param as TRUE, the returned
+ * object is of DATE type, otherwise the input is meant to be of
+ * DATE-TIME type.
+ * If the zone is not specified (NULL zone param) the time is taken
+ * to be floating, that is, valid in any timezone. Note that, in
+ * addition to the uses specified in [RFC2445], this can be used
+ * when doing simple math on couples of times.
+ * If the zone is specified (UTC or otherwise), it's stored in the
+ * object and it's used as the native timezone for this object.
+ * This means that the caller can convert this time to a different
+ * target timezone with no need to store the source timezone.
+ *
+ */
+struct icaltimetype
+imcaltime_from_timet_with_zone(const time_t tm, const int is_date,
+ const imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+ struct icaltimetype tt;
+ struct tm t;
+ imcaltimezone *utc_zone;
+ struct imcaldatetype dt;
+ utc_zone = imcaltimezone_get_utc_timezone ();
+
+ /* Convert the time_t to a struct tm in UTC time. We can trust gmtime
+ for this. */
+ t = *(gmtime(&tm));
+
+ /* IF NOT GREGORIAN , ... */
+ if ( NULL != cal->convert_to_cal_type ){
+ dt = cal->convert_to_cal_type(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);
+
+ tt.year = dt.year;
+ tt.month = dt.month;
+ tt.day = dt.day;
+ }
+ else{
+ tt.year = t.tm_year + 1900;
+ tt.month = t.tm_mon + 1;
+ tt.day = t.tm_mday;
+ }
+
+ tt.hour = t.tm_hour;
+ tt.minute = t.tm_min;
+ tt.second = t.tm_sec;
+ tt.is_date = 0;
+ tt.is_utc = (zone == utc_zone) ? 1 : 0;
+ tt.zone = NULL;
+ tt.is_daylight = 0;
+
+ /* Use our timezone functions to convert to the required timezone. */
+ imcaltimezone_convert_time (&tt, utc_zone, zone, cal);
+
+ tt.is_date = is_date;
+
+ /* If it is a DATE value, make sure hour, minute & second are 0. */
+ if (is_date) {
+ tt.hour = 0;
+ tt.minute = 0;
+ tt.second = 0;
+ }
+
+ return tt;
+}
+
+/** @brief Constructor.
+ *
+ * Returns an icaltimetype representing the current time in the given timezone.
+ */
+struct icaltimetype imcaltime_current_time_with_zone(const imcaltimezone *zone,
+ const struct imcaltimeobj *cal)
+{
+ return imcaltime_from_timet_with_zone (time (NULL), 0, zone, cal);
+}
+
+/** @brief Constructor.
+ *
+ * Returns an icaltimetype representing the current day.
+ */
+struct icaltimetype imcaltime_today(const struct imcaltimeobj *cal)
+{
+ return imcaltime_from_timet_with_zone (time (NULL), 1, NULL, cal);
+}
+
+/** @brief Return the time as seconds past the UNIX epoch
+ *
+ * While this function is not currently deprecated, it probably won't do
+ * what you expect, unless you know what you're doing. In particular, you
+ * should only pass an imcaltime in UTC, since no conversion is done. Even
+ * in that case, it's probably better to just use
+ * imcaltime_as_timet_with_zone().
+ */
+time_t imcaltime_as_timet(const struct icaltimetype tt, const struct imcaltimeobj *cal)
+{
+ struct tm stm;
+ time_t t;
+ struct imcaldatetype dt;
+
+ /* If the time is the special null time, return 0. */
+ if (imcaltime_is_null_time(tt)) {
+ return 0;
+ }
+
+ /* Copy the icaltimetype to a struct tm. */
+ memset (&stm, 0, sizeof (struct tm));
+
+ if (imcaltime_is_date(tt)) {
+ stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
+ } else {
+ stm.tm_sec = tt.second;
+ stm.tm_min = tt.minute;
+ stm.tm_hour = tt.hour;
+ }
+
+ if( NULL != cal -> convert_to_gregorian ){
+ dt = cal->convert_to_gregorian(tt.year, tt.month, tt.day);
+
+ stm.tm_mday = dt.day;
+ stm.tm_mon = dt.month-1;
+ stm.tm_year = dt.year-1900;
+ }
+ else{
+ stm.tm_mday = tt.day;
+ stm.tm_mon = tt.month-1;
+ stm.tm_year = tt.year-1900;
+ }
+
+ stm.tm_isdst = -1;
+
+ t = make_time(&stm, 0);
+
+ return t;
+
+}
+
+
+time_t imcaltime_as_timet_with_zone(const struct icaltimetype tt,
+ const imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+ imcaltimezone *utc_zone;
+ struct tm stm;
+ time_t t;
+ char *old_tz;
+ struct icaltimetype local_tt;
+ struct imcaldatetype dt;
+
+ utc_zone = imcaltimezone_get_utc_timezone ();
+
+ /* If the time is the special null time, return 0. */
+ if (imcaltime_is_null_time(tt)) {
+ return 0;
+ }
+
+ local_tt = tt;
+
+ /* Clear the is_date flag, so we can convert the time. */
+ local_tt.is_date = 0;
+
+ /* Use our timezone functions to convert to UTC. */
+ imcaltimezone_convert_time (&local_tt, zone, utc_zone, cal);
+
+ /* Copy the icaltimetype to a struct tm. */
+ memset (&stm, 0, sizeof (struct tm));
+
+ if( NULL != cal->convert_to_gregorian ){
+ dt = cal->convert_to_gregorian(local_tt.year, local_tt.month, local_tt.day);
+
+ local_tt.year = dt.year;
+ local_tt.month = dt.month;
+ local_tt.day = dt.day;
+ }
+
+ stm.tm_sec = local_tt.second;
+ stm.tm_min = local_tt.minute;
+ stm.tm_hour = local_tt.hour;
+ stm.tm_mday = local_tt.day;
+ stm.tm_mon = local_tt.month-1;
+ stm.tm_year = local_tt.year-1900;
+ stm.tm_isdst = -1;
+
+ /* Set TZ to UTC and use mktime to convert to a time_t. */
+ old_tz = set_tz ("UTC");
+ t = mktime (&stm);
+ unset_tz (old_tz);
+
+ return t;
+}
+
+/**
+ * Return a string represention of the time, in RFC2445 format. The
+ * string is owned by libical
+ */
+const char* imcaltime_as_ical_string(const struct icaltimetype tt)
+{
+ size_t size = 17;
+ char* buf = icalmemory_new_buffer(size);
+
+ if(tt.is_date){
+ snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
+ } else {
+ char* fmt;
+ if(tt.is_utc){
+ fmt = "%04d%02d%02dT%02d%02d%02dZ";
+ } else {
+ fmt = "%04d%02d%02dT%02d%02d%02d";
+ }
+ snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
+ tt.hour,tt.minute,tt.second);
+ }
+
+ icalmemory_add_tmp_buffer(buf);
+
+ return buf;
+
+}
+
+/**
+ * Reset all of the time components to be in their normal ranges. For
+ * instance, given a time with minutes=70, the minutes will be reduces
+ * to 10, and the hour incremented. This allows the caller to do
+ * arithmetic on times without worrying about overflow or
+ * underflow.
+ *
+ * Implementation note: we call imcaltime_adjust() with no adjustment.
+ */
+struct icaltimetype imcaltime_normalize(const struct icaltimetype tt, const struct imcaltimeobj *cal)
+{
+ struct icaltimetype ret = tt;
+ imcaltime_adjust(&ret, 0, 0, 0, 0, cal);
+ return ret;
+}
+
+
+
+/** @brief Contructor.
+ *
+ * Create a time from an ISO format string.
+ *
+ * @todo If the given string specifies a DATE-TIME not in UTC, there
+ * is no way to know if this is a floating time or really refers to a
+ * timezone. We should probably add a new constructor:
+ * imcaltime_from_string_with_zone()
+ */
+struct icaltimetype imcaltime_from_string(const char* str)
+{
+ struct icaltimetype tt = imcaltime_null_time();
+ int size;
+
+ icalerror_check_arg_re(str!=0,"str",imcaltime_null_time());
+
+ size = strlen(str);
+
+ if ((size == 15) || (size == 19)) { /* floating time with/without separators*/
+ tt.is_utc = 0;
+ tt.is_date = 0;
+ } else if ((size == 16) || (size == 20)) { /* UTC time, ends in 'Z'*/
+ if ((str[15] != 'Z') && (str[19] != 'Z'))
+ goto FAIL;
+
+ tt.is_utc = 1;
+ tt.zone = imcaltimezone_get_utc_timezone();
+ tt.is_date = 0;
+ } else if ((size == 8) || (size == 10)) { /* A DATE */
+ tt.is_utc = 0;
+ tt.is_date = 1;
+ } else { /* error */
+ goto FAIL;
+ }
+
+ if (tt.is_date == 1){
+ if (size == 10) {
+ char dsep1, dsep2;
+ if (sscanf(str,"%04d%c%02d%c%02d",&tt.year,&dsep1,&tt.month,&dsep2,&tt.day) < 5)
+ goto FAIL;
+ if ((dsep1 != '-') || (dsep2 != '-'))
+ goto FAIL;
+ } else if (sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day) < 3) {
+ goto FAIL;
+ }
+ } else {
+ if (size > 16 ) {
+ char dsep1, dsep2, tsep, tsep1, tsep2;
+ if (sscanf(str,"%04d%c%02d%c%02d%c%02d%c%02d%c%02d",&tt.year,&dsep1,&tt.month,&dsep2,
+ &tt.day,&tsep,&tt.hour,&tsep1,&tt.minute,&tsep2,&tt.second) < 11)
+ goto FAIL;
+
+ if((tsep != 'T') || (dsep1 != '-') || (dsep2 != '-') || (tsep1 != ':') || (tsep2 != ':'))
+ goto FAIL;
+
+ } else {
+ char tsep;
+ if (sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
+ &tsep,&tt.hour,&tt.minute,&tt.second) < 7)
+ goto FAIL;
+
+ if(tsep != 'T')
+ goto FAIL;
+ }
+ }
+
+ return tt;
+
+FAIL:
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return imcaltime_null_time();
+}
+
+
+/* Returns whether the specified year is a leap year. Year is the normal year,
+ e.g. 2001. */
+int
+imcaltime_is_leap_year (const int year, const struct imcaltimeobj *cal)
+{
+
+/* if (year <= 1752)
+ return (year % 4 == 0);
+ else
+ return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);*/
+
+ return cal->is_leap_year(year);
+}
+
+int imcaltime_days_in_month(const int month, const int year,const struct imcaltimeobj *cal)
+{
+
+ assert(month > 0);
+ assert(month <= 12);
+
+ return cal->days_in_month(month, year);
+}
+
+/* 1-> Sunday, 7->Saturday */
+/* TODO commnet */
+
+int imcaltime_day_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal){
+/* UTinstant jt;
+
+ memset(&jt,0,sizeof(UTinstant));
+
+ jt.year = t.year;
+ jt.month = t.month;
+ jt.day = t.day;
+ jt.i_hour = 0;
+ jt.i_minute = 0;
+ jt.i_second = 0;
+
+ juldat(&jt);
+
+ return jt.weekday + 1;*/
+ return cal->day_of_week(t.year, t.month, t.day) + 1;
+}
+
+/** Day of the year that the first day of the week (Sunday) is on.
+ */
+int imcaltime_start_doy_week(const struct icaltimetype t, int fdow,
+ const struct imcaltimeobj *cal){
+ /*UTinstant jt;
+ int delta;
+
+ memset(&jt,0,sizeof(UTinstant));
+
+ jt.year = t.year;
+ jt.month = t.month;
+ jt.day = t.day;
+ jt.i_hour = 0;
+ jt.i_minute = 0;
+ jt.i_second = 0;
+
+ juldat(&jt);
+ caldat(&jt);
+
+ delta = jt.weekday - (fdow - 1);
+ if (delta < 0) delta += 7;
+ return jt.day_of_year - delta;*/
+ int delta;
+
+ delta = imcaltime_day_of_week(t, cal) - (fdow + 1);
+ if (delta < 0) delta += 7;
+ return imcaltime_day_of_year(t, cal) - delta;
+}
+
+/** Day of the year that the first day of the week (Sunday) is on.
+ *
+ * @deprecated Doesn't take into account different week start days.
+ */
+int imcaltime_start_doy_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal){
+
+#ifndef NO_WARN_DEPRECATED
+ icalerror_warn("imcaltime_start_doy_of_week() is DEPRECATED, use\
+ imcaltime_start_doy_week() instead");
+#endif
+
+ return imcaltime_start_doy_week(t, 1, cal);
+}
+
+/**
+ * @todo Doesn't take into account the start day of the
+ * week. strftime assumes that weeks start on Monday.
+ */
+int imcaltime_week_number(const struct icaltimetype ictt, const struct imcaltimeobj *cal)
+{
+ /*UTinstant jt;
+
+ memset(&jt,0,sizeof(UTinstant));
+
+ jt.year = ictt.year;
+ jt.month = ictt.month;
+ jt.day = ictt.day;
+ jt.i_hour = 0;
+ jt.i_minute = 0;
+ jt.i_second = 0;
+
+ juldat(&jt, cal);
+ caldat(&jt, cal);
+
+ return (jt.day_of_year - jt.weekday) / 7;*/
+
+ return (( imcaltime_day_of_year(ictt, cal) - imcaltime_day_of_week(ictt, cal) ) / 7) + 1;
+}
+
+/**
+ * Returns the day of the year, counting from 1 (Jan 1st).
+ * FIXME handel UTC
+ */
+int imcaltime_day_of_year(const struct icaltimetype t, const struct imcaltimeobj *cal)
+{
+
+ return cal->day_of_year(t.year, t.month, t.day);
+}
+
+/** @brief Contructor.
+ *
+ * Create a new time, given a day of year and a year.
+ */
+/* Jan 1 is day #1, not 0 */
+struct icaltimetype imcaltime_from_day_of_year(const int _doy, const int _year,
+ const struct imcaltimeobj *cal)
+{
+ struct icaltimetype tt = imcaltime_null_date();
+ int is_leap;
+ int month;
+ int doy = _doy;
+ int year = _year;
+
+ is_leap = imcaltime_is_leap_year(year, cal);
+
+ /* Zero and neg numbers represent days of the previous year */
+ if(doy <1){
+ year--;
+ is_leap = imcaltime_is_leap_year(year, cal);
+ doy += cal->day_of_year(year, 12, 0);
+ } else if(doy > cal->day_of_year(year, 12, 0)){
+ /* Move on to the next year*/
+ is_leap = imcaltime_is_leap_year(year, cal);
+ doy -= cal->day_of_year(year, 12, 0);
+ year++;
+ }
+
+ tt.year = year;
+
+ for (month = 11; month >= 0; month--) {
+ if (doy > cal->day_of_year(year, month, 0)) {
+ tt.month = month + 1;
+ tt.day = doy - cal->day_of_year(year, month, 0);
+ break;
+ }
+ }
+
+ return tt;
+}
+
+/** @brief Constructor.
+ *
+ * Return a null time, which is guaranteed not to be equal to any other time.
+ */
+struct icaltimetype imcaltime_null_time(void)
+{
+ struct icaltimetype t;
+ memset(&t,0,sizeof(struct icaltimetype));
+
+ return t;
+}
+
+/** @brief Constructor.
+ *
+ * Return a null date.
+ */
+struct icaltimetype imcaltime_null_date(void)
+{
+ struct icaltimetype t;
+ memset(&t,0,sizeof(struct icaltimetype));
+
+ t.is_date = 1;
+
+ /*
+ * Init to -1 to match what icalyacc.y used to do.
+ * Does anything depend on this?
+ */
+ t.hour = -1;
+ t.minute = -1;
+ t.second = -1;
+
+ return t;
+}
+
+
+/**
+ * Returns false if the time is clearly invalid, but is not null. This
+ * is usually the result of creating a new time type buy not clearing
+ * it, or setting one of the flags to an illegal value.
+ */
+int imcaltime_is_valid_time(const struct icaltimetype t){
+ if(t.is_utc > 1 || t.is_utc < 0 ||
+ t.year < 0 || t.year > 3000 ||
+ t.is_date > 1 || t.is_date < 0){
+ return 0;
+ } else {
+ return 1;
+ }
+
+}
+
+/** @brief Returns true if time is a DATE
+ */
+int imcaltime_is_date(const struct icaltimetype t) {
+
+ return t.is_date;
+}
+
+/** @brief Returns true if time is relative to UTC zone
+ *
+ * @todo We should only check the zone
+ */
+int imcaltime_is_utc(const struct icaltimetype t) {
+
+ return t.is_utc;
+}
+
+/**
+ * Return true if the time is null.
+ */
+int imcaltime_is_null_time(const struct icaltimetype t)
+{
+ if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
+ return 1;
+ }
+
+ return 0;
+
+}
+
+/**
+ * Return -1, 0, or 1 to indicate that a<b, a==b, or a>b.
+ * This calls imcaltime_compare function after converting them to the utc
+ * timezone.
+ */
+
+int imcaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in,
+ const struct imcaltimeobj *cal)
+{
+ int retval = 0;
+ struct icaltimetype a, b;
+
+ a = imcaltime_convert_to_zone(a_in, imcaltimezone_get_utc_timezone(), cal);
+ b = imcaltime_convert_to_zone(b_in, imcaltimezone_get_utc_timezone(), cal);
+
+ if (a.year > b.year)
+ retval = 1;
+ else if (a.year < b.year)
+ retval = -1;
+
+ else if (a.month > b.month)
+ retval = 1;
+ else if (a.month < b.month)
+ retval = -1;
+
+ else if (a.day > b.day)
+ retval = 1;
+ else if (a.day < b.day)
+ retval = -1;
+
+ /* if both are dates, we are done */
+ if (a.is_date && b.is_date)
+ return retval;
+
+ /* else, if we already found a difference, we are done */
+ else if (retval != 0)
+ return retval;
+
+ /* else, if only one is a date (and we already know the date part is equal),
+ then the other is greater */
+ else if (b.is_date)
+ retval = 1;
+ else if (a.is_date)
+ retval = -1;
+
+ else if (a.hour > b.hour)
+ retval = 1;
+ else if (a.hour < b.hour)
+ retval = -1;
+
+ else if (a.minute > b.minute)
+ retval = 1;
+ else if (a.minute < b.minute)
+ retval = -1;
+
+ else if (a.second > b.second)
+ retval = 1;
+ else if (a.second < b.second)
+ retval = -1;
+
+ return retval;
+}
+
+/**
+ * like imcaltime_compare, but only use the date parts.
+ */
+
+int
+imcaltime_compare_date_only(const struct icaltimetype a_in, const struct icaltimetype b_in,
+ const struct imcaltimeobj *cal)
+{
+ int retval;
+ struct icaltimetype a, b;
+
+ a = imcaltime_convert_to_zone(a_in, imcaltimezone_get_utc_timezone(), cal);
+ b = imcaltime_convert_to_zone(b_in, imcaltimezone_get_utc_timezone(), cal);
+
+ if (a.year > b.year)
+ retval = 1;
+ else if (a.year < b.year)
+ retval = -1;
+
+ else if (a.month > b.month)
+ retval = 1;
+ else if (a.month < b.month)
+ retval = -1;
+
+ else if (a.day > b.day)
+ retval = 1;
+ else if (a.day < b.day)
+ retval = -1;
+
+ else
+ retval = 0;
+
+ return retval;
+}
+
+/* These are defined in icalduration.c:
+struct icaltimetype imcaltime_add(struct icaltimetype t,
+ struct icaldurationtype d)
+struct icaldurationtype imcaltime_subtract(struct icaltimetype t1,
+ struct icaltimetype t2)
+*/
+
+
+
+/** @brief Internal, shouldn't be part of the public API
+ *
+ * Adds (or subtracts) a time from a icaltimetype.
+ * NOTE: This function is exactly the same as imcaltimezone_adjust_change()
+ * except for the type of the first parameter.
+ */
+void
+imcaltime_adjust(struct icaltimetype *tt, const int days, const int hours,
+ const int minutes, const int seconds, const struct imcaltimeobj *cal) {
+
+ int second, minute, hour, day;
+ int minutes_overflow, hours_overflow, days_overflow = 0, years_overflow;
+ int days_in_month;
+
+ /* If we are passed a date make sure to ignore hour minute and second */
+ if (tt->is_date)
+ goto IS_DATE;
+
+ /* 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--;
+ }
+
+IS_DATE:
+ /* Normalize the month. We do this before handling the day since we may
+ need to know what month it is to get the number of days in it.
+ Note that months are 1 to 12, so we have to be a bit careful. */
+ if (tt->month >= 13) {
+ years_overflow = (tt->month - 1) / 12;
+ tt->year += years_overflow;
+ tt->month -= years_overflow * 12;
+ } else if (tt->month <= 0) {
+ /* 0 to -11 is -1 year out, -12 to -23 is -2 years. */
+ years_overflow = (tt->month / 12) - 1;
+ tt->year += years_overflow;
+ tt->month -= years_overflow * 12;
+ }
+
+ /* Add on the days. */
+ day = tt->day + days + days_overflow;
+ if (day > 0) {
+ for (;;) {
+ days_in_month = imcaltime_days_in_month (tt->month, tt->year, cal);
+ 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 += imcaltime_days_in_month (tt->month, tt->year, cal);
+ }
+ }
+ tt->day = day;
+}
+
+/** @brief Convert time to a given timezone
+ *
+ * Convert a time from its native timezone to a given timezone.
+ *
+ * If tt is a date, the returned time is an exact
+ * copy of the input. If it's a floating time, the returned object
+ * represents the same time translated to the given timezone.
+ * Otherwise the time will be converted to the new
+ * time zone, and its native timezone set to the right timezone.
+ */
+struct icaltimetype imcaltime_convert_to_zone(const struct icaltimetype tt,
+ imcaltimezone *zone,
+ const struct imcaltimeobj *cal) {
+
+ struct icaltimetype ret = tt;
+
+ /* If it's a date do nothing */
+ if (tt.is_date) {
+ return ret;
+ }
+
+ if (tt.zone == zone) {
+ return ret;
+ }
+
+ /* If it's a floating time we don't want to adjust the time */
+ if (tt.zone != NULL) {
+ imcaltimezone_convert_time(&ret, tt.zone, zone, cal);
+ }
+
+ ret.zone = zone;
+ if (zone == imcaltimezone_get_utc_timezone()) {
+ ret.is_utc = 1;
+ } else {
+ ret.is_utc = 0;
+ }
+
+ return ret;
+}
+
+const imcaltimezone *
+imcaltime_get_timezone(const struct icaltimetype t) {
+
+ return t.zone;
+}
+
+char *
+imcaltime_get_tzid(const struct icaltimetype t, const struct imcaltimeobj *cal) {
+
+ if (t.zone != NULL) {
+ return imcaltimezone_get_tzid(t.zone, cal);
+ } else {
+ return NULL;
+ }
+}
+
+/** @brief Set the timezone
+ *
+ * Force the imcaltime to be interpreted relative to another timezone.
+ * If you need to do timezone conversion, applying offset adjustments,
+ * then you should use imcaltime_convert_to_timezone instead.
+ */
+struct icaltimetype
+imcaltime_set_timezone(struct icaltimetype *t, const imcaltimezone *zone) {
+
+ /* If it's a date do nothing */
+ if (t->is_date) {
+ return *t;
+ }
+
+ if (t->zone == zone) {
+ return *t;
+ }
+
+ t->zone = zone;
+ if (zone == imcaltimezone_get_utc_timezone()) {
+ t->is_utc = 1;
+ } else {
+ t->is_utc = 0;
+ }
+
+ return *t;
+}
+
+
+/**
+ * @brief builds an imcaltimespan given a start time, end time and busy value.
+ *
+ * @param dtstart The beginning time of the span, can be a date-time
+ * or just a date.
+ * @param dtend The end time of the span.
+ * @param is_busy A boolean value, 0/1.
+ * @return A span using the supplied values.
+ *
+ * returned span contains times specified in UTC.
+ */
+
+imcaltime_span imcaltime_span_new(struct icaltimetype dtstart,
+ struct icaltimetype dtend,
+ int is_busy,
+ const struct imcaltimeobj *cal)
+{
+ imcaltime_span span;
+
+ span.is_busy = is_busy;
+
+ span.start = imcaltime_as_timet_with_zone(dtstart,
+ imcaltimezone_get_utc_timezone(),
+ cal);
+
+ if (imcaltime_is_null_time(dtend)) {
+ if (!imcaltime_is_date(dtstart)) {
+ /* If dtstart is a DATE-TIME and there is no DTEND nor DURATION
+ it takes no time */
+ span.end = span.start;
+ return span;
+ } else {
+ dtend = dtstart;
+ }
+ }
+
+ span.end = imcaltime_as_timet_with_zone(dtend, imcaltimezone_get_utc_timezone(), cal);
+
+ if (imcaltime_is_date(dtstart)) {
+ /* no time specified, go until the end of the day..*/
+ span.end += 60*60*24 - 1;
+ }
+ return span;
+}
+
+
+/** @brief Returns true if the two spans overlap
+ *
+ * @param s1 1st span to test
+ * @param s2 2nd span to test
+ * @return boolean value
+ *
+ * The result is calculated by testing if the start time of s1 is contained
+ * by the s2 span, or if the end time of s1 is contained by the s2 span.
+ *
+ * Also returns true if the spans are equal.
+ *
+ * Note, this will return false if the spans are adjacent.
+ */
+
+int imcaltime_span_overlaps(imcaltime_span *s1,
+ imcaltime_span *s2)
+{
+ /* s1->start in s2 */
+ if (s1->start > s2->start && s1->start < s2->end)
+ return 1;
+
+ /* s1->end in s2 */
+ if (s1->end > s2->start && s1->end < s2->end)
+ return 1;
+
+ /* s2->start in s1 */
+ if (s2->start > s1->start && s2->start < s1->end)
+ return 1;
+
+ /* s2->end in s1 */
+ if (s2->end > s1->start && s2->end < s1->end)
+ return 1;
+
+ if (s1->start == s2->start && s1->end == s2->end)
+ return 1;
+
+ return 0;
+}
+
+/** @brief Returns true if the span is totally within the containing
+ * span
+ *
+ * @param s The span to test for.
+ * @param container The span to test against.
+ * @return boolean value.
+ *
+ */
+
+int imcaltime_span_contains(imcaltime_span *s,
+ imcaltime_span *container)
+{
+
+ if ((s->start >= container->start && s->start < container->end) &&
+ (s->end <= container->end && s->end > container->start))
+ return 1;
+
+ return 0;
+}
+
+/* Gets a pointer to imcaltimeobj, and then set callbacks in two order:
+ *
+ * #ifdef MODULE then :
+ * loads the 'cal_type'.so in currnet directory.
+ * #else
+ * calls corespondent functions internally:
+ * jalali_loader() OR hijri_loader OR gregorian_loader
+ *
+ * NOTE: Addition of some other calendar types, is possible,
+ * by creating a object file containing whole callbacks in icaltimeobj structure.
+ * for a instance of a such file see, "imcaltimeobj_jalali.c"
+ *
+ */
+int imcaltime_init(const char *cal_type, const struct imcaltimeobj *cal)
+{
+ char *module_path;
+ char path[] = ".";
+ char *error;
+ void *handle;
+ void (*loader)(void *);
+
+#ifdef MODULES
+
+ if( strcmp(GREGORIAN ,cal_type) ){
+ /* allocates memory for name of the module */
+ module_path = (char *) icalmemory_new_buffer(strlen(path) + strlen(cal_type) + 5)
+ snprintf(module_path,strlen (module_path), "%s/%s.so", path, cal_type);
+
+ handle = dlopen (module_path, RTLD_LAZY);
+ if (!handle) {
+ fprintf (stderr, "%s\n", dlerror());
+ return (1);
+ }
+
+ icalmemory_free_buffer((void*) module_path) /* frees the allocated buffer */
+ dlerror(); /* Clear any existing error */
+
+
+ strncpy(cal -> cal_type, cal_type, MAX_CAL_NAME);
+
+ cal -> convert_to_cal_type = dlsym(handle, "convert_to_cal_type" );
+ cal -> convert_to_gregorian = dlsym(handle, "convert_to_gregorian");
+ cal -> day_in_the_year = dlsym(handle, "day_in_the_year");
+ cal -> day_of_week = dlsym(handle, "day_of_week");
+ cal -> day_in_the_month = dlsym(handle, "day_in_the_month");
+ cal -> is_leap_year = dlsym(handle, "is_leap_year");
+
+ if ((error = dlerror()) != NULL) {
+ fprintf (stderr, "%s\n", error);
+ return (1);
+ }
+ }else{
+ strncpy(cal -> cal_type, cal_type, MAX_CAL_NAME);
+ cal -> convert_to_cal_type = NULL;
+ cal -> convert_to_gregorian = NULL;
+ cal -> day_in_the_year = gregorian_day_in_year;
+ cal -> day_in_the_month = gregorian_day_in_month;
+ cal -> is_leap_year = gregorian_is_leap_year;
+
+ }
+
+#else
+ if( !strcmp(JALALI, cal_type) )
+ jalaly_loader(cal);
+
+ else if( !strcmp(GREGORIAN, cal_type) )
+ gregorian_loader(cal);
+
+ else if( !strcmp(HIJRI, cal_type) )
+ hijri_loader(cal);
+
+#endif
+}
+
+void * icaltimetype_to_icaltimetype(struct icaltimetype *src, struct icaltimetype *dest){
+ return memcpy(dest, src, sizeof(struct icaltimetype));
+}
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltime.h evolution-data-server-wd/calendar/libical/src/libical/imcaltime.h
--- evolution-data-server/calendar/libical/src/libical/imcaltime.h 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltime.h 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,325 @@
+
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: imcaltime.c
+ CREATOR: eric 02 June 2000
+
+ $Id: icaltime.c,v 1.34 2004/12/22 11:54:39 rodrigo Exp $
+ $Locker: $
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+ ======================================================================*/
+/** @file imcaltime.h
+ * @brief struct icaltimetype is a pseudo-object that abstracts time
+ * handling.
+ *
+ * It can represent either a DATE or a DATE-TIME (floating, UTC or in a
+ * given timezone), and it keeps track internally of its native timezone.
+ *
+ * The typical usage is to call the correct constructor specifying the
+ * desired timezone. If this is not known until a later time, the
+ * correct behavior is to specify a NULL timezone and call
+ * imcaltime_convert_to_zone() at a later time.
+ *
+ * There are several ways to create a new icaltimetype:
+ *
+ * - imcaltime_null_time()
+ * - imcaltime_null_date()
+ * - imcaltime_current_time_with_zone()
+ * - imcaltime_today()
+ * - imcaltime_from_timet_with_zone
+ * - imcaltime_from_string_with_zone
+ * - imcaltime_from_day_of_year
+ * - imcaltime_from_week_number
+ *
+ * italtimetype objects can be converted to different formats:
+ *
+ * - imcaltime_as_timet
+ * - imcaltime_as_timet_with_zone
+ * - imcaltime_as_ical_string
+ *
+ * Accessor methods include:
+ *
+ * - imcaltime_get_timezone
+ * - imcaltime_get_tzid
+ * - imcaltime_set_timezone
+ * - imcaltime_day_of_year
+ * - imcaltime_day_of_week
+ * - imcaltime_start_doy_week
+ * - imcaltime_week_number
+ *
+ * Query methods include:
+ *
+ * - imcaltime_is_null_time
+ * - imcaltime_is_valid_time
+ * - imcaltime_is_date
+ * - imcaltime_is_utc
+ * - imcaltime_is_floating
+ *
+ * Modify, compare and utility methods include:
+ *
+ * - imcaltime_add
+ * - imcaltime_subtract
+ * - imcaltime_compare_with_zone
+ * - imcaltime_compare
+ * - imcaltime_compare_date_only
+ * - imcaltime_adjust
+ * - imcaltime_normalize
+ * - imcaltime_convert_to_zone
+ */
+
+#ifndef imcaltime_H
+#define imcaltime_H
+
+#include <time.h>
+#include "icaltime.h"
+
+/* An opaque struct representing a timezone. We declare this here to avoid
+ a circular dependancy. */
+#ifndef imcaltimeZONE_DEFINED
+#define imcaltimeZONE_DEFINED
+typedef struct _imcaltimezone imcaltimezone;
+#endif
+
+
+#include <dlfcn.h> /* for module handling routins */
+
+#ifndef JALALI
+ #define JALALI "jalali" /* Iranian calendar system */
+#endif
+#ifndef HIJRI
+ #define HIJRI "hijri" /* Mostly used in Arabic countries */
+#endif
+#ifndef GREGORIAN
+ #define GREGORIAN "gregorian" /* The Julian calendar */
+
+/* NOTICE : we use gregorian routines (instead of libical internal routines)
+ * temporarly. In near future we'll make it work with the main
+ * functions. :D
+ */
+
+#endif
+#define MAX_CAL_NAME 16 /* MAXIMUM LENGHT OF CALENDAR NAME WE USE */
+
+/** imcaltime_span is returned by icalcomponent_get_span() */
+struct imcaltime_span {
+ time_t start; /**< in UTC */
+ time_t end; /**< in UTC */
+ int is_busy; /**< 1->busy time, 0-> free time */
+};
+
+typedef struct imcaltime_span imcaltime_span;
+
+/*
+ * FIXME
+ *
+ * is_utc is redundant, and might be considered a minor optimization.
+ * It might be deprecated, so you should use imcaltime_is_utc() instead.
+ */
+
+/* Return type of our date convertor routines */
+struct imcaldatetype{
+ int year;
+ int month;
+ int day;
+};
+
+typedef struct imcaldatetype imcaldatetype;
+
+/* Main object used in imcaltime routines, to handle multi calendar systems.
+ *
+ * cal_type: Holds preferd calendar type.
+ *
+ * convert_to_cal_type: Gets year, month and day in gregorian,
+ * and convert them to preferd calendar
+ * system, according to cal_type.
+ *
+ * convert_to_gregorian: gets year, month and day (non-gregorian),
+ * and convert them to gregorian.
+ *
+ * days_in_month: Returns days in a given month (handles leap years internally).
+ *
+ * day_of_year: Returns day of the year, using given year, month and day,
+ * which handles leap years automatically.
+ *
+ * day_of_week: Returns day of week.
+ *
+ * is_leap_year: True, if we're on a leap year!
+ */
+
+struct imcaltimeobj{
+ const char cal_type[16];
+
+ imcaldatetype (* convert_to_cal_type )(int year, int month, int day);
+ imcaldatetype (* convert_to_gregorian)(int year, int month, int day);
+
+ int (* days_in_month)(const int year, const int month);
+ int (* day_of_year )(const int year, const int month, const int day);
+ int (* day_of_week )(const int year, const int month, const int day);
+ int (* is_leap_year )(const int year);
+};
+
+typedef struct imcaltimeobj imcaltimeobj;
+
+/** Gets a pointer to imcaltimeobj, and then set callbacks. */
+int imcaltime_init(const char *cal_type, const struct imcaltimeobj *cal);
+
+/** Return a null time, which indicates no time has been set.
+ This time represent the beginning of the epoch */
+struct icaltimetype imcaltime_null_time(void);
+
+/** Return a null date */
+struct icaltimetype imcaltime_null_date(void);
+
+/** Returns the current time in the given timezone, as an icaltimetype. */
+struct icaltimetype imcaltime_current_time_with_zone(const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Returns the current day as an icaltimetype, with is_date set. */
+struct icaltimetype imcaltime_today(const struct imcaltimeobj *cal);
+
+/** Convert seconds past UNIX epoch to a timetype*/
+struct icaltimetype imcaltime_from_timet(const time_t v, const int is_date,const struct imcaltimeobj *cal);
+
+/** Convert seconds past UNIX epoch to a timetype, using timezones. */
+struct icaltimetype imcaltime_from_timet_with_zone(const time_t tm,
+ const int is_date, const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** create a time from an ISO format string */
+struct icaltimetype imcaltime_from_string(const char* str);
+
+/** create a time from an ISO format string */
+struct icaltimetype imcaltime_from_string_with_zone(const char* str,
+ const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Create a new time, given a day of year and a year. */
+struct icaltimetype imcaltime_from_day_of_year(const int doy,
+ const int year,const struct imcaltimeobj *cal);
+
+/** @brief Contructor (TODO).
+ * Create a new time from a weeknumber and a year. */
+struct icaltimetype imcaltime_from_week_number(const int week_number,
+ const int year);
+
+/** Return the time as seconds past the UNIX epoch */
+time_t imcaltime_as_timet(const struct icaltimetype, const struct imcaltimeobj *cal);
+
+/** Return the time as seconds past the UNIX epoch, using timezones. */
+time_t imcaltime_as_timet_with_zone(const struct icaltimetype tt,
+ const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Return a string represention of the time, in RFC2445 format. The
+ string is owned by libical */
+const char* imcaltime_as_ical_string(const struct icaltimetype tt);
+
+/** @brief Return the timezone */
+const imcaltimezone *imcaltime_get_timezone(const struct icaltimetype t);
+
+/** @brief Return the tzid, or NULL for a floating time */
+char *imcaltime_get_tzid(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** @brief Set the timezone */
+struct icaltimetype imcaltime_set_timezone(struct icaltimetype *t,
+ const imcaltimezone *zone);
+
+/** Return the day of the year of the given time */
+int imcaltime_day_of_year(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return the day of the week of the given time. Sunday is 1 */
+int imcaltime_day_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return the day of the year for the Sunday of the week that the
+ given time is within. */
+int imcaltime_start_doy_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return the day of the year for the first day of the week that the
+ given time is within. */
+int imcaltime_start_doy_week(const struct icaltimetype t, int fdow, const struct imcaltimeobj *cal);
+
+/** Return the week number for the week the given time is within */
+int imcaltime_week_number(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return true of the time is null. */
+int imcaltime_is_null_time(const struct icaltimetype t);
+
+/** Returns false if the time is clearly invalid, but is not null. This
+ is usually the result of creating a new time type buy not clearing
+ it, or setting one of the flags to an illegal value. */
+int imcaltime_is_valid_time(const struct icaltimetype t);
+
+/** @brief Returns true if time is of DATE type, false if DATE-TIME */
+int imcaltime_is_date(const struct icaltimetype t);
+
+/** @brief Returns true if time is relative to UTC zone */
+int imcaltime_is_utc(const struct icaltimetype t);
+
+/** @brief Returns true if time is a floating time */
+int imcaltime_is_floating(const struct icaltimetype t);
+
+/** Return -1, 0, or 1 to indicate that a<b, a==b or a>b */
+int imcaltime_compare_with_zone(const struct icaltimetype a,
+ const struct icaltimetype b);
+
+/** Return -1, 0, or 1 to indicate that a<b, a==b or a>b */
+int imcaltime_compare(const struct icaltimetype a,
+ const struct icaltimetype b, const struct imcaltimeobj *cal);
+
+/** like imcaltime_compare, but only use the date parts. */
+int imcaltime_compare_date_only(const struct icaltimetype a,
+ const struct icaltimetype b, const struct imcaltimeobj *cal);
+
+/** Adds or subtracts a number of days, hours, minutes and seconds. */
+void imcaltime_adjust(struct icaltimetype *tt, const int days,
+ const int hours, const int minutes, const int seconds, const struct imcaltimeobj *cal);
+
+/** Normalize the imcaltime, so that all fields are within the normal range. */
+struct icaltimetype imcaltime_normalize(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** convert tt, of timezone tzid, into a utc time. Does nothing if the
+ time is already UTC. */
+struct icaltimetype imcaltime_convert_to_zone(const struct icaltimetype tt,
+ imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Return the number of days in the given month */
+int imcaltime_days_in_month(const int month, const int year, const struct imcaltimeobj *cal);
+
+
+/** @brief calculate an imcaltimespan given a start and end time. */
+struct imcaltime_span imcaltime_span_new(struct icaltimetype dtstart,
+ struct icaltimetype dtend,
+ int is_busy,
+ const struct imcaltimeobj *cal);
+
+/** @brief Returns true if the two spans overlap **/
+int imcaltime_span_overlaps(imcaltime_span *s1,
+ imcaltime_span *s2);
+
+/** @brief Returns true if the span is totally within the containing
+ * span
+ */
+int imcaltime_span_contains(imcaltime_span *s,
+ imcaltime_span *container);
+
+
+
+#endif /* !imcaltime_H */
+
+
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.c 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.c 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,190 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_gregorian.c
+ CREATOR: Bagher Fathi fathi yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2001, Damon Chaplin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+
+======================================================================*/
+
+#include "imcaltimeobj_gregorian.h"
+#include "imcaltime.h"
+#include "astime.h"
+#include "assert.h"
+
+
+struct imcaldatetype gregorianDate (long gregorianDaysNo)
+{
+
+ int gregorianMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ struct imcaldatetype h;
+ int gregorianYear, gregorianMonth, gregorianDay;
+ int leap;
+ int i;
+
+ gregorianYear = 1600 + 400 * (div ((int) gregorianDaysNo, (int) 146097).quot);
+ gregorianDaysNo = gregorianDaysNo % 146097;
+
+ if (gregorianDaysNo >= 36524)
+ {
+ gregorianYear += 100 * (div ((int) gregorianDaysNo, (int) 36524).quot);
+ gregorianDaysNo = gregorianDaysNo % 36524;
+ }
+
+ gregorianYear += 4 * (div ((int) gregorianDaysNo, (int) 1461).quot);
+ gregorianDaysNo %= 1461;
+ leap = 0;
+
+ if (gregorianDaysNo <= 365 && gregorianDaysNo != 0)
+ {
+ leap = 1;
+ }
+
+ else if (gregorianDaysNo == 0)
+ {
+ gregorianYear -= 1;
+ gregorianDaysNo = 365;
+ }
+
+ else
+ {
+ gregorianDaysNo--;
+ gregorianYear += (div ((int) gregorianDaysNo, (int) 365).quot);
+ gregorianDaysNo = gregorianDaysNo % 365;
+
+ if (gregorianDaysNo == 0)
+ {
+ gregorianYear -= 1;
+ gregorianDaysNo = 365;
+ }
+ }
+
+
+ for (i = 0; gregorianDaysNo > (gregorianMonthDays[i] + (i == 1 && leap)); i++)
+ gregorianDaysNo -= gregorianMonthDays[i] + (i == 1 && leap);
+
+ gregorianMonth = i + 1;
+ gregorianDay = gregorianDaysNo;
+ h.year = gregorianYear;
+ h.month = gregorianMonth;
+ h.day = gregorianDay;
+ gregorianYear -= 1600;
+
+ return (h);
+}
+
+long
+gregorianDays (long gregorianYear, long gregorianMonth, long gregorianDay)
+{
+
+ int gregorianMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int gregorianDaysNo;
+ int i;
+
+ gregorianYear -= 1600;
+ gregorianMonth -= 1;
+ gregorianDaysNo = 365 * gregorianYear + (div ((int) (gregorianYear + 3), (int) 4).quot) -
+ (div ((int) (gregorianYear + 99), (int) 100).quot) + (div ((int) (gregorianYear + 399), (int) 400).quot);
+
+ for (i = 0; i < gregorianMonth; ++i)
+ gregorianDaysNo += gregorianMonthDays[i];
+
+ if (gregorianMonth > 1 && ((gregorianYear % 4 == 0 && gregorianYear % 100 != 0) || (gregorianYear % 400 == 0)))
+ gregorianDaysNo++;
+
+ gregorianDaysNo += gregorianDay;
+
+ return gregorianDaysNo;
+}
+
+#ifdef MODULE
+int day_of_week (int year, int month, int day)
+#else
+int gregorian_day_of_week (int year, int month, int day)
+#endif
+{
+ UTinstant jt;
+
+ memset(&jt,0,sizeof(UTinstant));
+ jt.year = year;
+ jt.month = month;
+ jt.day = day;
+ jt.i_hour = 0;
+ jt.i_minute = 0;
+ jt.i_second = 0;
+ juldat(&jt);
+
+ return jt.weekday + 1;
+}
+
+#ifdef MODULE
+int is_leap_year (int year)
+#else
+int gregorian_is_leap_year (int year)
+#endif
+{
+ if (year <= 1752)
+ return (year % 4 == 0);
+ else
+ return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);
+}
+
+#ifdef MODULE
+int days_in_month (int month, int year)
+#else
+int gregorian_days_in_month (int month, int year)
+#endif
+{
+ int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ assert (month > 0);
+ assert (month <= 12);
+
+ if ( year == 12 )
+ return days[month] = gregorian_is_leap_year(year);
+
+ return days[month];
+}
+
+#ifdef MODULE
+int day_of_year (int year, int month, int day)
+#else
+int gregorian_day_of_year (int year, int month, int day)
+#endif
+{
+ int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+
+ if ( month == 12 )
+ return days[month - 1] + gregorian_is_leap_year(year) + day;
+
+ return days[month - 1] + day;
+}
+
+#ifndef MODULES
+
+void gregorian_loader(imcaltimeobj *cal){
+ strncpy((char*) cal -> cal_type, GREGORIAN, MAX_CAL_NAME);
+ cal -> convert_to_cal_type = NULL;
+ cal -> convert_to_gregorian = NULL;
+ cal -> days_in_month = &gregorian_days_in_month;
+ cal -> day_of_year = &gregorian_day_of_year;
+ cal -> day_of_week = &gregorian_day_of_week;
+ cal -> is_leap_year = &gregorian_is_leap_year;
+}
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.h 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.h 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_gregorian.h
+ CREATOR: Bagher Fathi fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#ifndef _imcaltime_OBJ_GREGORIAN_
+ #define _imcaltime_OBJ_GREGORIAN_
+
+#include <stdlib.h>
+
+struct imcaldatetype gregorianDate (long gregorianDaysNo);
+long int gregorianDays (long gregorianYear, long gregorianMonth, long gregorianDay);
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.c 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.c 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,312 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_hijri.c
+ CREATOR: Bagher Fathi fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#include "imcaltimeobj_hijri.h"
+#include "imcaltime.h"
+#include "assert.h"
+
+
+long
+hijriDays (int hijriYear, int hijriMonth, int hijriDay)
+{
+ int hijriMonthDays[] = { 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29 };
+ long int hijriDaysNo;
+ struct imcaldatetype h;
+ int i;
+
+ hijriYear -=1009;
+ hijriMonth -=1;
+
+ if (hijriYear >= 12)
+ {
+ hijriDaysNo = 4252;
+ hijriYear = hijriYear - 12;
+ }
+
+ else
+ hijriDaysNo = 0;
+
+ hijriDaysNo += 10631 * (div ((int) hijriYear, (int) 30).quot);
+ hijriYear = hijriYear % 30;
+
+ for (i = 1; i <= hijriYear; i++)
+ {
+ if (i == 2 || i == 5 || i == 7 || i == 10 || i == 13 || i == 15 ||
+ i == 18 || i == 21 || i == 24 || i == 26 || i == 29)
+ hijriDaysNo += 355;
+ else
+ hijriDaysNo += 354;
+ }
+
+ for (i = 0; i < hijriMonth; i++)
+ hijriDaysNo += hijriMonthDays[i];
+
+ hijriDaysNo += hijriDay;
+
+ return hijriDaysNo;
+}
+
+/* FIXME Remove fopen */
+struct imcaldatetype hijriToGregorian (hijriYear, hijriMonth, hijriDay)
+{
+
+ FILE * fp;
+ struct imcaldatetype h;
+ struct imcaldatetype hd;
+ struct imcaldatetype gd;
+ long int hijriDaysNo, gregorianDaysNo;
+
+ hijriDaysNo = hijriDays (hijriYear, hijriMonth, hijriDay);
+
+ if ((fp = fopen ("dateExep.txt", "r")) != NULL)
+ {
+ while (fscanf(fp, "%d %d %d %d %d %d ", &gd.year, &gd.month, &gd.day,
+ &hd.year, &hd.month, &hd.day) != EOF)
+ {
+ if (hijriDays (hijriYear, hijriMonth, hijriDay) >=
+ hijriDays (hd.year, hd.month, hd.day))
+ {
+
+ if (hijriDays (hijriYear, hijriMonth, hijriDay) ==
+ hijriDays (hd.year, hd.month, hd.day))
+
+ if (hijriMonth > hd.month)
+ {
+ h = gregorianDate (gregorianDays (gd.year, gd.month, gd.day) + 1);
+
+ return (h);
+ }
+
+ else if (hijriMonth == hd.month)
+ {
+ h = gregorianDate (gregorianDays (gd.year, gd.month, gd.day));
+
+ return (h);
+ }
+
+ if (hd.day == 30)
+ hijriDaysNo++;
+
+ if (hd.day == 1)
+ hijriDaysNo--;
+
+ }
+ }
+ fclose (fp);
+ }
+
+ gregorianDaysNo = hijriDaysNo + 194;
+ h = gregorianDate (gregorianDaysNo);
+
+ return (h);
+}
+
+struct imcaldatetype hijriDate (long hijriDaysNo)
+{
+
+ int hijriMonthDays[] = { 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29 };
+ int hijriYear, hijriMonth, hijriDay;
+ struct imcaldatetype h;
+ int temp1, temp2,i;
+
+ if (hijriDaysNo >= 4252)
+ {
+ temp2 = 12;
+ hijriDaysNo -= 4252;
+ }
+
+ else
+ temp2 = 0;
+
+
+ temp1 = (div ((int) hijriDaysNo, (int) 10631).quot);
+ hijriDaysNo = hijriDaysNo % 10631;
+
+ hijriYear = temp2 + 1009 + 30 * temp1;
+
+ for (i = 1; i <= 30; i++)
+ {
+ if (i == 2 || i == 5 || i == 7 || i == 10 || i == 13 || i == 15 ||
+ i == 18 || i == 21 || i == 24 || i == 26 || i == 29)
+ {
+ if (hijriDaysNo >= 355)
+ {
+ hijriDaysNo -= 355;
+ hijriYear += 1;
+ }
+
+ else
+ i = 30;
+ }
+
+ else
+ {
+ if (hijriDaysNo >= 354)
+ {
+ hijriDaysNo -= 354;
+ hijriYear += 1;
+ }
+
+ else
+ i = 30;
+ }
+ }
+
+ if (hijriDaysNo == 0)
+ {
+ i = (hijriYear - 1) % 30;
+
+ if (i == 2 || i == 5 || i == 7 || i == 10 || i == 13 || i == 15 ||
+ i == 18 || i == 21 || i == 24 || i == 26 || i == 29)
+ {
+ hijriYear -= 1;
+ hijriDaysNo = 355;
+ }
+
+ else
+ {
+ hijriYear -= 1;
+ hijriDaysNo = 354;
+ }
+ }
+
+ for (i = 0; i < 11 && hijriDaysNo > hijriMonthDays[i]; i++)
+ hijriDaysNo -= hijriMonthDays[i];
+
+ hijriMonth = i + 1;
+ hijriDay = hijriDaysNo;
+ h.year = hijriYear;
+ h.month = hijriMonth;
+ h.day = hijriDay;
+
+ return (h);
+}
+
+
+
+struct imcaldatetype gregorianToHijri (int gregorianYear, int gregorianMonth, int gregorianDay)
+{
+ FILE * fp;
+ long int gregorianDaysNo;
+ struct imcaldatetype h, hd, gd;
+
+ gregorianDaysNo = gregorianDays (gregorianYear, gregorianMonth, gregorianDay);
+
+ if ((fp = fopen ("dateExep.txt", "r")) != NULL)
+ {
+ while (fscanf(fp, "%d %d %d %d %d %d ", &gd.year, &gd.month, &gd.day,
+ &hd.year, &hd.month, &hd.day) != EOF)
+ {
+ if (gregorianDays (gregorianYear, gregorianMonth, gregorianDay) >=
+ gregorianDays (gd.year, gd.month, gd.day))
+ {
+ if (gregorianDays (gregorianYear, gregorianMonth, gregorianDay) ==
+ gregorianDays (gd.year, gd.month, gd.day))
+ {
+ h.day = hd.day;
+ h.month = hd.month;
+ h.year = hd.year;
+
+ return (h);
+ }
+
+ if (hd.day == 30)
+ gregorianDaysNo--;
+
+ if (hd.day == 1)
+ gregorianDaysNo++;
+ }
+ }
+ fclose (fp);
+
+ }
+
+ gregorianDaysNo = gregorianDaysNo - 194;
+ h = hijriDate (gregorianDaysNo);
+
+ return (h);
+}
+
+#ifdef MODULES
+int day_of_week (int year, int month, int day)
+#else
+int hijri_day_of_week (int year, int month, int day)
+#endif
+{
+ return gregorian_day_of_week(year, month, day);
+}
+
+#ifdef MODULES
+int is_leap_year (int year)
+#else
+int hijri_is_leap_year (int year)
+#endif
+{
+ /* TODO Add support for non-gregorian calendar systems. */
+ return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);
+}
+
+#ifdef MODULES
+int days_in_month (int month, int year)
+#else
+int hijri_days_in_month (int month, int year)
+#endif
+{
+ int days[] = { 0, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29 };
+
+ assert (month > 0);
+ assert (month <= 12);
+
+ if ( year == 12 )
+ return days[month] = hijri_is_leap_year(year);
+
+ return days[month];
+}
+
+#ifdef MODULES
+int day_of_year (int year, int month, int day)
+#else
+int hijri_day_of_year (int year, int month, int day)
+#endif
+{
+ int days[] = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 354};
+
+ if ( month == 12 )
+ return days[month - 1] + hijri_is_leap_year(year) + day;
+
+ return days[month - 1] + day;
+}
+
+#ifndef MODULES
+
+void hijri_loader(imcaltimeobj *cal){
+ strncpy((char*) cal -> cal_type, HIJRI, MAX_CAL_NAME);
+ cal -> convert_to_cal_type = &gregorianToHijri;
+ cal -> convert_to_gregorian = &hijriToGregorian;
+ cal -> days_in_month = &hijri_days_in_month;
+ cal -> day_of_year = &hijri_day_of_year;
+ cal -> day_of_week = &hijri_day_of_week;
+ cal -> is_leap_year = &hijri_is_leap_year;
+}
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.h 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.h 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_jalali.c
+ CREATOR: Bagher Fathi fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#ifndef _imcaltime_OBJ_HIJRI_
+ #define _imcaltime_OBJ_HIJRI_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+struct imcaldatetype hijriToGregorian (int hijriYear, int hijriMonth, int hijriDay);
+struct imcaldatetype gregorianToHijri (int gregorianYear, int gregorianMonth, int gregorianDay);
+struct imcaldatetype gregorianDate (long gregorianDaysNo);
+long int hijriDays (int hijriYear, int hijriMonth, int hijriDay);
+int jalali_day_of_week (int year, int month, int day);
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.c 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.c 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_jalali.c
+ CREATOR: Bagher Fathi fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#include "imcaltimeobj_jalali.h"
+#include "imcaltime.h"
+#include "assert.h"
+
+
+long int
+jalalyDays (int jalalyYear, int jalalyMonth, int jalalyDay)
+{
+
+ int jalalyMonthDays[] = { 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 };
+ long int jalalyDaysNo;
+ int i;
+
+
+ jalalyYear -= 979;
+ jalalyMonth -= 1;
+
+ if (jalalyYear >= 8){
+ jalalyDaysNo = 2922;
+ jalalyYear -= 8;
+ }
+
+ else
+ jalalyDaysNo = 0;
+
+ jalalyDaysNo += 46751 * (div ((int) jalalyYear, (int) 128).quot);
+ jalalyYear %=128;
+
+ if (jalalyYear >= 29){
+ jalalyDaysNo += 10592;
+ jalalyYear -=29;
+ }
+
+ jalalyDaysNo += 12053 * (div ((int) jalalyYear, (int) 33).quot);
+ jalalyYear %=33;
+
+ if (jalalyYear >= 5)
+ {
+ jalalyDaysNo += 1826;
+ jalalyYear -=5;
+ }
+
+ else if (jalalyYear == 4)
+ {
+ jalalyDaysNo += 1460;
+ jalalyYear -=4;
+ }
+
+ jalalyDaysNo += 1461 * (div ((int) jalalyYear, (int) 4).quot);
+ jalalyYear %= 4;
+ jalalyDaysNo += 365 * jalalyYear;
+
+ for (i = 0; i < jalalyMonth; i++)
+ jalalyDaysNo += jalalyMonthDays[i];
+
+ jalalyDaysNo += jalalyDay;
+
+ return jalalyDaysNo;
+}
+
+#ifdef MODULE
+struct imcaldatetype convert_to_Gregorian (jalalyYear, jalalyMonth, jalalyDay)
+#else
+struct imcaldatetype jalaliToGregorian (jalalyYear, jalalyMonth, jalalyDay)
+#endif
+{
+ struct imcaldatetype h;
+ long int jalalyDaysNo, gregorianDaysNo;
+
+ jalalyDaysNo = jalalyDays (jalalyYear, jalalyMonth, jalalyDay);
+ gregorianDaysNo = jalalyDaysNo + 80;
+ h = gregorianDate (gregorianDaysNo);
+
+ return (h);
+}
+
+struct imcaldatetype jalalyDate (long jalalyDaysNo)
+{
+
+ int jalalyMonthDays[] = { 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 };
+ struct imcaldatetype h;
+ int jalayYear, jalalyMonth, jalalyDay;
+ int temp1, temp2, temp3, temp4,i;
+
+ if (jalalyDaysNo >= 2922)
+ {
+ temp3 = 8;
+ jalalyDaysNo -= 2922;
+ }
+
+ else
+ temp3 = 0;
+
+ temp1 = (div ((int) jalalyDaysNo, (int) 46751).quot);
+ jalalyDaysNo = jalalyDaysNo % 46751;
+
+ if (jalalyDaysNo >= 10592)
+ {
+ jalayYear = 29;
+ jalalyDaysNo -= 10592;
+ }
+
+ else
+ jalayYear = 0;
+
+ temp2 = (div ((int) jalalyDaysNo, (int) 12053).quot);
+ jalalyDaysNo = jalalyDaysNo % 12053;
+
+ if (jalalyDaysNo >= 1826)
+ {
+ temp4 = 5;
+ jalalyDaysNo -= 1826;
+ }
+
+ else
+ if (jalalyDaysNo > 1095)
+ {
+ temp4 = 3;
+ jalalyDaysNo -= 1095;
+ }
+ else
+ temp4 = 0;
+
+ jalayYear += temp4 + temp3 + 979 + 128 * temp1 + 33 * temp2 + 4 * (div ((int) jalalyDaysNo, (int) 1461).quot);
+ jalalyDaysNo %= 1461;
+
+ if (jalalyDaysNo == 0)
+ {
+ jalayYear -= 1;
+ jalalyDaysNo = 366;
+ }
+
+ else
+ {
+ jalayYear += (div ((int) jalalyDaysNo, (int) 365).quot);
+ jalalyDaysNo = jalalyDaysNo % 365;
+
+ if (jalalyDaysNo == 0)
+ {
+ jalayYear -= 1;
+ jalalyDaysNo = 365;
+ }
+ }
+
+ for (i = 0; i < 11 && jalalyDaysNo > jalalyMonthDays[i]; ++i)
+ jalalyDaysNo -= jalalyMonthDays[i];
+
+ jalalyMonth = i + 1;
+ jalalyDay = jalalyDaysNo;
+ h.day = jalalyDay;
+ h.month = jalalyMonth;
+ h.year = jalayYear;
+
+ return (h);
+
+}
+
+#ifdef MODULES
+struct imcaldatetype gregorian_to_cal_type (gregorianYear, gregorianMonth, gregorianDay)
+#else
+struct imcaldatetype gregorianToJalali (gregorianYear, gregorianMonth, gregorianDay)
+#endif
+{
+ int gregorianDaysNo, jalalyDaysNo;
+ struct imcaldatetype h;
+
+ gregorianDaysNo = gregorianDays (gregorianYear, gregorianMonth, gregorianDay);
+ jalalyDaysNo = gregorianDaysNo - 80;
+ h = jalalyDate (jalalyDaysNo);
+
+ return (h);
+}
+
+#ifdef MODULES
+int day_of_week (int year, int month, int day)
+#else
+int jalali_day_of_week (int year, int month, int day)
+#endif
+{
+ struct imcaldatetype dt = jalaliToGregorian(year, month, day);
+
+ return gregorian_day_of_week(dt.year, dt.month, dt.day);
+}
+
+#ifdef MODULES
+int is_leap_year (int year)
+#else
+int jalali_is_leap_year (int year)
+#endif
+{
+ /* TODO Add support for non-gregorian calendar systems. */
+ return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);
+}
+
+#ifdef MODULES
+int days_in_month (int month, int year)
+#else
+int jalali_days_in_month (int month, int year)
+#endif
+{
+ int days[13] = {0, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};
+
+ assert (month > 0);
+ assert (month <= 12);
+
+ if ( year == 12 )
+ return days[month] = jalali_is_leap_year(year);
+
+ return days[month];
+}
+
+#ifdef MODULES
+int day_of_year (int year, int month, int day)
+#else
+int jalali_day_of_year (int year, int month, int day)
+#endif
+{
+ int days[12] = {0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 365};
+
+ if ( month == 12 )
+ return days[month - 1] + jalali_is_leap_year(year) + day;
+
+ return days[month - 1] + day;
+}
+
+#ifndef MODULES
+
+void jalaly_loader(imcaltimeobj *cal){
+ strncpy((char*) cal -> cal_type, JALALI, MAX_CAL_NAME);
+ cal -> convert_to_cal_type = &gregorianToJalali;
+ cal -> convert_to_gregorian = &jalaliToGregorian;
+ cal -> days_in_month = &jalali_days_in_month;
+ cal -> day_of_year = &jalali_day_of_year;
+ cal -> day_of_week = &jalali_day_of_week;
+ cal -> is_leap_year = &jalali_is_leap_year;
+}
+
+#endif
+
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.h 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.h 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_jalali.h
+ CREATOR: Bagher Fathi fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#ifndef _imcaltime_OBJ_JALALI_
+ #define _imcaltime_OBJ_JALALI_
+
+#include <stdlib.h>
+
+struct imcaldatetype jalalyDate (long jalalyDaysNo);
+struct imcaldatetype jalaliToGregorian (int jalalyYear, int jalalyMonth, int jalalyDay);
+struct imcaldatetype gregorianDate (long gregorianDaysNo);
+struct imcaldatetype gregorianToJalali(int,int,int);
+long int jalalyDays (int jalalyYear, int jalalyMonth, int jalalyDay);
+int jalali_day_of_week (int year, int month, int day);
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimezone.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimezone.c 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.c 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,1716 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: icaltimezone.c
+ CREATOR: Damon Chaplin 15 March 2001
+
+ $Id: icaltimezone.c,v 1.22 2003/10/21 18:28:27 ettore Exp $
+ $Locker: $
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2001, Damon Chaplin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+
+======================================================================*/
+
+ /***********************************************************************
+ * @file imcaltimezone.c *
+ * *
+ * @This file prepares some timezone handling routines which supports *
+ * multi calendar *
+ ***********************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "icalproperty.h"
+#include "icalarray.h"
+#include "icalerror.h"
+#include "icalparser.h"
+#include "imcaltimezone.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#define PACKAGE_DATA_DIR "/Projects/libical"
+#endif
+
+/** This is the toplevel directory where the timezone data is installed in. */
+#define ZONEINFO_DIRECTORY PACKAGE_DATA_DIR "/zoneinfo"
+
+/** The prefix we use to uniquely identify TZIDs. */
+#define TZID_PREFIX "/softwarestudio.org/"
+#define TZID_PREFIX_LEN 20
+
+/** This is the filename of the file containing the city names and
+ coordinates of all the builtin timezones. */
+#define ZONES_TAB_FILENAME "zones.tab"
+
+/** This is the number of years of extra coverage we do when expanding
+ the timezone changes. */
+#define imcaltimeZONE_EXTRA_COVERAGE 5
+
+/** This is the maximum year we will expand to. time_t values only go up to
+ somewhere around 2037. */
+#define imcaltimeZONE_MAX_YEAR 2035
+
+struct _imcaltimezone {
+ char *tzid;
+ /**< The unique ID of this timezone,
+ e.g. "/softwarestudio.org/Olson_20010601_1/Africa/Banjul".
+ This should only be used to identify a VTIMEZONE. It is not
+ meant to be displayed to the user in any form. */
+
+ char *location;
+ /**< The location for the timezone, e.g. "Africa/Accra" for the
+ Olson database. We look for this in the "LOCATION" or
+ "X-LIC-LOCATION" properties of the VTIMEZONE component. It
+ isn't a standard property yet. This will be NULL if no location
+ is found in the VTIMEZONE. */
+
+ char *tznames;
+ /**< This will be set to a combination of the TZNAME properties
+ from the last STANDARD and DAYLIGHT components in the
+ VTIMEZONE, e.g. "EST/EDT". If they both use the same TZNAME,
+ or only one type of component is found, then only one TZNAME
+ will appear, e.g. "AZOT". If no TZNAME is found this will be
+ NULL. */
+
+ double latitude;
+ double longitude;
+ /**< The coordinates of the city, in degrees. */
+
+ icalcomponent *component;
+ /**< The toplevel VTIMEZONE component loaded from the .ics file for this
+ timezone. If we need to regenerate the changes data we need this. */
+
+ imcaltimezone *builtin_timezone;
+ /**< If this is not NULL it points to the builtin imcaltimezone
+ that the above TZID refers to. This imcaltimezone should be used
+ instead when accessing the timezone changes data, so that the
+ expanded timezone changes data is shared between calendar
+ components. */
+
+ int end_year;
+ /**< This is the last year for which we have expanded the data to.
+ If we need to calculate a date past this we need to expand the
+ timezone component data from scratch. */
+
+ icalarray *changes;
+ /**< A dynamically-allocated array of time zone changes, sorted by the
+ time of the change in local time. So we can do fast binary-searches
+ to convert from local time to UTC. */
+};
+
+typedef struct _imcaltimezonechange imcaltimezonechange;
+
+struct _imcaltimezonechange {
+ int utc_offset;
+ /**< The offset to add to UTC to get local time, in seconds. */
+
+ int prev_utc_offset;
+ /**< The offset to add to UTC, before this change, in seconds. */
+
+ int year; /**< Actual year, e.g. 2001. */
+ int month; /**< 1 (Jan) to 12 (Dec). */
+ int day;
+ int hour;
+ int minute;
+ int second;
+ /**< The time that the change came into effect, in UTC.
+ Note that the prev_utc_offset applies to this local time,
+ since we haven't changed to the new offset yet. */
+
+ int is_daylight;
+ /**< Whether this is STANDARD or DAYLIGHT time. */
+};
+
+
+/** An array of imcaltimezones for the builtin timezones. */
+static icalarray *builtin_timezones = NULL;
+
+/** This is the special UTC timezone, which isn't in builtin_timezones. */
+static imcaltimezone utc_timezone = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static char* zone_files_directory = NULL;
+
+static void imcaltimezone_reset (imcaltimezone *zone);
+static char* imcaltimezone_get_location_from_vtimezone (icalcomponent *component);
+static char* imcaltimezone_get_tznames_from_vtimezone (icalcomponent *component, const struct imcaltimeobj *cal);
+static void imcaltimezone_expand_changes (imcaltimezone *zone,
+ int end_year,
+ const struct imcaltimeobj *cal);
+static void imcaltimezone_expand_vtimezone (icalcomponent *comp,
+ int end_year,
+ icalarray *changes, const struct imcaltimeobj *cal);
+static int imcaltimezone_compare_change_fn (const void *elem1,
+ const void *elem2);
+
+static int imcaltimezone_find_nearby_change (imcaltimezone *zone,
+ imcaltimezonechange *change);
+
+static void imcaltimezone_adjust_change (imcaltimezonechange *tt,
+ int days,
+ int hours,
+ int minutes,
+ int seconds,
+ const struct imcaltimeobj *cal);
+
+static void imcaltimezone_init (imcaltimezone *zone);
+
+/** Gets the TZID, LOCATION/X-LIC-LOCATION, and TZNAME properties from the
+ VTIMEZONE component and places them in the imcaltimezone. It returns 1 on
+ success, or 0 if the TZID can't be found. */
+static int imcaltimezone_get_vtimezone_properties (imcaltimezone *zone,
+ icalcomponent *component,
+ const struct imcaltimeobj *cal);
+
+
+static void imcaltimezone_load_builtin_timezone (imcaltimezone *zone,
+ const struct imcaltimeobj *cal);
+
+static void imcaltimezone_ensure_coverage (imcaltimezone *zone,
+ int end_year,
+ const struct imcaltimeobj *cal);
+
+
+static void imcaltimezone_init_builtin_timezones(void);
+
+static void imcaltimezone_parse_zone_tab (void);
+
+static char* imcaltimezone_load_get_line_fn (char *s,
+ size_t size,
+ void *data);
+
+static void format_utc_offset (int utc_offset,
+ char *buffer);
+
+static char* get_zone_directory(void);
+
+
+/** Creates a new imcaltimezone. */
+imcaltimezone*
+imcaltimezone_new (void)
+{
+ imcaltimezone *zone;
+
+ zone = (imcaltimezone*) malloc (sizeof (imcaltimezone));
+ if (!zone) {
+ icalerror_set_errno (ICAL_NEWFAILED_ERROR);
+ return NULL;
+ }
+
+ imcaltimezone_init (zone);
+
+ return zone;
+}
+
+
+/** Frees all memory used for the imcaltimezone. */
+void
+imcaltimezone_free (imcaltimezone *zone,
+ int free_struct)
+{
+ imcaltimezone_reset (zone);
+ if (free_struct)
+ free (zone);
+}
+
+
+/** Resets the imcaltimezone to the initial state, freeing most of the fields. */
+static void
+imcaltimezone_reset (imcaltimezone *zone)
+{
+ if (zone->tzid)
+ free (zone->tzid);
+ if (zone->location)
+ free (zone->location);
+ if (zone->tznames)
+ free (zone->tznames);
+ if (zone->component)
+ icalcomponent_free (zone->component);
+ if (zone->changes)
+ icalarray_free (zone->changes);
+
+ imcaltimezone_init (zone);
+}
+
+
+/** Initializes an imcaltimezone. */
+static void
+imcaltimezone_init (imcaltimezone *zone)
+{
+ zone->tzid = NULL;
+ zone->location = NULL;
+ zone->tznames = NULL;
+ zone->latitude = 0.0;
+ zone->longitude = 0.0;
+ zone->component = NULL;
+ zone->builtin_timezone = NULL;
+ zone->end_year = 0;
+ zone->changes = NULL;
+}
+
+
+/** Gets the TZID, LOCATION/X-LIC-LOCATION and TZNAME properties of
+ the VTIMEZONE component and stores them in the imcaltimezone. It
+ returns 1 on success, or 0 if the TZID can't be found. Note that
+ it expects the zone to be initialized or reset - it doesn't free
+ any old values. */
+static int
+imcaltimezone_get_vtimezone_properties (imcaltimezone *zone,
+ icalcomponent *component,
+ const struct imcaltimeobj *cal)
+{
+ icalproperty *prop;
+ const char *tzid;
+
+ prop = icalcomponent_get_first_property (component, ICAL_TZID_PROPERTY);
+ if (!prop)
+ return 0;
+
+ /* A VTIMEZONE MUST have a TZID, or a lot of our code won't work. */
+ tzid = icalproperty_get_tzid (prop);
+ if (!tzid)
+ return 0;
+
+ zone->tzid = strdup (tzid);
+ zone->component = component;
+ if ( zone->location != 0 ) free ( zone->location );
+ zone->location = imcaltimezone_get_location_from_vtimezone (component) ;
+ zone->tznames = imcaltimezone_get_tznames_from_vtimezone (component, cal);
+
+ return 1;
+}
+
+/** Gets the LOCATION or X-LIC-LOCATION property from a VTIMEZONE. */
+static char*
+imcaltimezone_get_location_from_vtimezone (icalcomponent *component)
+{
+ icalproperty *prop;
+ const char *location;
+ const char *name;
+
+ prop = icalcomponent_get_first_property (component,
+ ICAL_LOCATION_PROPERTY);
+ if (prop) {
+ location = icalproperty_get_location (prop);
+ if (location)
+ return strdup (location);
+ }
+
+ prop = icalcomponent_get_first_property (component, ICAL_X_PROPERTY);
+ while (prop) {
+ name = icalproperty_get_x_name (prop);
+ if (name && !strcmp (name, "X-LIC-LOCATION")) {
+ location = icalproperty_get_x (prop);
+ if (location)
+ return strdup (location);
+ }
+ prop = icalcomponent_get_next_property (component,
+ ICAL_X_PROPERTY);
+ }
+
+ return NULL;
+}
+
+
+/** Gets the TZNAMEs used for the last STANDARD & DAYLIGHT components
+ in a VTIMEZONE. If both STANDARD and DAYLIGHT components use the
+ same TZNAME, it returns that. If they use different TZNAMEs, it
+ formats them like "EST/EDT". The returned string should be freed by
+ the caller. */
+static char*
+imcaltimezone_get_tznames_from_vtimezone (icalcomponent *component, const struct imcaltimeobj *cal)
+{
+ icalcomponent *comp;
+ icalcomponent_kind type;
+ icalproperty *prop;
+ struct icaltimetype dtstart;
+ struct icaldatetimeperiodtype rdate;
+ const char *current_tzname;
+ const char *standard_tzname = NULL, *daylight_tzname = NULL;
+ struct icaltimetype standard_max_date, daylight_max_date;
+ struct icaltimetype current_max_date;
+
+ standard_max_date = imcaltime_null_time();
+ daylight_max_date = imcaltime_null_time();
+
+ /* Step through the STANDARD & DAYLIGHT subcomponents. */
+ comp = icalcomponent_get_first_component (component, ICAL_ANY_COMPONENT);
+ while (comp) {
+ type = icalcomponent_isa (comp);
+ if (type == ICAL_XSTANDARD_COMPONENT
+ || type == ICAL_XDAYLIGHT_COMPONENT) {
+ current_max_date = imcaltime_null_time ();
+ current_tzname = NULL;
+
+ /* Step through the properties. We want to find the TZNAME, and
+ the largest DTSTART or RDATE. */
+ prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+ while (prop) {
+ switch (icalproperty_isa (prop)) {
+ case ICAL_TZNAME_PROPERTY:
+ current_tzname = icalproperty_get_tzname (prop);
+ break;
+
+ case ICAL_DTSTART_PROPERTY:
+ dtstart = icalproperty_get_dtstart (prop);
+ if (imcaltime_compare (dtstart, current_max_date, cal) > 0)
+ current_max_date = dtstart;
+
+ break;
+
+ case ICAL_RDATE_PROPERTY:
+ rdate = icalproperty_get_rdate (prop);
+ if (imcaltime_compare (rdate.time, current_max_date, cal) > 0)
+ current_max_date = rdate.time;
+
+ break;
+
+ default:
+ break;
+ }
+
+ prop = icalcomponent_get_next_property (comp,
+ ICAL_ANY_PROPERTY);
+ }
+
+ if (current_tzname) {
+ if (type == ICAL_XSTANDARD_COMPONENT) {
+ if (!standard_tzname
+ || imcaltime_compare (current_max_date,
+ standard_max_date, cal) > 0) {
+ standard_max_date = current_max_date;
+ standard_tzname = current_tzname;
+ }
+ } else {
+ if (!daylight_tzname
+ || imcaltime_compare (current_max_date,
+ daylight_max_date, cal) > 0) {
+ daylight_max_date = current_max_date;
+ daylight_tzname = current_tzname;
+ }
+ }
+ }
+ }
+
+ comp = icalcomponent_get_next_component (component,
+ ICAL_ANY_COMPONENT);
+ }
+
+ /* Outlook (2000) places "Standard Time" and "Daylight Time" in the TZNAME
+ strings, which is totally useless. So we return NULL in that case. */
+ if (standard_tzname && !strcmp (standard_tzname, "Standard Time"))
+ return NULL;
+
+ /* If both standard and daylight TZNAMEs were found, if they are the same
+ we return just one, else we format them like "EST/EDT". */
+ if (standard_tzname && daylight_tzname) {
+ unsigned int standard_len, daylight_len;
+ char *tznames;
+
+ if (!strcmp (standard_tzname, daylight_tzname))
+ return strdup (standard_tzname);
+
+ standard_len = strlen (standard_tzname);
+ daylight_len = strlen (daylight_tzname);
+ tznames = malloc (standard_len + daylight_len + 2);
+ strcpy (tznames, standard_tzname);
+ tznames[standard_len] = '/';
+ strcpy (tznames + standard_len + 1, daylight_tzname);
+ return tznames;
+ } else {
+ const char *tznames;
+
+ /* If either of the TZNAMEs was found just return that, else NULL. */
+ tznames = standard_tzname ? standard_tzname : daylight_tzname;
+ return tznames ? strdup (tznames) : NULL;
+ }
+}
+
+
+static void
+imcaltimezone_ensure_coverage (imcaltimezone *zone,
+ int end_year,
+ const struct imcaltimeobj *cal)
+{
+ /* When we expand timezone changes we always expand at least up to this
+ year, plus imcaltimeZONE_EXTRA_COVERAGE. */
+ static int imcaltimezone_minimum_expansion_year = -1;
+
+ int changes_end_year;
+
+ if (!zone->component)
+ imcaltimezone_load_builtin_timezone (zone, cal);
+
+ if (imcaltimezone_minimum_expansion_year == -1) {
+ struct icaltimetype today = imcaltime_today(cal);
+ imcaltimezone_minimum_expansion_year = today.year;
+ }
+
+ changes_end_year = end_year;
+ if (changes_end_year < imcaltimezone_minimum_expansion_year)
+ changes_end_year = imcaltimezone_minimum_expansion_year;
+
+ changes_end_year += imcaltimeZONE_EXTRA_COVERAGE;
+
+ if (changes_end_year > imcaltimeZONE_MAX_YEAR)
+ changes_end_year = imcaltimeZONE_MAX_YEAR;
+
+ if (!zone->changes || zone->end_year < end_year)
+ imcaltimezone_expand_changes (zone, changes_end_year, cal);
+}
+
+
+static void
+imcaltimezone_expand_changes (imcaltimezone *zone,
+ int end_year,
+ const struct imcaltimeobj *cal)
+{
+ icalarray *changes;
+ icalcomponent *comp;
+
+#if 0
+ printf ("\nExpanding changes for: %s to year: %i\n", zone->tzid, end_year);
+#endif
+
+ changes = icalarray_new (sizeof (imcaltimezonechange), 32);
+ if (!changes)
+ return;
+
+ /* Scan the STANDARD and DAYLIGHT subcomponents. */
+ comp = icalcomponent_get_first_component (zone->component,
+ ICAL_ANY_COMPONENT);
+ while (comp) {
+ imcaltimezone_expand_vtimezone (comp, end_year, changes, cal);
+ comp = icalcomponent_get_next_component (zone->component,
+ ICAL_ANY_COMPONENT);
+ }
+
+ /* Sort the changes. We may have duplicates but I don't think it will
+ matter. */
+ icalarray_sort (changes, imcaltimezone_compare_change_fn);
+
+ if (zone->changes)
+ icalarray_free (zone->changes);
+
+ zone->changes = changes;
+ zone->end_year = end_year;
+}
+
+
+static void
+imcaltimezone_expand_vtimezone (icalcomponent *comp,
+ int end_year,
+ icalarray *changes,
+ const struct imcaltimeobj *cal)
+{
+ imcaltimezonechange change;
+ icalproperty *prop;
+ struct icaltimetype dtstart, occ;
+ struct icalrecurrencetype rrule;
+ icalrecur_iterator* rrule_iterator;
+ struct icaldatetimeperiodtype rdate;
+ int found_dtstart = 0, found_tzoffsetto = 0, found_tzoffsetfrom = 0;
+ int has_recurrence = 0;
+
+ /* First we check if it is a STANDARD or DAYLIGHT component, and
+ just return if it isn't. */
+ if (icalcomponent_isa (comp) == ICAL_XSTANDARD_COMPONENT)
+ change.is_daylight = 0;
+ else if (icalcomponent_isa (comp) == ICAL_XDAYLIGHT_COMPONENT)
+ change.is_daylight = 1;
+ else
+ return;
+
+ /* Step through each of the properties to find the DTSTART,
+ TZOFFSETFROM and TZOFFSETTO. We can't expand recurrences here
+ since we need these properties before we can do that. */
+ prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+ while (prop) {
+ switch (icalproperty_isa (prop)) {
+ case ICAL_DTSTART_PROPERTY:
+ dtstart = icalproperty_get_dtstart (prop);
+ found_dtstart = 1;
+ break;
+ case ICAL_TZOFFSETTO_PROPERTY:
+ change.utc_offset = icalproperty_get_tzoffsetto (prop);
+ /*printf ("Found TZOFFSETTO: %i\n", change.utc_offset);*/
+ found_tzoffsetto = 1;
+ break;
+ case ICAL_TZOFFSETFROM_PROPERTY:
+ change.prev_utc_offset = icalproperty_get_tzoffsetfrom (prop);
+ /*printf ("Found TZOFFSETFROM: %i\n", change.prev_utc_offset);*/
+ found_tzoffsetfrom = 1;
+ break;
+ case ICAL_RDATE_PROPERTY:
+ case ICAL_RRULE_PROPERTY:
+ has_recurrence = 1;
+ break;
+ default:
+ /* Just ignore any other properties. */
+ break;
+ }
+
+ prop = icalcomponent_get_next_property (comp, ICAL_ANY_PROPERTY);
+ }
+
+ /* If we didn't find a DTSTART, TZOFFSETTO and TZOFFSETFROM we have to
+ ignore the component. FIXME: Add an error property? */
+ if (!found_dtstart || !found_tzoffsetto || !found_tzoffsetfrom)
+ return;
+
+#if 0
+ printf ("\n Expanding component DTSTART (Y/M/D): %i/%i/%i %i:%02i:%02i\n",
+ dtstart.year, dtstart.month, dtstart.day,
+ dtstart.hour, dtstart.minute, dtstart.second);
+#endif
+
+ /* If the STANDARD/DAYLIGHT component has no recurrence data, we just add
+ a single change for the DTSTART. */
+ if (!has_recurrence) {
+ change.year = dtstart.year;
+ change.month = dtstart.month;
+ change.day = dtstart.day;
+ change.hour = dtstart.hour;
+ change.minute = dtstart.minute;
+ change.second = dtstart.second;
+
+ /* Convert to UTC. */
+ imcaltimezone_adjust_change (&change, 0, 0, 0, -change.prev_utc_offset, cal);
+
+#if 0
+ printf (" Appending single DTSTART (Y/M/D): %i/%02i/%02i %i:%02i:%02i\n",
+ change.year, change.month, change.day,
+ change.hour, change.minute, change.second);
+#endif
+
+ /* Add the change to the array. */
+ icalarray_append (changes, &change);
+ return;
+ }
+
+ /* The component has recurrence data, so we expand that now. */
+ prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+ while (prop) {
+#if 0
+ printf ("Expanding property...\n");
+#endif
+ switch (icalproperty_isa (prop)) {
+ case ICAL_RDATE_PROPERTY:
+ rdate = icalproperty_get_rdate (prop);
+ change.year = rdate.time.year;
+ change.month = rdate.time.month;
+ change.day = rdate.time.day;
+ /* RDATEs with a DATE value inherit the time from
+ the DTSTART. */
+ if (imcaltime_is_date(rdate.time)) {
+ change.hour = dtstart.hour;
+ change.minute = dtstart.minute;
+ change.second = dtstart.second;
+ } else {
+ change.hour = rdate.time.hour;
+ change.minute = rdate.time.minute;
+ change.second = rdate.time.second;
+
+ /* The spec was a bit vague about whether RDATEs were in local
+ time or UTC so we support both to be safe. So if it is in
+ UTC we have to add the UTC offset to get a local time. */
+ if (!imcaltime_is_utc(rdate.time))
+ imcaltimezone_adjust_change (&change, 0, 0, 0,
+ -change.prev_utc_offset, cal);
+ }
+
+#if 0
+ printf (" Appending RDATE element (Y/M/D): %i/%02i/%02i %i:%02i:%02i\n",
+ change.year, change.month, change.day,
+ change.hour, change.minute, change.second);
+#endif
+
+ icalarray_append (changes, &change);
+ break;
+ case ICAL_RRULE_PROPERTY:
+ rrule = icalproperty_get_rrule (prop);
+
+ /* If the rrule UNTIL value is set and is in UTC, we convert it to
+ a local time, since the recurrence code has no way to convert
+ it itself. */
+ if (!imcaltime_is_null_time (rrule.until) && rrule.until.is_utc) {
+#if 0
+ printf (" Found RRULE UNTIL in UTC.\n");
+#endif
+
+ /* To convert from UTC to a local time, we use the TZOFFSETFROM
+ since that is the offset from UTC that will be in effect
+ when each of the RRULE occurrences happens. */
+ imcaltime_adjust (&rrule.until, 0, 0, 0,
+ change.prev_utc_offset, cal);
+ rrule.until.is_utc = 0;
+ }
+
+ rrule_iterator = icalrecur_iterator_new (rrule, dtstart);
+ for (;;) {
+ occ = icalrecur_iterator_next (rrule_iterator);
+ if (occ.year > end_year || imcaltime_is_null_time (occ))
+ break;
+
+ change.year = occ.year;
+ change.month = occ.month;
+ change.day = occ.day;
+ change.hour = occ.hour;
+ change.minute = occ.minute;
+ change.second = occ.second;
+
+#if 0
+ printf (" Appending RRULE element (Y/M/D): %i/%02i/%02i %i:%02i:%02i\n",
+ change.year, change.month, change.day,
+ change.hour, change.minute, change.second);
+#endif
+
+ imcaltimezone_adjust_change (&change, 0, 0, 0,
+ -change.prev_utc_offset, cal);
+
+ icalarray_append (changes, &change);
+ }
+
+ icalrecur_iterator_free (rrule_iterator);
+ break;
+ default:
+ break;
+ }
+
+ prop = icalcomponent_get_next_property (comp, ICAL_ANY_PROPERTY);
+ }
+}
+
+
+/** A function to compare 2 imcaltimezonechange elements, used for qsort(). */
+static int
+imcaltimezone_compare_change_fn (const void *elem1,
+ const void *elem2)
+{
+ const imcaltimezonechange *change1, *change2;
+ int retval;
+
+ change1 = elem1;
+ change2 = elem2;
+
+ if (change1->year < change2->year)
+ retval = -1;
+ else if (change1->year > change2->year)
+ retval = 1;
+
+ else if (change1->month < change2->month)
+ retval = -1;
+ else if (change1->month > change2->month)
+ retval = 1;
+
+ else if (change1->day < change2->day)
+ retval = -1;
+ else if (change1->day > change2->day)
+ retval = 1;
+
+ else if (change1->hour < change2->hour)
+ retval = -1;
+ else if (change1->hour > change2->hour)
+ retval = 1;
+
+ else if (change1->minute < change2->minute)
+ retval = -1;
+ else if (change1->minute > change2->minute)
+ retval = 1;
+
+ else if (change1->second < change2->second)
+ retval = -1;
+ else if (change1->second > change2->second)
+ retval = 1;
+
+ else
+ retval = 0;
+
+ return retval;
+}
+
+
+
+void
+imcaltimezone_convert_time (struct icaltimetype *tt,
+ imcaltimezone *from_zone,
+ imcaltimezone *to_zone,
+ const struct imcaltimeobj *cal)
+{
+ int utc_offset, is_daylight;
+
+ /* If the time is a DATE value or both timezones are the same, or we are
+ converting a floating time, we don't need to do anything. */
+ if (imcaltime_is_date(*tt) || from_zone == to_zone || from_zone == NULL)
+ return;
+
+ /* Convert the time to UTC by getting the UTC offset and subtracting it. */
+ utc_offset = imcaltimezone_get_utc_offset (from_zone, tt, NULL, cal);
+ imcaltime_adjust (tt, 0, 0, 0, -utc_offset, cal);
+
+ /* Now we convert the time to the new timezone by getting the UTC offset
+ of our UTC time and adding it. */
+ utc_offset = imcaltimezone_get_utc_offset_of_utc_time (to_zone, tt,
+ &is_daylight, cal);
+ tt->is_daylight = is_daylight;
+ imcaltime_adjust (tt, 0, 0, 0, utc_offset, cal);
+}
+
+
+
+
+/** @deprecated This API wasn't updated when we changed icaltimetype to contain its own
+ timezone. Also, this takes a pointer instead of the struct. */
+/* Calculates the UTC offset of a given local time in the given
+ timezone. It is the number of seconds to add to UTC to get local
+ time. The is_daylight flag is set to 1 if the time is in
+ daylight-savings time. */
+int
+imcaltimezone_get_utc_offset (imcaltimezone *zone,
+ struct icaltimetype *tt,
+ int *is_daylight,
+ const struct imcaltimeobj *cal)
+{
+ imcaltimezonechange *zone_change, *prev_zone_change, tt_change, tmp_change;
+ int change_num, step, utc_offset_change, cmp;
+ int change_num_to_use;
+ int want_daylight;
+
+ if (tt == NULL)
+ return 0;
+
+ if (is_daylight)
+ *is_daylight = 0;
+
+ /* For local times and UTC return 0. */
+ if (zone == NULL || zone == &utc_timezone)
+ return 0;
+
+ /* Use the builtin imcaltimezone if possible. */
+ if (zone->builtin_timezone)
+ zone = zone->builtin_timezone;
+
+ /* Make sure the changes array is expanded up to the given time. */
+ imcaltimezone_ensure_coverage (zone, tt->year, cal);
+
+ if (!zone->changes || zone->changes->num_elements == 0)
+ return 0;
+
+ /* Copy the time parts of the icaltimetype to an imcaltimezonechange so we
+ can use our comparison function on it. */
+ tt_change.year = tt->year;
+ tt_change.month = tt->month;
+ tt_change.day = tt->day;
+ tt_change.hour = tt->hour;
+ tt_change.minute = tt->minute;
+ tt_change.second = tt->second;
+
+ /* This should find a change close to the time, either the change before
+ it or the change after it. */
+ change_num = imcaltimezone_find_nearby_change (zone, &tt_change);
+
+ /* Sanity check. */
+ icalerror_assert (change_num >= 0,
+ "Negative timezone change index");
+ icalerror_assert (change_num < zone->changes->num_elements,
+ "Timezone change index out of bounds");
+
+ /* Now move backwards or forwards to find the timezone change that applies
+ to tt. It should only have to do 1 or 2 steps. */
+ zone_change = icalarray_element_at (zone->changes, change_num);
+ step = 1;
+ change_num_to_use = -1;
+ for (;;) {
+ /* Copy the change, so we can adjust it. */
+ tmp_change = *zone_change;
+
+ /* If the clock is going backward, check if it is in the region of time
+ that is used twice. If it is, use the change with the daylight
+ setting which matches tt, or use standard if we don't know. */
+ if (tmp_change.utc_offset < tmp_change.prev_utc_offset) {
+ /* If the time change is at 2:00AM local time and the clock is
+ going back to 1:00AM we adjust the change to 1:00AM. We may
+ have the wrong change but we'll figure that out later. */
+ imcaltimezone_adjust_change (&tmp_change, 0, 0, 0,
+ tmp_change.utc_offset, cal);
+ } else {
+ imcaltimezone_adjust_change (&tmp_change, 0, 0, 0,
+ tmp_change.prev_utc_offset, cal);
+ }
+
+ cmp = imcaltimezone_compare_change_fn (&tt_change, &tmp_change);
+
+ /* If the given time is on or after this change, then this change may
+ apply, but we continue as a later change may be the right one.
+ If the given time is before this change, then if we have already
+ found a change which applies we can use that, else we need to step
+ backwards. */
+ if (cmp >= 0)
+ change_num_to_use = change_num;
+ else
+ step = -1;
+
+ /* If we are stepping backwards through the changes and we have found
+ a change that applies, then we know this is the change to use so
+ we exit the loop. */
+ if (step == -1 && change_num_to_use != -1)
+ break;
+
+ change_num += step;
+
+ /* If we go past the start of the changes array, then we have no data
+ for this time so we return a UTC offset of 0. */
+ if (change_num < 0)
+ return 0;
+
+ if (change_num >= zone->changes->num_elements)
+ break;
+
+ zone_change = icalarray_element_at (zone->changes, change_num);
+ }
+
+ /* If we didn't find a change to use, then we have a bug! */
+ icalerror_assert (change_num_to_use != -1,
+ "No applicable timezone change found");
+
+ /* Now we just need to check if the time is in the overlapped region of
+ time when clocks go back. */
+ zone_change = icalarray_element_at (zone->changes, change_num_to_use);
+
+ utc_offset_change = zone_change->utc_offset - zone_change->prev_utc_offset;
+ if (utc_offset_change < 0 && change_num_to_use > 0) {
+ tmp_change = *zone_change;
+ imcaltimezone_adjust_change (&tmp_change, 0, 0, 0,
+ tmp_change.prev_utc_offset, cal);
+
+ if (imcaltimezone_compare_change_fn (&tt_change, &tmp_change) < 0) {
+ /* The time is in the overlapped region, so we may need to use
+ either the current zone_change or the previous one. If the
+ time has the is_daylight field set we use the matching change,
+ else we use the change with standard time. */
+ prev_zone_change = icalarray_element_at (zone->changes,
+ change_num_to_use - 1);
+
+ /* I was going to add an is_daylight flag to struct icaltimetype,
+ but iCalendar doesn't let us distinguish between standard and
+ daylight time anyway, so there's no point. So we just use the
+ standard time instead. */
+ want_daylight = (tt->is_daylight == 1) ? 1 : 0;
+
+#if 0
+ if (zone_change->is_daylight == prev_zone_change->is_daylight)
+ printf (" **** Same is_daylight setting\n");
+#endif
+
+ if (zone_change->is_daylight != want_daylight
+ && prev_zone_change->is_daylight == want_daylight)
+ zone_change = prev_zone_change;
+ }
+ }
+
+ /* Now we know exactly which timezone change applies to the time, so
+ we can return the UTC offset and whether it is a daylight time. */
+ if (is_daylight)
+ *is_daylight = zone_change->is_daylight;
+ return zone_change->utc_offset;
+}
+
+
+/** @deprecated This API wasn't updated when we changed icaltimetype to contain its own
+ timezone. Also, this takes a pointer instead of the struct. */
+/** Calculates the UTC offset of a given UTC time in the given
+ timezone. It is the number of seconds to add to UTC to get local
+ time. The is_daylight flag is set to 1 if the time is in
+ daylight-savings time. */
+int
+imcaltimezone_get_utc_offset_of_utc_time (imcaltimezone *zone,
+ struct icaltimetype *tt,
+ int *is_daylight,
+ const struct imcaltimeobj *cal)
+{
+ imcaltimezonechange *zone_change, tt_change, tmp_change;
+ int change_num, step, change_num_to_use;
+
+ if (is_daylight)
+ *is_daylight = 0;
+
+ /* For local times and UTC return 0. */
+ if (zone == NULL || zone == &utc_timezone)
+ return 0;
+
+ /* Use the builtin imcaltimezone if possible. */
+ if (zone->builtin_timezone)
+ zone = zone->builtin_timezone;
+
+ /* Make sure the changes array is expanded up to the given time. */
+ imcaltimezone_ensure_coverage (zone, tt->year, cal);
+
+ if (!zone->changes || zone->changes->num_elements == 0)
+ return 0;
+
+ /* Copy the time parts of the icaltimetype to an imcaltimezonechange so we
+ can use our comparison function on it. */
+ tt_change.year = tt->year;
+ tt_change.month = tt->month;
+ tt_change.day = tt->day;
+ tt_change.hour = tt->hour;
+ tt_change.minute = tt->minute;
+ tt_change.second = tt->second;
+
+ /* This should find a change close to the time, either the change before
+ it or the change after it. */
+ change_num = imcaltimezone_find_nearby_change (zone, &tt_change);
+
+ /* Sanity check. */
+ icalerror_assert (change_num >= 0,
+ "Negative timezone change index");
+ icalerror_assert (change_num < zone->changes->num_elements,
+ "Timezone change index out of bounds");
+
+ /* Now move backwards or forwards to find the timezone change that applies
+ to tt. It should only have to do 1 or 2 steps. */
+ zone_change = icalarray_element_at (zone->changes, change_num);
+ step = 1;
+ change_num_to_use = -1;
+ for (;;) {
+ /* Copy the change and adjust it to UTC. */
+ tmp_change = *zone_change;
+
+ /* If the given time is on or after this change, then this change may
+ apply, but we continue as a later change may be the right one.
+ If the given time is before this change, then if we have already
+ found a change which applies we can use that, else we need to step
+ backwards. */
+ if (imcaltimezone_compare_change_fn (&tt_change, &tmp_change) >= 0)
+ change_num_to_use = change_num;
+ else
+ step = -1;
+
+ /* If we are stepping backwards through the changes and we have found
+ a change that applies, then we know this is the change to use so
+ we exit the loop. */
+ if (step == -1 && change_num_to_use != -1)
+ break;
+
+ change_num += step;
+
+ /* If we go past the start of the changes array, then we have no data
+ for this time so we return a UTC offset of 0. */
+ if (change_num < 0)
+ return 0;
+
+ if (change_num >= zone->changes->num_elements)
+ break;
+
+ zone_change = icalarray_element_at (zone->changes, change_num);
+ }
+
+ /* If we didn't find a change to use, then we have a bug! */
+ icalerror_assert (change_num_to_use != -1,
+ "No applicable timezone change found");
+
+ /* Now we know exactly which timezone change applies to the time, so
+ we can return the UTC offset and whether it is a daylight time. */
+ zone_change = icalarray_element_at (zone->changes, change_num_to_use);
+ if (is_daylight)
+ *is_daylight = zone_change->is_daylight;
+
+ return zone_change->utc_offset;
+}
+
+
+/** Returns the index of a timezone change which is close to the time
+ given in change. */
+static int
+imcaltimezone_find_nearby_change (imcaltimezone *zone,
+ imcaltimezonechange *change)
+{
+ imcaltimezonechange *zone_change;
+ int lower, upper, middle, cmp;
+
+ /* Do a simple binary search. */
+ lower = middle = 0;
+ upper = zone->changes->num_elements;
+
+ while (lower < upper) {
+ middle = (lower + upper) / 2;
+ zone_change = icalarray_element_at (zone->changes, middle);
+ cmp = imcaltimezone_compare_change_fn (change, zone_change);
+ if (cmp == 0)
+ break;
+ else if (cmp < 0)
+ upper = middle;
+ else
+ lower = middle + 1;
+ }
+
+ return middle;
+}
+
+
+
+
+/** Adds (or subtracts) a time from a imcaltimezonechange. NOTE: This
+ function is exactly the same as imcaltime_adjust() except for the
+ type of the first parameter. */
+static void
+imcaltimezone_adjust_change (imcaltimezonechange *tt,
+ int days,
+ int hours,
+ int minutes,
+ int seconds,
+ const struct imcaltimeobj *cal)
+{
+ 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 = imcaltime_days_in_month (tt->month, tt->year, cal);
+ 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 += imcaltime_days_in_month (tt->month, tt->year, cal);
+ }
+ }
+ tt->day = day;
+}
+
+
+char*
+imcaltimezone_get_tzid (imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+ /* If this is a floating time, without a timezone, return NULL. */
+ if (!zone)
+ return NULL;
+
+ if (!zone->tzid)
+ imcaltimezone_load_builtin_timezone (zone, cal);
+
+ return zone->tzid;
+}
+
+
+char*
+imcaltimezone_get_location (imcaltimezone *zone)
+{
+ /* If this is a floating time, without a timezone, return NULL. */
+ if (!zone)
+ return NULL;
+
+ /* Note that for builtin timezones this comes from zones.tab so we don't
+ need to check the timezone is loaded here. */
+ return zone->location;
+}
+
+
+char*
+imcaltimezone_get_tznames (imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+ /* If this is a floating time, without a timezone, return NULL. */
+ if (!zone)
+ return NULL;
+
+ if (!zone->component)
+ imcaltimezone_load_builtin_timezone (zone, cal);
+
+ return zone->tznames;
+}
+
+
+/** Returns the latitude of a builtin timezone. */
+double
+imcaltimezone_get_latitude (imcaltimezone *zone)
+{
+ /* If this is a floating time, without a timezone, return 0. */
+ if (!zone)
+ return 0.0;
+
+ /* Note that for builtin timezones this comes from zones.tab so we don't
+ need to check the timezone is loaded here. */
+ return zone->latitude;
+}
+
+
+/** Returns the longitude of a builtin timezone. */
+double
+imcaltimezone_get_longitude (imcaltimezone *zone)
+{
+ /* If this is a floating time, without a timezone, return 0. */
+ if (!zone)
+ return 0.0;
+
+ /* Note that for builtin timezones this comes from zones.tab so we don't
+ need to check the timezone is loaded here. */
+ return zone->longitude;
+}
+
+
+/** Returns the VTIMEZONE component of a timezone. */
+icalcomponent*
+imcaltimezone_get_component (imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+ /* If this is a floating time, without a timezone, return NULL. */
+ if (!zone)
+ return NULL;
+
+ if (!zone->component)
+ imcaltimezone_load_builtin_timezone (zone, cal);
+
+ return zone->component;
+}
+
+
+/** Sets the VTIMEZONE component of an imcaltimezone, initializing the
+ tzid, location & tzname fields. It returns 1 on success or 0 on
+ failure, i.e. no TZID was found. */
+int
+imcaltimezone_set_component (imcaltimezone *zone,
+ icalcomponent *comp,
+ const struct imcaltimeobj *cal)
+{
+ imcaltimezone_reset (zone);
+ return imcaltimezone_get_vtimezone_properties (zone, comp, cal);
+}
+
+
+/* Returns the timezone name to display to the user. We prefer to use the
+ Olson city name, but fall back on the TZNAME, or finally the TZID. We don't
+ want to use "" as it may be wrongly interpreted as a floating time.
+ Do not free the returned string. */
+char*
+imcaltimezone_get_display_name (imcaltimezone *zone,
+ const struct imcaltimeobj *cal)
+{
+ char *display_name;
+
+ display_name = imcaltimezone_get_location (zone);
+ if (!display_name)
+ display_name = imcaltimezone_get_tznames (zone, cal);
+ if (!display_name) {
+ display_name = imcaltimezone_get_tzid (zone, cal);
+ /* Outlook will strip out X-LIC-LOCATION property and so all
+ we get back in the iTIP replies is the TZID. So we see if
+ this is one of our TZIDs and if so we jump to the city name
+ at the end of it. */
+ if (display_name
+ && !strncmp (display_name, TZID_PREFIX, TZID_PREFIX_LEN)) {
+ /* Get the location, which is after the 3rd '/' char. */
+ char *p;
+ int num_slashes = 0;
+ for (p = display_name; *p; p++) {
+ if (*p == '/') {
+ num_slashes++;
+ if (num_slashes == 3)
+ return p + 1;
+ }
+ }
+ }
+ }
+
+ return display_name;
+}
+
+
+icalarray*
+imcaltimezone_array_new (void)
+{
+ return icalarray_new (sizeof (imcaltimezone), 16);
+}
+
+
+void
+imcaltimezone_array_append_from_vtimezone (icalarray *timezones,
+ icalcomponent *child, const struct imcaltimeobj *cal)
+{
+ imcaltimezone zone;
+
+ imcaltimezone_init (&zone);
+ if (imcaltimezone_get_vtimezone_properties (&zone, child, cal))
+ icalarray_append (timezones, &zone);
+}
+
+
+void
+imcaltimezone_array_free (icalarray *timezones)
+{
+ imcaltimezone *zone;
+ int i;
+
+ if ( timezones )
+ {
+ for (i = 0; i < timezones->num_elements; i++) {
+ zone = icalarray_element_at (timezones, i);
+ imcaltimezone_free (zone, 0);
+ }
+
+ icalarray_free (timezones);
+ }
+}
+
+
+/*
+ * BUILTIN TIMEZONE HANDLING
+ */
+
+
+/** Returns an icalarray of imcaltimezone structs, one for each builtin
+ timezone. This will load and parse the zones.tab file to get the
+ timezone names and their coordinates. It will not load the
+ VTIMEZONE data for any timezones. */
+icalarray*
+imcaltimezone_get_builtin_timezones (void)
+{
+ if (!builtin_timezones)
+ imcaltimezone_init_builtin_timezones ();
+
+ return builtin_timezones;
+}
+
+/** Release builtin timezone memory */
+void
+imcaltimezone_free_builtin_timezones(void)
+{
+ imcaltimezone_array_free(builtin_timezones);
+}
+
+
+/** Returns a single builtin timezone, given its Olson city name. */
+imcaltimezone*
+imcaltimezone_get_builtin_timezone (const char *location)
+{
+ imcaltimezone *zone;
+ int lower, upper, middle, cmp;
+ char *zone_location;
+
+ if (!location || !location[0])
+ return NULL;
+
+ if (!strcmp (location, "UTC"))
+ return &utc_timezone;
+
+ if (!builtin_timezones)
+ imcaltimezone_init_builtin_timezones ();
+
+ /* Do a simple binary search. */
+ lower = middle = 0;
+ upper = builtin_timezones->num_elements;
+
+ while (lower < upper) {
+ middle = (lower + upper) / 2;
+ zone = icalarray_element_at (builtin_timezones, middle);
+ zone_location = imcaltimezone_get_location (zone);
+ cmp = strcmp (location, zone_location);
+ if (cmp == 0)
+ return zone;
+ else if (cmp < 0)
+ upper = middle;
+ else
+ lower = middle + 1;
+ }
+
+ return NULL;
+}
+
+
+/** Returns a single builtin timezone, given its TZID. */
+imcaltimezone*
+imcaltimezone_get_builtin_timezone_from_tzid (const char *tzid, const struct imcaltimeobj *cal)
+{
+ int num_slashes = 0;
+ const char *p, *zone_tzid;
+ imcaltimezone *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 = imcaltimezone_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 = imcaltimezone_get_tzid (zone, cal);
+ if (!strcmp (zone_tzid, tzid))
+ return zone;
+ else
+ return NULL;
+}
+
+
+/** Returns the special UTC timezone. */
+imcaltimezone*
+imcaltimezone_get_utc_timezone (void)
+{
+ if (!builtin_timezones)
+ imcaltimezone_init_builtin_timezones ();
+
+ return &utc_timezone;
+}
+
+
+
+/** This initializes the builtin timezone data, i.e. the
+ builtin_timezones array and the special UTC timezone. It should be
+ called before any code that uses the timezone functions. */
+static void
+imcaltimezone_init_builtin_timezones (void)
+{
+ /* Initialize the special UTC timezone. */
+ utc_timezone.tzid = "UTC";
+
+ imcaltimezone_parse_zone_tab ();
+}
+
+
+/** This parses the zones.tab file containing the names and locations
+ of the builtin timezones. It creates the builtin_timezones array
+ which is an icalarray of imcaltimezone structs. It only fills in the
+ location, latitude and longtude fields; the rest are left
+ blank. The VTIMEZONE component is loaded later if it is needed. The
+ timezones in the zones.tab file are sorted by their name, which is
+ useful for binary searches. */
+static void
+imcaltimezone_parse_zone_tab (void)
+{
+ char *filename;
+ FILE *fp;
+ char buf[1024]; /* Used to store each line of zones.tab as it is read. */
+ char location[1024]; /* Stores the city name when parsing buf. */
+ unsigned int filename_len;
+ int latitude_degrees, latitude_minutes, latitude_seconds;
+ int longitude_degrees, longitude_minutes, longitude_seconds;
+ imcaltimezone zone;
+
+ icalerror_assert (builtin_timezones == NULL,
+ "Parsing zones.tab file multiple times");
+
+ builtin_timezones = icalarray_new (sizeof (imcaltimezone), 32);
+
+ filename_len = strlen (get_zone_directory()) + strlen (ZONES_TAB_FILENAME)
+ + 2;
+
+ filename = (char*) malloc (filename_len);
+ if (!filename) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return;
+ }
+
+ snprintf (filename, filename_len, "%s/%s", get_zone_directory(),
+ ZONES_TAB_FILENAME);
+
+ fp = fopen (filename, "r");
+ free (filename);
+ if (!fp) {
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return;
+ }
+
+ while (fgets (buf, sizeof(buf), fp)) {
+ if (*buf == '#') continue;
+
+ /* The format of each line is: "latitude longitude location". */
+ if (sscanf (buf, "%4d%2d%2d %4d%2d%2d %s",
+ &latitude_degrees, &latitude_minutes,
+ &latitude_seconds,
+ &longitude_degrees, &longitude_minutes,
+ &longitude_seconds,
+ location) != 7) {
+ fprintf (stderr, "Invalid timezone description line: %s\n", buf);
+ continue;
+ }
+
+ imcaltimezone_init (&zone);
+ zone.location = strdup (location);
+
+ if (latitude_degrees >= 0)
+ zone.latitude = (double) latitude_degrees
+ + (double) latitude_minutes / 60
+ + (double) latitude_seconds / 3600;
+ else
+ zone.latitude = (double) latitude_degrees
+ - (double) latitude_minutes / 60
+ - (double) latitude_seconds / 3600;
+
+ if (longitude_degrees >= 0)
+ zone.longitude = (double) longitude_degrees
+ + (double) longitude_minutes / 60
+ + (double) longitude_seconds / 3600;
+ else
+ zone.longitude = (double) longitude_degrees
+ - (double) longitude_minutes / 60
+ - (double) longitude_seconds / 3600;
+
+ icalarray_append (builtin_timezones, &zone);
+
+#if 0
+ printf ("Found zone: %s %f %f\n",
+ location, zone.latitude, zone.longitude);
+#endif
+ }
+
+ fclose (fp);
+}
+
+
+/** Loads the builtin VTIMEZONE data for the given timezone. */
+static void
+imcaltimezone_load_builtin_timezone (imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+ char *filename;
+ unsigned int filename_len;
+ FILE *fp;
+ icalparser *parser;
+ icalcomponent *comp, *subcomp;
+
+ /* If the location isn't set, it isn't a builtin timezone. */
+ if (!zone->location || !zone->location[0])
+ return;
+
+ filename_len = strlen (get_zone_directory()) + strlen (zone->location) + 6;
+
+ filename = (char*) malloc (filename_len);
+ if (!filename) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return;
+ }
+
+ snprintf (filename, filename_len, "%s/%s.ics", get_zone_directory(),
+ zone->location);
+
+ fp = fopen (filename, "r");
+ free (filename);
+ if (!fp) {
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return;
+ }
+
+
+ /* ##### B.# Sun, 11 Nov 2001 04:04:29 +1100
+ this is where the MALFORMEDDATA error is being set, after the call to 'icalparser_parse'
+ fprintf(stderr, "** WARNING ** %s: %d %s\n", __FILE__, __LINE__, icalerror_strerror(icalerrno));
+ */
+
+ parser = icalparser_new ();
+ icalparser_set_gen_data (parser, fp);
+ comp = icalparser_parse (parser, imcaltimezone_load_get_line_fn);
+ icalparser_free (parser);
+ fclose (fp);
+
+
+
+ /* Find the VTIMEZONE component inside the VCALENDAR. There should be 1. */
+ subcomp = icalcomponent_get_first_component (comp,
+ ICAL_VTIMEZONE_COMPONENT);
+ if (!subcomp) {
+ icalerror_set_errno(ICAL_PARSE_ERROR);
+ return;
+ }
+
+ imcaltimezone_get_vtimezone_properties (zone, subcomp, cal);
+
+ icalcomponent_remove_component(comp,subcomp);
+
+ icalcomponent_free(comp);
+
+}
+
+
+/** Callback used from icalparser_parse() */
+static char *
+imcaltimezone_load_get_line_fn (char *s,
+ size_t size,
+ void *data)
+{
+ return fgets (s, size, (FILE*) data);
+}
+
+
+
+
+/*
+ * DEBUGGING
+ */
+
+/**
+ * This outputs a list of timezone changes for the given timezone to the
+ * given file, up to the maximum year given. We compare this output with the
+ * output from 'vzic --dump-changes' to make sure that we are consistent.
+ * (vzic is the Olson timezone database to VTIMEZONE converter.)
+ *
+ * The output format is:
+ *
+ * Zone-Name [tab] Date [tab] Time [tab] UTC-Offset
+ *
+ * The Date and Time fields specify the time change in UTC.
+ *
+ * The UTC Offset is for local (wall-clock) time. It is the amount of time
+ * to add to UTC to get local time.
+ */
+int
+imcaltimezone_dump_changes (imcaltimezone *zone,
+ int max_year,
+ FILE *fp,
+ const struct imcaltimeobj *cal)
+{
+ static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ imcaltimezonechange *zone_change;
+ int change_num;
+ char buffer[8];
+
+ /* Make sure the changes array is expanded up to the given time. */
+ imcaltimezone_ensure_coverage (zone, max_year, cal);
+
+#if 0
+ printf ("Num changes: %i\n", zone->changes->num_elements);
+#endif
+
+ change_num = 0;
+ for (change_num = 0; change_num < zone->changes->num_elements; change_num++) {
+ zone_change = icalarray_element_at (zone->changes, change_num);
+
+ if (zone_change->year > max_year)
+ break;
+
+ fprintf (fp, "%s\t%2i %s %04i\t%2i:%02i:%02i",
+ zone->location,
+ zone_change->day, months[zone_change->month - 1],
+ zone_change->year,
+ zone_change->hour, zone_change->minute, zone_change->second);
+
+ /* Wall Clock Time offset from UTC. */
+ format_utc_offset (zone_change->utc_offset, buffer);
+ fprintf (fp, "\t%s", buffer);
+
+ fprintf (fp, "\n");
+ }
+ return 1;
+}
+
+
+/** This formats a UTC offset as "+HHMM" or "+HHMMSS".
+ buffer should have space for 8 characters. */
+static void
+format_utc_offset (int utc_offset,
+ char *buffer)
+{
+ char *sign = "+";
+ int hours, minutes, seconds;
+
+ if (utc_offset < 0) {
+ utc_offset = -utc_offset;
+ sign = "-";
+ }
+
+ hours = utc_offset / 3600;
+ minutes = (utc_offset % 3600) / 60;
+ seconds = utc_offset % 60;
+
+ /* Sanity check. Standard timezone offsets shouldn't be much more than 12
+ hours, and daylight saving shouldn't change it by more than a few hours.
+ (The maximum offset is 15 hours 56 minutes at present.) */
+ if (hours < 0 || hours >= 24 || minutes < 0 || minutes >= 60
+ || seconds < 0 || seconds >= 60) {
+ fprintf (stderr, "Warning: Strange timezone offset: H:%i M:%i S:%i\n",
+ hours, minutes, seconds);
+ }
+
+ if (seconds == 0)
+ sprintf (buffer, "%s%02i%02i", sign, hours, minutes);
+ else
+ sprintf (buffer, "%s%02i%02i%02i", sign, hours, minutes, seconds);
+}
+
+static char* get_zone_directory(void)
+{
+ return zone_files_directory == NULL ? ZONEINFO_DIRECTORY : zone_files_directory;
+}
+
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimezone.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimezone.h 1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.h 2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimezone.h
+ CREATOR: Damon Chaplin 15 March 2001
+
+ $Id: imcaltimezone.h,v 1.8 2003/10/21 18:28:27 ettore Exp $
+ $Locker: $
+
+ MODIFIED : Mohammad R. Ghorbani ghorbani bluehome net
+ Arash Yadegarnia arash bluehome net
+
+ (C) COPYRIGHT 2001, Damon Chaplin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+
+======================================================================*/
+/**
+ * @file imcaltimezone.h
+ * @brief timezone handling routines
+ */
+
+#ifndef imcaltimeZONE_H
+#define imcaltimeZONE_H
+
+#include <stdio.h> /* For FILE* */
+#include "imcaltime.h"
+#include "icalarray.h"
+#include "icalcomponent.h"
+
+
+#ifndef imcaltimeZONE_DEFINED
+#define imcaltimeZONE_DEFINED
+/** @brief An opaque struct representing a timezone.
+ * We declare this here to avoid a circular dependancy.
+ */
+typedef struct _imcaltimezone imcaltimezone;
+#endif
+
+/**
+ * @par Creating/Destroying individual imcaltimezones.
+ */
+
+/** Creates a new imcaltimezone. */
+imcaltimezone *imcaltimezone_new (void);
+
+/** Frees all memory used for the imcaltimezone. Set free_struct to free the
+ imcaltimezone struct as well. */
+void imcaltimezone_free (imcaltimezone *zone,
+ int free_struct);
+
+/**
+ * @par Accessing timezones.
+ */
+
+/** Free any builtin timezone information **/
+void imcaltimezone_free_builtin_timezones(void);
+
+/** Returns the array of builtin imcaltimezones. */
+icalarray* imcaltimezone_get_builtin_timezones (void);
+
+/** Returns a single builtin timezone, given its Olson city name. */
+imcaltimezone* imcaltimezone_get_builtin_timezone (const char *location);
+
+/** Returns a single builtin timezone, given its TZID. */
+imcaltimezone* imcaltimezone_get_builtin_timezone_from_tzid (const char *tzid,
+ const struct imcaltimeobj * cal);
+
+/** Returns the UTC timezone. */
+imcaltimezone* imcaltimezone_get_utc_timezone (void);
+
+/** Returns the TZID of a timezone. */
+char* imcaltimezone_get_tzid (imcaltimezone *zone,
+ const struct imcaltimeobj * cal);
+
+/** Returns the city name of a timezone. */
+char* imcaltimezone_get_location (imcaltimezone *zone);
+
+/** Returns the TZNAME properties used in the latest STANDARD and DAYLIGHT
+ components. If they are the same it will return just one, e.g. "LMT".
+ If they are different it will format them like "EST/EDT". Note that this
+ may also return NULL. */
+char* imcaltimezone_get_tznames (imcaltimezone *zone, const struct imcaltimeobj *);
+
+/** Returns the latitude of a builtin timezone. */
+double imcaltimezone_get_latitude (imcaltimezone *zone);
+
+/** Returns the longitude of a builtin timezone. */
+double imcaltimezone_get_longitude (imcaltimezone *zone);
+
+/** Returns the VTIMEZONE component of a timezone. */
+icalcomponent* imcaltimezone_get_component (imcaltimezone *zone, const struct imcaltimeobj *);
+
+/** Sets the VTIMEZONE component of an imcaltimezone, initializing the tzid,
+ location & tzname fields. It returns 1 on success or 0 on failure, i.e.
+ no TZID was found. */
+int imcaltimezone_set_component (imcaltimezone *zone,
+ icalcomponent *comp,
+ const struct imcaltimeobj * cal);
+
+char* imcaltimezone_get_display_name (imcaltimezone *zone,
+ const struct imcaltimeobj * cal);
+
+/**
+ * @par Converting times between timezones.
+ */
+
+void imcaltimezone_convert_time (struct icaltimetype *tt,
+ imcaltimezone *from_zone,
+ imcaltimezone *to_zone,
+ const struct imcaltimeobj * cal);
+
+
+/**
+ * @par Getting offsets from UTC.
+ */
+
+/** Calculates the UTC offset of a given local time in the given
+ timezone. It is the number of seconds to add to UTC to get local
+ time. The is_daylight flag is set to 1 if the time is in
+ daylight-savings time. */
+int imcaltimezone_get_utc_offset (imcaltimezone *zone,
+ struct icaltimetype *tt,
+ int *is_daylight,
+ const struct imcaltimeobj * cal);
+
+/** Calculates the UTC offset of a given UTC time in the given
+ timezone. It is the number of seconds to add to UTC to get local
+ time. The is_daylight flag is set to 1 if the time is in
+ daylight-savings time. */
+int imcaltimezone_get_utc_offset_of_utc_time (imcaltimezone *zone,
+ struct icaltimetype *tt,
+ int *is_daylight,
+ const struct imcaltimeobj * cal);
+
+
+
+/*
+ * Handling arrays of timezones. Mainly for internal use.
+ */
+icalarray* imcaltimezone_array_new (void);
+
+void imcaltimezone_array_append_from_vtimezone (icalarray *timezones,
+ icalcomponent *child,
+ const struct imcaltimeobj * cal);
+
+void imcaltimezone_array_free (icalarray *timezones);
+
+
+/*
+ * @par Handling the default location the timezone files
+ */
+
+/** Set the directory to look for the zonefiles */
+void set_zone_directory(char *path);
+
+/** Free memory dedicated to the zonefile directory */
+void free_zone_directory(void);
+
+/*
+ * @par Debugging Output.
+ */
+
+/** Dumps information about changes in the timezone up to and including
+ max_year. */
+int imcaltimezone_dump_changes (imcaltimezone *zone,
+ int max_year,
+ FILE *fp,
+ const struct imcaltimeobj * cal);
+
+#endif /* imcaltimeZONE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]