aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
Diffstat (limited to 'calendar')
-rw-r--r--calendar/ChangeLog23
-rw-r--r--calendar/cal-client/cal-client.c10
-rw-r--r--calendar/cal-client/cal-client.h5
-rw-r--r--calendar/cal-util/cal-component.c39
-rw-r--r--calendar/cal-util/cal-component.h4
-rw-r--r--calendar/cal-util/cal-recur.c267
-rw-r--r--calendar/cal-util/timeutil.c606
-rw-r--r--calendar/cal-util/timeutil.h123
-rw-r--r--calendar/gui/calendar-model.c100
-rw-r--r--calendar/gui/dialogs/cal-prefs-dialog.c2
-rw-r--r--calendar/gui/dialogs/comp-editor-util.c5
-rw-r--r--calendar/gui/dialogs/event-page.c7
-rw-r--r--calendar/gui/e-calendar-table.c1
-rw-r--r--calendar/gui/e-day-view-main-item.c30
-rw-r--r--calendar/gui/e-day-view-top-item.c8
-rw-r--r--calendar/gui/e-day-view.c25
-rw-r--r--calendar/gui/e-day-view.h2
-rw-r--r--calendar/gui/e-week-view.c12
-rw-r--r--calendar/gui/gnome-cal.c48
-rw-r--r--calendar/gui/print.c354
-rw-r--r--calendar/pcs/cal-backend-file.c5
-rw-r--r--calendar/pcs/query.c7
22 files changed, 1030 insertions, 653 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index b12f8a8d90..2b6bf179e0 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,26 @@
+2001-07-10 Damon Chaplin <damon@ximian.com>
+
+ * gui/calendar-model.c:
+ * gui/e-calendar-table.c:
+ * gui/e-day-view-main-item.c:
+ * gui/e-day-view-top-item.c:
+ * gui/e-day-view.[hc]:
+ * gui/e-week-view.c:
+ * gui/gnome-cal.c:
+ * gui/print.c:
+ * gui/dialogs/cal-prefs-dialog.c:
+ * gui/dialogs/comp-editor-util.c:
+ * gui/dialogs/event-page.c:
+ * pcs/cal-backend-file.c:
+ * pcs/query.c:
+ * cal-util/cal-component.[hc]:
+ * cal-util/cal-recur.c:
+ * cal-util/timeutil.[hc]:
+ * cal-client/cal-client.[hc]: more timezone updates. I'm pretty much
+ done with the calendar code now, except for alarms and conduits,
+ which Federico and JP know more about. And there are a couple of
+ other minor things to fix. But it is still pretty buggy.
+
2001-07-10 JP Rosevear <jpr@ximian.com>
* gui/dialogs/meeting-page.c: Add popup support so you can delete
diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c
index 8acbbc376a..dc81ec044a 100644
--- a/calendar/cal-client/cal-client.c
+++ b/calendar/cal-client/cal-client.c
@@ -833,6 +833,8 @@ cal_client_get_timezone (CalClient *client,
icalcomponent *icalcomp;
icaltimezone *tmp_zone;
+ g_print ("In cal_client_get_timezone: %s\n", tzid);
+
g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND);
g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_GET_NOT_FOUND);
@@ -845,12 +847,14 @@ cal_client_get_timezone (CalClient *client,
/* If tzid is NULL or "" we return NULL, since it is a 'local time'. */
if (!tzid || !tzid[0]) {
*zone = NULL;
+ g_print (" zone is local time (NULL)\n");
return CAL_CLIENT_GET_SUCCESS;
}
/* If it is UTC, we return the special UTC timezone. */
if (!strcmp (tzid, "UTC")) {
*zone = icaltimezone_get_utc_timezone ();
+ g_print (" zone is UTC\n");
return CAL_CLIENT_GET_SUCCESS;
}
@@ -858,12 +862,15 @@ cal_client_get_timezone (CalClient *client,
tmp_zone = g_hash_table_lookup (priv->timezones, tzid);
if (tmp_zone) {
*zone = tmp_zone;
+ g_print (" zone is in cache\n");
return CAL_CLIENT_GET_SUCCESS;
}
retval = CAL_CLIENT_GET_NOT_FOUND;
*zone = NULL;
+ g_print (" getting zone from server\n");
+
/* We don't already have it, so we try to get it from the server. */
CORBA_exception_init (&ev);
comp_str = GNOME_Evolution_Calendar_Cal_getTimezoneObject (priv->cal, (char *) tzid, &ev);
@@ -876,6 +883,7 @@ cal_client_get_timezone (CalClient *client,
goto out;
}
+ g_print (" parsing zone:\n%s\n", comp_str);
icalcomp = icalparser_parse_string (comp_str);
CORBA_free (comp_str);
@@ -884,6 +892,7 @@ cal_client_get_timezone (CalClient *client,
goto out;
}
+ g_print (" creating icaltimezone\n");
tmp_zone = icaltimezone_new ();
if (!tmp_zone) {
/* FIXME: Needs better error code - out of memory. Or just
@@ -901,6 +910,7 @@ cal_client_get_timezone (CalClient *client,
g_hash_table_insert (priv->timezones, icaltimezone_get_tzid (tmp_zone),
tmp_zone);
+ g_print (" returning icaltimezone\n");
*zone = tmp_zone;
retval = CAL_CLIENT_GET_SUCCESS;
diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h
index 12d04b70d4..4681574289 100644
--- a/calendar/cal-client/cal-client.h
+++ b/calendar/cal-client/cal-client.h
@@ -135,8 +135,13 @@ gboolean cal_client_get_alarms_for_object (CalClient *client, const char *uid,
time_t start, time_t end,
CalComponentAlarms **alarms);
+/* Add or update a single object. When adding an object only builtin timezones
+ are allowed. To use external VTIMEZONE data call update_objects() instead.*/
gboolean cal_client_update_object (CalClient *client, CalComponent *comp);
+/* Add or update multiple objects, possibly including VTIMEZONE data. */
+gboolean cal_client_update_objects (CalClient *client, icalcomponent *icalcomp);
+
gboolean cal_client_remove_object (CalClient *client, const char *uid);
CalQuery *cal_client_get_query (CalClient *client, const char *sexp);
diff --git a/calendar/cal-util/cal-component.c b/calendar/cal-util/cal-component.c
index 1ebc398e63..d340cea60f 100644
--- a/calendar/cal-util/cal-component.c
+++ b/calendar/cal-util/cal-component.c
@@ -4933,5 +4933,44 @@ cal_component_event_dates_match (CalComponent *comp1,
return TRUE;
}
+/* Returns TRUE if the TZIDs are equivalent, i.e. both NULL or the same. */
+static gboolean
+cal_component_compare_tzid (const char *tzid1, const char *tzid2)
+{
+ gboolean retval = TRUE;
+
+ if (tzid1) {
+ if (!tzid2 || strcmp (tzid1, tzid2))
+ retval = FALSE;
+ } else {
+ if (tzid2)
+ retval = FALSE;
+ }
+
+ return retval;
+}
+/* Returns TRUE if the component uses the given timezones for both DTSTART
+ and DTEND. */
+gboolean
+cal_component_compare_event_timezone (CalComponent *comp, icaltimezone *zone)
+{
+ CalComponentDateTime datetime;
+ const char *tzid;
+ gboolean match;
+ tzid = icaltimezone_get_tzid (zone);
+
+ cal_component_get_dtstart (comp, &datetime);
+ match = cal_component_compare_tzid (tzid, datetime.tzid);
+ cal_component_free_datetime (&datetime);
+ if (!match)
+ return FALSE;
+
+ /* FIXME: DURATION may be used instead. */
+ cal_component_get_dtend (comp, &datetime);
+ match = cal_component_compare_tzid (tzid, datetime.tzid);
+ cal_component_free_datetime (&datetime);
+
+ return match;
+}
diff --git a/calendar/cal-util/cal-component.h b/calendar/cal-util/cal-component.h
index 2dcc06ce61..f0628cb967 100644
--- a/calendar/cal-util/cal-component.h
+++ b/calendar/cal-util/cal-component.h
@@ -335,6 +335,10 @@ void cal_component_set_attendee_list (CalComponent *comp, GSList *attendee_list)
gboolean cal_component_event_dates_match (CalComponent *comp1, CalComponent *comp2);
+/* Returns TRUE if the component uses the given timezones for both DTSTART
+ and DTEND. */
+gboolean cal_component_compare_event_timezone (CalComponent *comp, icaltimezone *zone);
+
/* Functions to free returned values */
void cal_component_free_categories_list (GSList *categ_list);
diff --git a/calendar/cal-util/cal-recur.c b/calendar/cal-util/cal-recur.c
index 1e21f3109c..8df567fa5c 100644
--- a/calendar/cal-util/cal-recur.c
+++ b/calendar/cal-util/cal-recur.c
@@ -115,8 +115,8 @@ typedef struct {
int interval;
- /* Specifies the end of the recurrence. No occurrences are generated
- after this date. If it is 0, the event recurs forever. */
+ /* Specifies the end of the recurrence, inclusive. No occurrences are
+ generated after this date. If it is 0, the event recurs forever. */
time_t enddate;
/* WKST property - the week start day: 0 = Monday to 6 = Sunday. */
@@ -197,8 +197,13 @@ struct _CalObjTime {
guint8 hour; /* 0 - 23 */
guint8 minute; /* 0 - 59 */
guint8 second; /* 0 - 59 (maybe up to 61 for leap seconds) */
- guint8 is_rdate; /* TRUE if this is an RDATE, which may have an
- end or duration set. */
+ guint8 flags; /* The meaning of this depends on where the
+ CalObjTime is used. In most cases this is
+ set to TRUE to indicate that this is an
+ RDATE with an end or a duration set.
+ In the exceptions code, this is set to TRUE
+ to indicate that this is an EXDATE with a
+ DATE value. */
};
/* This is what we use to represent specific recurrence dates.
@@ -262,7 +267,8 @@ static void cal_recur_generate_instances_of_rule (CalComponent *comp,
gpointer tz_cb_data);
static CalRecurrence * cal_recur_from_icalproperty (icalproperty *prop,
- gboolean exception);
+ gboolean exception,
+ icaltimezone *zone);
static gint cal_recur_ical_weekday_to_weekday (enum icalrecurrencetype_weekday day);
static void cal_recur_free (CalRecurrence *r);
@@ -276,6 +282,7 @@ static void cal_object_compute_duration (CalObjTime *start,
static gboolean generate_instances_for_chunk (CalComponent *comp,
time_t comp_dtstart,
+ icaltimezone *zone,
GSList *rrules,
GSList *rdates,
GSList *exrules,
@@ -291,6 +298,7 @@ static gboolean generate_instances_for_chunk (CalComponent *comp,
gpointer cb_data);
static GArray* cal_obj_expand_recurrence (CalObjTime *event_start,
+ icaltimezone *zone,
CalRecurrence *recur,
CalObjTime *interval_start,
CalObjTime *interval_end,
@@ -458,11 +466,10 @@ static gint cal_obj_time_day_of_year (CalObjTime *cotime);
static void cal_obj_time_find_first_week (CalObjTime *cotime,
RecurData *recur_data);
static void cal_object_time_from_time (CalObjTime *cotime,
- time_t t);
-#if 0
-static gint cal_obj_date_only_compare_func (const void *arg1,
- const void *arg2);
-#endif
+ time_t t,
+ icaltimezone *zone);
+static gint cal_obj_date_only_compare_func (const void *arg1,
+ const void *arg2);
@@ -722,13 +729,14 @@ cal_recur_generate_instances_of_rule (CalComponent *comp,
/* Convert the interval start & end to CalObjTime. Note that if end
is -1 interval_end won't be set, so don't use it!
Also note that we use end - 1 since we want the interval to be
- inclusive as it makes the code simpler. */
- cal_object_time_from_time (&interval_start, start);
+ inclusive as it makes the code simpler. We do all calculation
+ in the timezone of the DTSTART. */
+ cal_object_time_from_time (&interval_start, start, start_zone);
if (end != -1)
- cal_object_time_from_time (&interval_end, end - 1);
+ cal_object_time_from_time (&interval_end, end - 1, start_zone);
- cal_object_time_from_time (&event_start, dtstart_time);
- cal_object_time_from_time (&event_end, dtend_time);
+ cal_object_time_from_time (&event_start, dtstart_time, start_zone);
+ cal_object_time_from_time (&event_end, dtend_time, start_zone);
/* Calculate the duration of the event, which we use for all
occurrences. We can't just subtract start from end since that may
@@ -776,10 +784,11 @@ cal_recur_generate_instances_of_rule (CalComponent *comp,
chunk_end.hour = 23;
chunk_end.minute = 59;
chunk_end.second = 61;
- chunk_end.is_rdate = FALSE;
+ chunk_end.flags = FALSE;
}
if (!generate_instances_for_chunk (comp, dtstart_time,
+ start_zone,
rrules, rdates,
exrules, exdates,
single_rule,
@@ -820,6 +829,8 @@ array_to_list (short *array, int max_elements)
/**
* cal_recur_from_icalproperty:
* @ir: An RRULE or EXRULE #icalproperty.
+ * @zone: The DTSTART timezone, used for converting the UNTIL property if it
+ * is given as a DATE value.
*
* Converts an #icalproperty to a #CalRecurrence. This should be
* freed using the cal_recur_free() function.
@@ -827,7 +838,8 @@ array_to_list (short *array, int max_elements)
* Return value: #CalRecurrence structure.
**/
static CalRecurrence *
-cal_recur_from_icalproperty (icalproperty *prop, gboolean exception)
+cal_recur_from_icalproperty (icalproperty *prop, gboolean exception,
+ icaltimezone *zone)
{
struct icalrecurrencetype ir;
CalRecurrence *r;
@@ -846,16 +858,31 @@ cal_recur_from_icalproperty (icalproperty *prop, gboolean exception)
r->interval = ir.interval;
if (ir.count != 0) {
+ /* If COUNT is set, we use the pre-calculated enddate. */
r->enddate = cal_recur_get_rule_end_date (prop);
} else {
- /* FIXME: icaltime_as_timet() seems to return -1 if UNTIL isn't
- set, but a simpler test would be better. */
- r->enddate = icaltime_as_timet (ir.until);
- if (r->enddate == -1)
+ if (icaltime_is_null_time (ir.until)) {
+ /* If neither COUNT or UNTIL is set, the event
+ recurs forever. */
r->enddate = 0;
- else if (ir.until.is_date)
- /* FIXME: Decide what to do here. */
- r->enddate = time_add_day (r->enddate, 1) - 1;
+ } else if (ir.until.is_date) {
+ /* If UNTIL is a DATE, we stop at the end of
+ the day, in local time (with the DTSTART timezone).
+ Note that UNTIL is inclusive so we stop before
+ midnight. */
+ ir.until.hour = 23;
+ ir.until.minute = 59;
+ ir.until.second = 59;
+
+ r->enddate = icaltime_as_timet_with_zone (ir.until,
+ zone);
+ } else {
+ /* If UNTIL is a DATE-TIME, it must be in UTC. */
+ icaltimezone *utc_zone;
+ utc_zone = icaltimezone_get_utc_timezone ();
+ r->enddate = icaltime_as_timet_with_zone (ir.until,
+ utc_zone);
+ }
}
r->week_start_day = cal_recur_ical_weekday_to_weekday (ir.week_start);
@@ -984,6 +1011,7 @@ cal_recur_free (CalRecurrence *r)
static gboolean
generate_instances_for_chunk (CalComponent *comp,
time_t comp_dtstart,
+ icaltimezone *zone,
GSList *rrules,
GSList *rdates,
GSList *exrules,
@@ -1003,7 +1031,7 @@ generate_instances_for_chunk (CalComponent *comp,
GSList *elem;
gint i;
time_t start_time, end_time;
- struct tm start_tm, end_tm;
+ struct icaltimetype start_tt, end_tt;
gboolean cb_status = TRUE, rule_finished, finished = TRUE;
#if 0
@@ -1041,9 +1069,9 @@ generate_instances_for_chunk (CalComponent *comp,
CalRecurrence *r;
prop = elem->data;
- r = cal_recur_from_icalproperty (prop, FALSE);
+ r = cal_recur_from_icalproperty (prop, FALSE, zone);
- tmp_occs = cal_obj_expand_recurrence (event_start, r,
+ tmp_occs = cal_obj_expand_recurrence (event_start, zone, r,
chunk_start,
chunk_end,
&rule_finished);
@@ -1058,16 +1086,26 @@ generate_instances_for_chunk (CalComponent *comp,
g_array_free (tmp_occs, TRUE);
}
- /* Add on specific occurrence dates, flag them as RDATEs, and store
- a pointer to the period in the rdate_periods array. */
+ /* Add on specific RDATE occurrence dates. If they have an end time
+ or duration set, flag them as RDATEs, and store a pointer to the
+ period in the rdate_periods array. Otherwise we can just treat them
+ as normal occurrences. */
for (elem = rdates; elem; elem = elem->next) {
CalComponentPeriod *p;
CalObjRecurrenceDate rdate;
- time_t t;
p = elem->data;
- t = icaltime_as_timet (p->start);
- cal_object_time_from_time (&cotime, t);
+
+ /* FIXME: We currently assume RDATEs are in the same timezone
+ as DTSTART. We should get the RDATE timezone and convert
+ to the DTSTART timezone first. */
+ cotime.year = p->start.year;
+ cotime.month = p->start.month - 1;
+ cotime.day = p->start.day;
+ cotime.hour = p->start.hour;
+ cotime.minute = p->start.minute;
+ cotime.second = p->start.second;
+ cotime.flags = FALSE;
/* If the rdate is after the current chunk we set finished
to FALSE, and we skip it. */
@@ -1078,10 +1116,11 @@ generate_instances_for_chunk (CalComponent *comp,
/* Check if the end date or duration is set. If it is we need
to store it so we can get it later. (libical seems to set
- second to -1 to denote an unset time. See icalvalue.c) */
+ second to -1 to denote an unset time. See icalvalue.c)
+ FIXME. */
if (p->type != CAL_COMPONENT_PERIOD_DATETIME
|| p->u.end.second != -1) {
- cotime.is_rdate = TRUE;
+ cotime.flags = TRUE;
rdate.start = cotime;
rdate.period = p;
@@ -1097,9 +1136,9 @@ generate_instances_for_chunk (CalComponent *comp,
CalRecurrence *r;
prop = elem->data;
- r = cal_recur_from_icalproperty (prop, FALSE);
+ r = cal_recur_from_icalproperty (prop, FALSE, zone);
- tmp_occs = cal_obj_expand_recurrence (event_start, r,
+ tmp_occs = cal_obj_expand_recurrence (event_start, zone, r,
chunk_start,
chunk_end,
&rule_finished);
@@ -1112,16 +1151,30 @@ generate_instances_for_chunk (CalComponent *comp,
/* Add on specific exception dates. */
for (elem = exdates; elem; elem = elem->next) {
CalComponentDateTime *cdt;
- time_t t;
-
- /* FIXME we should only be dealing with dates, not times too.
- No, I think it is supposed to be dates & times - Damon.
- I'm not sure what the semantics of just a date would be,
- since the event could recur several times each day. */
cdt = elem->data;
- t = icaltime_as_timet (*cdt->value);
- cal_object_time_from_time (&cotime, t);
+
+ /* FIXME: We currently assume EXDATEs are in the same timezone
+ as DTSTART. We should get the EXDATE timezone and convert
+ to the DTSTART timezone first. */
+ cotime.year = cdt->value->year;
+ cotime.month = cdt->value->month - 1;
+ cotime.day = cdt->value->day;
+
+ /* If the EXDATE has a DATE value, set the time to the start
+ of the day and set flags to TRUE so we know to skip all
+ occurrences on that date. */
+ if (cdt->value->is_date) {
+ cotime.hour = 0;
+ cotime.minute = 0;
+ cotime.second = 0;
+ cotime.flags = TRUE;
+ } else {
+ cotime.hour = cdt->value->hour;
+ cotime.minute = cdt->value->minute;
+ cotime.second = cdt->value->second;
+ cotime.flags = FALSE;
+ }
g_array_append_val (ex_occs, cotime);
}
@@ -1148,17 +1201,17 @@ generate_instances_for_chunk (CalComponent *comp,
g_print ("Checking occurrence: %s\n",
cal_obj_time_to_string (occ));
#endif
- start_tm.tm_year = occ->year - 1900;
- start_tm.tm_mon = occ->month;
- start_tm.tm_mday = occ->day;
- start_tm.tm_hour = occ->hour;
- start_tm.tm_min = occ->minute;
- start_tm.tm_sec = occ->second;
- start_tm.tm_isdst = -1;
- start_time = mktime (&start_tm);
+ start_tt.year = occ->year;
+ start_tt.month = occ->month + 1;
+ start_tt.day = occ->day;
+ start_tt.hour = occ->hour;
+ start_tt.minute = occ->minute;
+ start_tt.second = occ->second;
+ start_tt.is_daylight = -1;
+ start_time = icaltime_as_timet_with_zone (start_tt, zone);
if (start_time == -1) {
- g_warning ("mktime failed - time_t out of range?");
+ g_warning ("time_t out of range");
finished = TRUE;
break;
}
@@ -1177,7 +1230,10 @@ generate_instances_for_chunk (CalComponent *comp,
continue;
}
- if (occ->is_rdate) {
+ if (occ->flags) {
+ /* If it is an RDATE, we see if the end date or
+ duration was set. If not, we use the same duration
+ as the original occurrence. */
if (!cal_object_get_rdate_end (occ, rdate_periods)) {
cal_obj_time_add_days (occ, duration_days);
cal_obj_time_add_seconds (occ,
@@ -1188,17 +1244,17 @@ generate_instances_for_chunk (CalComponent *comp,
cal_obj_time_add_seconds (occ, duration_seconds);
}
- end_tm.tm_year = occ->year - 1900;
- end_tm.tm_mon = occ->month;
- end_tm.tm_mday = occ->day;
- end_tm.tm_hour = occ->hour;
- end_tm.tm_min = occ->minute;
- end_tm.tm_sec = occ->second;
- end_tm.tm_isdst = -1;
- end_time = mktime (&end_tm);
+ end_tt.year = occ->year;
+ end_tt.month = occ->month + 1;
+ end_tt.day = occ->day;
+ end_tt.hour = occ->hour;
+ end_tt.minute = occ->minute;
+ end_tt.second = occ->second;
+ end_tt.is_daylight = -1;
+ end_time = icaltime_as_timet_with_zone (end_tt, zone);
if (end_time == -1) {
- g_warning ("mktime failed - time_t out of range?");
+ g_warning ("time_t out of range");
finished = TRUE;
break;
}
@@ -1238,7 +1294,6 @@ cal_object_get_rdate_end (CalObjTime *occ,
CalObjRecurrenceDate *rdate = NULL;
CalComponentPeriod *p;
gint lower, upper, middle, cmp = 0;
- time_t t;
lower = 0;
upper = rdate_periods->len;
@@ -1267,8 +1322,16 @@ cal_object_get_rdate_end (CalObjTime *occ,
p = rdate->period;
if (p->type == CAL_COMPONENT_PERIOD_DATETIME) {
- t = icaltime_as_timet (p->u.end);
- cal_object_time_from_time (occ, t);
+ /* FIXME: We currently assume RDATEs are in the same timezone
+ as DTSTART. We should get the RDATE timezone and convert
+ to the DTSTART timezone first. */
+ occ->year = p->u.end.year;
+ occ->month = p->u.end.month - 1;
+ occ->day = p->u.end.day;
+ occ->hour = p->u.end.hour;
+ occ->minute = p->u.end.minute;
+ occ->second = p->u.end.second;
+ occ->flags = FALSE;
} else {
cal_obj_time_add_days (occ, p->u.duration.weeks * 7
+ p->u.duration.days);
@@ -1319,6 +1382,7 @@ cal_object_compute_duration (CalObjTime *start,
after the given interval.*/
static GArray*
cal_obj_expand_recurrence (CalObjTime *event_start,
+ icaltimezone *zone,
CalRecurrence *recur,
CalObjTime *interval_start,
CalObjTime *interval_end,
@@ -1346,7 +1410,7 @@ cal_obj_expand_recurrence (CalObjTime *event_start,
/* Compute the event_end, if the recur's enddate is set. */
if (recur->enddate > 0) {
cal_object_time_from_time (&event_end_cotime,
- recur->enddate);
+ recur->enddate, zone);
event_end = &event_end_cotime;
/* If the enddate is before the requested interval return. */
@@ -1653,7 +1717,7 @@ static CalRecurVTable* cal_obj_get_vtable (icalrecurrencetype_frequency recur_ty
vtable = &cal_obj_secondly_vtable;
break;
default:
- g_warning ("Unknown recurrence frequenct");
+ g_warning ("Unknown recurrence frequency");
vtable = NULL;
}
@@ -1836,15 +1900,15 @@ cal_obj_remove_exceptions (GArray *occs,
&& cal_obj_time_compare_func (occ, prev_occ) == 0) {
keep_occ = FALSE;
- /* If this occurrence is an RDATE, and the previous
- occurrence in the array was kept, set the RDATE flag
- of the last one, so we still use the end date
- or duration. */
- if (occ->is_rdate && !current_time_is_exception) {
+ /* If this occurrence is an RDATE with an end or
+ duration set, and the previous occurrence in the
+ array was kept, set the RDATE flag of the last one,
+ so we still use the end date or duration. */
+ if (occ->flags && !current_time_is_exception) {
last_occ_kept = &g_array_index (occs,
CalObjTime,
j - 1);
- last_occ_kept->is_rdate = TRUE;
+ last_occ_kept->flags = TRUE;
}
} else {
/* We've found a new occurrence time. Reset the flag
@@ -1857,9 +1921,14 @@ cal_obj_remove_exceptions (GArray *occs,
to one that matches or follows this
occurrence. */
while (ex_occ) {
- cmp = cal_obj_time_compare_func (ex_occ, occ);
- /* I'm pretty sure this is wrong. */
- /*cmp = cal_obj_date_only_compare_func (ex_occ, occ);*/
+ /* If the exception is an EXDATE with
+ a DATE value, we only have to
+ compare the date. */
+ if (ex_occ->flags)
+ cmp = cal_obj_date_only_compare_func (ex_occ, occ);
+ else
+ cmp = cal_obj_time_compare_func (ex_occ, occ);
+
if (cmp > 0)
break;
@@ -1886,6 +1955,10 @@ cal_obj_remove_exceptions (GArray *occs,
}
if (keep_occ) {
+ /* We are keeping this occurrence, so we move it to
+ the next free space, unless its position hasn't
+ changed (i.e. all previous occurrences were also
+ kept). */
if (i != j)
g_array_index (occs, CalObjTime, j)
= g_array_index (occs, CalObjTime, i);
@@ -3465,7 +3538,7 @@ cal_obj_time_compare_func (const void *arg1,
return retval;
}
-#if 0
+
static gint
cal_obj_date_only_compare_func (const void *arg1,
const void *arg2)
@@ -3492,7 +3565,7 @@ cal_obj_date_only_compare_func (const void *arg1,
return 0;
}
-#endif
+
/* Returns the weekday of the given CalObjTime, from 0 (Mon) - 6 (Sun). */
static gint
@@ -3590,23 +3663,21 @@ cal_obj_time_find_first_week (CalObjTime *cotime,
static void
-cal_object_time_from_time (CalObjTime *cotime,
- time_t t)
+cal_object_time_from_time (CalObjTime *cotime,
+ time_t t,
+ icaltimezone *zone)
{
- struct tm *tmp_tm;
- time_t tmp_time_t;
+ struct icaltimetype tt;
- tmp_time_t = t;
- /* FIXME */
- tmp_tm = localtime (&tmp_time_t);
+ tt = icaltime_from_timet_with_zone (t, FALSE, zone);
- cotime->year = tmp_tm->tm_year + 1900;
- cotime->month = tmp_tm->tm_mon;
- cotime->day = tmp_tm->tm_mday;
- cotime->hour = tmp_tm->tm_hour;
- cotime->minute = tmp_tm->tm_min;
- cotime->second = tmp_tm->tm_sec;
- cotime->is_rdate = FALSE;
+ cotime->year = tt.year;
+ cotime->month = tt.month - 1;
+ cotime->day = tt.day;
+ cotime->hour = tt.hour;
+ cotime->minute = tt.minute;
+ cotime->second = tt.second;
+ cotime->flags = FALSE;
}
@@ -3746,6 +3817,7 @@ cal_recur_get_rule_end_date (icalproperty *prop)
const char *xname, *xvalue;
icalvalue *value;
struct icaltimetype icaltime;
+ icaltimezone *utc_zone;
param = icalproperty_get_first_parameter (prop, ICAL_X_PARAMETER);
while (param) {
@@ -3758,7 +3830,9 @@ cal_recur_get_rule_end_date (icalproperty *prop)
icaltime = icalvalue_get_datetime (value);
icalvalue_free (value);
- return icaltime_as_timet (icaltime);
+ utc_zone = icaltimezone_get_utc_timezone ();
+ return icaltime_as_timet_with_zone (icaltime,
+ utc_zone);
}
}
@@ -3776,10 +3850,13 @@ cal_recur_set_rule_end_date (icalproperty *prop,
{
icalparameter *param;
icalvalue *value;
+ icaltimezone *utc_zone;
struct icaltimetype icaltime;
const char *end_date_string, *xname;
- icaltime = icaltime_from_timet (end_date, FALSE);
+ /* We save the value as a UTC DATE-TIME. */
+ utc_zone = icaltimezone_get_utc_timezone ();
+ icaltime = icaltime_from_timet_with_zone (end_date, FALSE, utc_zone);
value = icalvalue_new_datetime (icaltime);
end_date_string = icalvalue_as_ical_string (value);
icalvalue_free (value);
diff --git a/calendar/cal-util/timeutil.c b/calendar/cal-util/timeutil.c
index 3bb254dbf7..eb68376449 100644
--- a/calendar/cal-util/timeutil.c
+++ b/calendar/cal-util/timeutil.c
@@ -2,10 +2,10 @@
*
* Copyright (C) 1998 The Free Software Foundation
* Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 2000 Ximian, Inc.
*
* Authors: Federico Mena <federico@ximian.com>
* Miguel de Icaza <miguel@ximian.com>
+ * Damon Chaplin <damon@ximian.com>
*/
#include <string.h>
@@ -16,108 +16,36 @@
-void
-print_time_t (time_t t)
-{
- struct tm *tm = localtime (&t);
-
- printf ("%d/%02d/%02d %02d:%02d:%02d",
- 1900 + tm->tm_year, tm->tm_mon+1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
-}
-
-/**
- * isodate_from_time_t:
- * @t: A time value.
- *
- * Creates an ISO 8601 local time representation from a time value.
- *
- * Return value: String with the ISO 8601 representation of the local time.
- **/
-char *
-isodate_from_time_t (time_t t)
-{
- struct tm *tm;
- char isotime[40];
-
- tm = gmtime (&t);
- strftime (isotime, sizeof (isotime)-1, "%Y%m%dT%H%M%SZ", tm);
- return g_strdup (isotime);
-}
-
-/**
- * time_from_isodate:
- * @str: Date/time value in ISO 8601 format.
- *
- * Converts an ISO 8601 time string into a time_t value.
- *
- * Return value: Time_t corresponding to the specified ISO string.
- * Note that we only allow UTC times at present.
- **/
-time_t
-time_from_isodate (const char *str)
-{
- int len;
- struct tm my_tm;
- time_t t;
- int i;
- char *old_tz;
-
- g_return_val_if_fail (str != NULL, -1);
-
- /* yyyymmdd[Thhmmss[Z]] */
-
- len = strlen (str);
+#define REFORMATION_DAY 639787 /* First day of the reformation, counted from 1 Jan 1 */
+#define MISSING_DAYS 11 /* They corrected out 11 days */
+#define THURSDAY 4 /* First day of reformation */
+#define SATURDAY 6 /* Offset value; 1 Jan 1 was a Saturday */
- if (!(len == 8 || len == 15 || len == 16))
- return -1;
- for (i = 0; i < len; i++)
- if (!((i != 8 && i != 15 && isdigit (str[i]))
- || (i == 8 && str[i] == 'T')
- || (i == 15 && str[i] == 'Z')))
- return -1;
-
- memset (&my_tm, 0, sizeof (my_tm));
-
-#define digit_at(x,y) (x[y] - '0')
-
- my_tm.tm_year = (digit_at (str, 0) * 1000 + digit_at (str, 1) * 100 +
- digit_at (str, 2) * 10 + digit_at (str, 3)) - 1900;
-
- my_tm.tm_mon = digit_at (str, 4) * 10 + digit_at (str, 5) - 1;
- my_tm.tm_mday = digit_at (str, 6) * 10 + digit_at (str, 7);
-
- if (len > 8) {
- my_tm.tm_hour = digit_at (str, 9) * 10 + digit_at (str, 10);
- my_tm.tm_min = digit_at (str, 11) * 10 + digit_at (str, 12);
- my_tm.tm_sec = digit_at (str, 13) * 10 + digit_at (str, 14);
- }
+/* Number of days in a month, using 0 (Jan) to 11 (Dec). For leap years,
+ add 1 to February (month 1). */
+static const int days_in_month[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
- my_tm.tm_isdst = -1;
- old_tz = set_tz ("UTC");
- t = mktime (&my_tm);
- unset_tz (old_tz);
- return t;
-}
+/**************************************************************************
+ * time_t manipulation functions.
+ *
+ * NOTE: these use the Unix timezone functions like mktime() and localtime()
+ * and so should not be used in Evolution. New Evolution code should use
+ * icaltimetype values rather than time_t values wherever possible.
+ **************************************************************************/
-time_t
-time_add_minutes (time_t time, int minutes)
+static void
+print_time_t (time_t t)
{
- struct tm *tm = localtime (&time);
- time_t new_time;
-
- tm->tm_min += minutes;
- if ((new_time = mktime (tm)) == -1) {
- g_message ("time_add_minutes(): mktime() could not handle "
- "adding %d minutes with\n", minutes);
- print_time_t (time);
- printf ("\n");
- return time;
- }
- return new_time;
+ struct tm *tm = localtime (&t);
+
+ printf ("%d/%02d/%02d %02d:%02d:%02d",
+ 1900 + tm->tm_year, tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
}
/* Adds a day onto the time, using local time.
@@ -132,9 +60,6 @@ time_add_day (time_t time, int days)
{
struct tm *tm = localtime (&time);
time_t new_time;
-#if 0
- int dst_flag = tm->tm_isdst;
-#endif
tm->tm_mday += days;
tm->tm_isdst = -1;
@@ -147,18 +72,6 @@ time_add_day (time_t time, int days)
return time;
}
-#if 0
- /* I don't know what this is for. See also time_day_begin() and
- time_day_end(). - Damon. */
- if (dst_flag > tm->tm_isdst) {
- tm->tm_hour++;
- new_time += 3600;
- } else if (dst_flag < tm->tm_isdst) {
- tm->tm_hour--;
- new_time -= 3600;
- }
-#endif
-
return new_time;
}
@@ -197,63 +110,23 @@ time_add_month (time_t time, int months)
}
time_t
-time_add_year (time_t time, int years)
-{
- struct tm *tm = localtime (&time);
- time_t new_time;
-
- tm->tm_year += years;
- if ((new_time = mktime (tm)) == -1) {
- g_message ("time_add_year(): mktime() could not handling adding %d years with\n",
- years);
- print_time_t (time);
- printf ("\n");
- return time;
- }
- return new_time;
-}
-
-/* Number of days in a month, for normal and leap years */
-static const int days_in_month[2][12] = {
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
-};
-
-/* Returns whether the specified year is a leap year */
-static int
-is_leap_year (int year)
-{
- if (year <= 1752)
- return !(year % 4);
- else
- return (!(year % 4) && (year % 100)) || !(year % 400);
-}
-
-int
-time_days_in_month (int year, int month)
-{
- g_return_val_if_fail (year >= 1900, 0);
- g_return_val_if_fail ((month >= 0) && (month < 12), 0);
-
- return days_in_month [is_leap_year (year)][month];
-}
-
-time_t
-time_from_day (int year, int month, int day)
+time_year_begin (time_t t)
{
struct tm tm;
- memset (&tm, 0, sizeof (tm));
- tm.tm_year = year - 1900;
- tm.tm_mon = month;
- tm.tm_mday = day;
+ tm = *localtime (&t);
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
tm.tm_isdst = -1;
return mktime (&tm);
}
time_t
-time_year_begin (time_t t)
+time_month_begin (time_t t)
{
struct tm tm;
@@ -261,32 +134,37 @@ time_year_begin (time_t t)
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
- tm.tm_mon = 0;
tm.tm_mday = 1;
tm.tm_isdst = -1;
return mktime (&tm);
}
+/* Returns the start of the week. week_start_day should use the same values
+ as mktime(), i.e. 0 (Sun) to 6 (Sat). */
time_t
-time_year_end (time_t t)
+time_week_begin (time_t t, int week_start_day)
{
struct tm tm;
+ int offset;
tm = *localtime (&t);
+
+ /* Calculate the current offset from the week start day. */
+ offset = (tm.tm_wday + 7 - week_start_day) % 7;
+
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
- tm.tm_mon = 0;
- tm.tm_mday = 1;
- tm.tm_year++;
+ tm.tm_mday -= offset;
tm.tm_isdst = -1;
return mktime (&tm);
}
+/* Returns the start of the day, according to the local time. */
time_t
-time_month_begin (time_t t)
+time_day_begin (time_t t)
{
struct tm tm;
@@ -294,99 +172,397 @@ time_month_begin (time_t t)
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
- tm.tm_mday = 1;
tm.tm_isdst = -1;
return mktime (&tm);
}
+/* Returns the end of the day, according to the local time. */
time_t
-time_month_end (time_t t)
+time_day_end (time_t t)
{
struct tm tm;
tm = *localtime (&t);
+ tm.tm_mday++;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
- tm.tm_mday = 1;
- tm.tm_mon++;
tm.tm_isdst = -1;
return mktime (&tm);
}
-/* Returns the start of the week. week_start_day should use the same values
- as mktime(), i.e. 0 (Sun) to 6 (Sat). */
+
+/**************************************************************************
+ * time_t manipulation functions, using timezones in libical.
+ *
+ * NOTE: these are only here to make the transition to the timezone
+ * functions easier. New code should use icaltimetype values rather than
+ * time_t values wherever possible.
+ **************************************************************************/
+
+
+/* Adds or subtracts a number of days to/from the given time_t value, using
+ the given timezone.
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
time_t
-time_week_begin (time_t t, int week_start_day)
+time_add_day_with_zone (time_t time, int days, icaltimezone *zone)
{
- struct tm tm;
- int offset;
+ struct icaltimetype tt;
- tm = *localtime (&t);
+ /* Convert to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
- /* Calculate the current offset from the week start day. */
- offset = (tm.tm_wday + 7 - week_start_day) % 7;
+ /* Add/subtract the number of days. */
+ icaltime_adjust (&tt, days, 0, 0, 0);
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- tm.tm_mday -= offset;
- tm.tm_isdst = -1;
+ /* Convert back to a time_t. */
+ return icaltime_as_timet_with_zone (tt, zone);
+}
- return mktime (&tm);
+
+/* Adds or subtracts a number of weeks to/from the given time_t value, using
+ the given timezone.
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
+time_t
+time_add_week_with_zone (time_t time, int weeks, icaltimezone *zone)
+{
+ return time_add_day_with_zone (time, weeks * 7, zone);
}
-/* Returns the end of the week. week_start_day should use the same values
- as mktime(), i.e. 0 (Sun) to 6 (Sat). */
+
+/* Adds or subtracts a number of months to/from the given time_t value, using
+ the given timezone.
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
time_t
-time_week_end (time_t t, int week_start_day)
+time_add_month_with_zone (time_t time, int months, icaltimezone *zone)
{
- struct tm tm;
- int offset;
+ struct icaltimetype tt;
- tm = *localtime (&t);
+ /* Convert to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+
+ /* Add on the number of months. */
+ tt.month += months;
+
+ /* Normalize it, fixing any overflow. */
+ tt = icaltime_normalize (tt);
+
+ /* Convert back to a time_t. */
+ return icaltime_as_timet_with_zone (tt, zone);
+}
+
+
+/* Returns the start of the year containing the given time_t, using the given
+ timezone.
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
+time_t
+time_year_begin_with_zone (time_t time, icaltimezone *zone)
+{
+ struct icaltimetype tt;
+
+ /* Convert to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+
+ /* Set it to the start of the year. */
+ tt.month = 1;
+ tt.day = 1;
+ tt.hour = 0;
+ tt.minute = 0;
+ tt.second = 0;
+ tt.is_daylight = -1;
+
+ /* Convert back to a time_t. */
+ return icaltime_as_timet_with_zone (tt, zone);
+}
+
+
+/* Returns the start of the month containing the given time_t, using the given
+ timezone.
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
+time_t
+time_month_begin_with_zone (time_t time, icaltimezone *zone)
+{
+ struct icaltimetype tt;
+
+ /* Convert to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+
+ /* Set it to the start of the month. */
+ tt.day = 1;
+ tt.hour = 0;
+ tt.minute = 0;
+ tt.second = 0;
+ tt.is_daylight = -1;
+
+ /* Convert back to a time_t. */
+ return icaltime_as_timet_with_zone (tt, zone);
+}
+
+
+/* Returns the start of the week containing the given time_t, using the given
+ timezone. week_start_day should use the same values as mktime(),
+ i.e. 0 (Sun) to 6 (Sat).
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
+time_t
+time_week_begin_with_zone (time_t time, int week_start_day, icaltimezone *zone)
+{
+ struct icaltimetype tt;
+ int weekday, offset;
+
+ /* Convert to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
+
+ /* Get the weekday. */
+ weekday = time_day_of_week (tt.day, tt.month - 1, tt.year);
/* Calculate the current offset from the week start day. */
- offset = (tm.tm_wday + 7 - week_start_day) % 7;
+ offset = (weekday + 7 - week_start_day) % 7;
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- tm.tm_mday += 7 - offset;
- tm.tm_isdst = -1;
+ /* Set it to the start of the month. */
+ tt.day -= offset;
+ tt.hour = 0;
+ tt.minute = 0;
+ tt.second = 0;
+ tt.is_daylight = -1;
- return mktime (&tm);
+ /* Normalize it, to fix any overflow. */
+ tt = icaltime_normalize (tt);
+
+ /* Convert back to a time_t. */
+ return icaltime_as_timet_with_zone (tt, zone);
}
-/* Returns the start of the day, according to the local time. */
+
+/* Returns the start of the day containing the given time_t, using the given
+ timezone.
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
time_t
-time_day_begin (time_t t)
+time_day_begin_with_zone (time_t time, icaltimezone *zone)
{
- struct tm tm;
+ struct icaltimetype tt;
- tm = *localtime (&t);
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- tm.tm_isdst = -1;
+ /* Convert to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
- return mktime (&tm);
+ /* Set it to the start of the day. */
+ tt.hour = 0;
+ tt.minute = 0;
+ tt.second = 0;
+ tt.is_daylight = -1;
+
+ /* Convert back to a time_t. */
+ return icaltime_as_timet_with_zone (tt, zone);
}
-/* Returns the end of the day, according to the local time. */
+
+/* Returns the end of the day containing the given time_t, using the given
+ timezone. (The end of the day is the start of the next day.)
+ NOTE: this function is only here to make the transition to the timezone
+ functions easier. New code should use icaltimetype values and
+ icaltime_adjust() to add or subtract days, hours, minutes & seconds. */
time_t
-time_day_end (time_t t)
+time_day_end_with_zone (time_t time, icaltimezone *zone)
{
- struct tm tm;
+ struct icaltimetype tt;
- tm = *localtime (&t);
- tm.tm_mday++;
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- tm.tm_isdst = -1;
+ /* Convert to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
- return mktime (&tm);
+ /* Set it to the start of the next day. */
+ tt.day++;
+ tt.hour = 0;
+ tt.minute = 0;
+ tt.second = 0;
+ tt.is_daylight = -1;
+
+ /* Normalize it, to fix any overflow. */
+ tt = icaltime_normalize (tt);
+
+ /* Convert back to a time_t. */
+ return icaltime_as_timet_with_zone (tt, zone);
}
+
+
+/**************************************************************************
+ * General time functions.
+ **************************************************************************/
+
+
+/* Returns the number of days in the month. Year is the normal year, e.g. 2001.
+ Month is 0 (Jan) to 11 (Dec). */
+int
+time_days_in_month (int year, int month)
+{
+ int days;
+
+ g_return_val_if_fail (year >= 1900, 0);
+ g_return_val_if_fail ((month >= 0) && (month < 12), 0);
+
+ days = days_in_month[month];
+ if (month == 1 && time_is_leap_year (year))
+ days++;
+
+ return days;
+}
+
+
+/* Returns the 1-based day number within the year of the specified date.
+ Year is the normal year, e.g. 2001. Month is 0 to 11. */
+int
+time_day_of_year (int day, int month, int year)
+{
+ int i;
+
+ for (i = 0; i < month; i++) {
+ day += days_in_month[i];
+
+ if (month == 1 && time_is_leap_year (year))
+ day++;
+ }
+
+ return day;
+}
+
+
+/* Returns the day of the week for the specified date, 0 (Sun) to 6 (Sat).
+ For the days that were removed on the Gregorian reformation, it returns
+ Thursday. Year is the normal year, e.g. 2001. Month is 0 to 11. */
+int
+time_day_of_week (int day, int month, int year)
+{
+ int n;
+
+ n = (year - 1) * 365 + time_leap_years_up_to (year - 1)
+ + time_day_of_year (day, month, year);
+
+ if (n < REFORMATION_DAY)
+ return (n - 1 + SATURDAY) % 7;
+
+ if (n >= (REFORMATION_DAY + MISSING_DAYS))
+ return (n - 1 + SATURDAY - MISSING_DAYS) % 7;
+
+ return THURSDAY;
+}
+
+
+/* Returns whether the specified year is a leap year. Year is the normal year,
+ e.g. 2001. */
+gboolean
+time_is_leap_year (int year)
+{
+ if (year <= 1752)
+ return !(year % 4);
+ else
+ return (!(year % 4) && (year % 100)) || !(year % 400);
+}
+
+
+/* Returns the number of leap years since year 1 up to (but not including) the
+ specified year. Year is the normal year, e.g. 2001. */
+int
+time_leap_years_up_to (int year)
+{
+ /* There is normally a leap year every 4 years, except at the turn of
+ centuries since 1700. But there is a leap year on centuries since 1700
+ which are divisible by 400. */
+ return (year / 4
+ - ((year > 1700) ? (year / 100 - 17) : 0)
+ + ((year > 1600) ? ((year - 1600) / 400) : 0));
+}
+
+
+/**
+ * isodate_from_time_t:
+ * @t: A time value.
+ *
+ * Creates an ISO 8601 UTC representation from a time value.
+ *
+ * Return value: String with the ISO 8601 representation of the UTC time.
+ **/
+char *
+isodate_from_time_t (time_t t)
+{
+ struct tm *tm;
+ char isotime[40];
+
+ tm = gmtime (&t);
+ strftime (isotime, sizeof (isotime)-1, "%Y%m%dT%H%M%SZ", tm);
+ return g_strdup (isotime);
+}
+
+/**
+ * time_from_isodate:
+ * @str: Date/time value in ISO 8601 format.
+ *
+ * Converts an ISO 8601 UTC time string into a time_t value.
+ *
+ * Return value: Time_t corresponding to the specified ISO string.
+ * Note that we only allow UTC times at present.
+ **/
+time_t
+time_from_isodate (const char *str)
+{
+ struct icaltimetype tt = icaltime_null_time ();
+ icaltimezone *utc_zone;
+ int len, i;
+
+ g_return_val_if_fail (str != NULL, -1);
+
+ /* yyyymmdd[Thhmmss[Z]] */
+
+ len = strlen (str);
+
+ if (!(len == 8 || len == 15 || len == 16))
+ return -1;
+
+ for (i = 0; i < len; i++)
+ if (!((i != 8 && i != 15 && isdigit (str[i]))
+ || (i == 8 && str[i] == 'T')
+ || (i == 15 && str[i] == 'Z')))
+ return -1;
+
+#define digit_at(x,y) (x[y] - '0')
+
+ tt.year = digit_at (str, 0) * 1000
+ + digit_at (str, 1) * 100
+ + digit_at (str, 2) * 10
+ + digit_at (str, 3);
+
+ tt.month = digit_at (str, 4) * 10
+ + digit_at (str, 5);
+
+ tt.day = digit_at (str, 6) * 10
+ + digit_at (str, 7);
+
+ if (len > 8) {
+ tt.hour = digit_at (str, 9) * 10
+ + digit_at (str, 10);
+ tt.minute = digit_at (str, 11) * 10
+ + digit_at (str, 12);
+ tt.second = digit_at (str, 13) * 10
+ + digit_at (str, 14);
+ }
+
+ tt.is_daylight = -1;
+
+ utc_zone = icaltimezone_get_utc_timezone ();
+
+ return icaltime_as_timet_with_zone (tt, utc_zone);
+}
+
diff --git a/calendar/cal-util/timeutil.h b/calendar/cal-util/timeutil.h
index b01747ecfc..3679173572 100644
--- a/calendar/cal-util/timeutil.h
+++ b/calendar/cal-util/timeutil.h
@@ -2,10 +2,10 @@
*
* Copyright (C) 1998 The Free Software Foundation
* Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 2000 Ximian, Inc.
*
* Authors: Federico Mena <federico@ximian.com>
* Miguel de Icaza <miguel@ximian.com>
+ * Damon Chaplin <damon@ximian.com>
*/
#ifndef TIMEUTIL_H
@@ -14,52 +14,107 @@
#include <time.h>
#include <ical.h>
+#include <glib.h>
-char *isodate_from_time_t (time_t t);
-time_t time_from_isodate (const char *str);
+/**************************************************************************
+ * General time functions.
+ **************************************************************************/
-time_t time_add_minutes (time_t time, int minutes);
-time_t time_add_day (time_t time, int days);
-time_t time_add_week (time_t time, int weeks);
-time_t time_add_month (time_t time, int months);
-time_t time_add_year (time_t time, int years);
+/* Returns the number of days in the month. Year is the normal year, e.g. 2001.
+ Month is 0 (Jan) to 11 (Dec). */
+int time_days_in_month (int year, int month);
+/* Returns the 1-based day number within the year of the specified date.
+ Year is the normal year, e.g. 2001. Month is 0 to 11. */
+int time_day_of_year (int day, int month, int year);
-/* Returns the number of days in the specified month. Years are full years
- (starting from year 1). Months are in [0, 11]. */
-int time_days_in_month (int year, int month);
+/* Returns the day of the week for the specified date, 0 (Sun) to 6 (Sat).
+ For the days that were removed on the Gregorian reformation, it returns
+ Thursday. Year is the normal year, e.g. 2001. Month is 0 to 11. */
+int time_day_of_week (int day, int month, int year);
-/* Converts the specified date to a time_t at the start of the specified day.
- Years are full years (starting from year 1). Months are in [0, 11].
- Days are 1-based. */
-time_t time_from_day (int year, int month, int day);
+/* Returns whether the specified year is a leap year. Year is the normal year,
+ e.g. 2001. */
+gboolean time_is_leap_year (int year);
-/* For the functions below, time ranges are considered to contain the start
- time, but not the end time. */
+/* Returns the number of leap years since year 1 up to (but not including) the
+ specified year. Year is the normal year, e.g. 2001. */
+int time_leap_years_up_to (int year);
-/* These two functions take a time value and return the beginning or end of
- the corresponding year, respectively. */
-time_t time_year_begin (time_t t);
-time_t time_year_end (time_t t);
+/* Convert to or from an ISO 8601 representation of a time, in UTC,
+ e.g. "20010708T183000Z". */
+char *isodate_from_time_t (time_t t);
+time_t time_from_isodate (const char *str);
-/* These two functions take a time value and return the beginning or end of
- the corresponding month, respectively. */
-time_t time_month_begin (time_t t);
-time_t time_month_end (time_t t);
-/* These functions take a time value and return the beginning or end of the
- corresponding week, respectively. week_start_day should use the same values
+/**************************************************************************
+ * time_t manipulation functions.
+ *
+ * NOTE: these use the Unix timezone functions like mktime() and localtime()
+ * and so should not be used in Evolution. New Evolution code should use
+ * icaltimetype values rather than time_t values wherever possible.
+ **************************************************************************/
+
+/* Add or subtract a number of days, weeks or months. */
+time_t time_add_day (time_t time, int days);
+time_t time_add_week (time_t time, int weeks);
+time_t time_add_month (time_t time, int months);
+
+/* Returns the beginning of the year or month. */
+time_t time_year_begin (time_t t);
+time_t time_month_begin (time_t t);
+
+/* Returns the beginning of the week. week_start_day should use the same values
as mktime(), i.e. 0 (Sun) to 6 (Sat). */
-time_t time_week_begin (time_t t, int week_start_day);
-time_t time_week_end (time_t t, int week_start_day);
+time_t time_week_begin (time_t t, int week_start_day);
-/* These two functions take a time value and return the beginning or end of
- the corresponding day, respectively. */
-time_t time_day_begin (time_t t);
-time_t time_day_end (time_t t);
+/* Returns the beginning or end of the day. */
+time_t time_day_begin (time_t t);
+time_t time_day_end (time_t t);
-void print_time_t (time_t t);
+
+/**************************************************************************
+ * time_t manipulation functions, using timezones in libical.
+ *
+ * NOTE: these are only here to make the transition to the timezone
+ * functions easier. New code should use icaltimetype values rather than
+ * time_t values wherever possible.
+ **************************************************************************/
+
+/* Adds or subtracts a number of days to/from the given time_t value, using
+ the given timezone. */
+time_t time_add_day_with_zone (time_t time, int days, icaltimezone *zone);
+
+/* Adds or subtracts a number of weeks to/from the given time_t value, using
+ the given timezone. */
+time_t time_add_week_with_zone (time_t time, int weeks, icaltimezone *zone);
+
+/* Adds or subtracts a number of months to/from the given time_t value, using
+ the given timezone. */
+time_t time_add_month_with_zone (time_t time, int months, icaltimezone *zone);
+
+/* Returns the start of the year containing the given time_t, using the given
+ timezone. */
+time_t time_year_begin_with_zone (time_t time, icaltimezone *zone);
+
+/* Returns the start of the month containing the given time_t, using the given
+ timezone. */
+time_t time_month_begin_with_zone (time_t time, icaltimezone *zone);
+
+/* Returns the start of the week containing the given time_t, using the given
+ timezone. week_start_day should use the same values as mktime(),
+ i.e. 0 (Sun) to 6 (Sat). */
+time_t time_week_begin_with_zone (time_t time, int week_start_day,
+ icaltimezone *zone);
+
+/* Returns the start of the day containing the given time_t, using the given
+ timezone. */
+time_t time_day_begin_with_zone (time_t time, icaltimezone *zone);
+
+/* Returns the end of the day containing the given time_t, using the given
+ timezone. (The end of the day is the start of the next day.) */
+time_t time_day_end_with_zone (time_t time, icaltimezone *zone);
#endif
diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c
index 6d1625238d..10e18b106d 100644
--- a/calendar/gui/calendar-model.c
+++ b/calendar/gui/calendar-model.c
@@ -328,6 +328,10 @@ get_time_t (CalendarModel *model, time_t *t, gboolean show_midnight)
if (*t <= 0) {
buffer[0] = '\0';
} else {
+ /* Note that although the property may be in a different
+ timezone, we convert it to the current timezone to display
+ it in the table. If the user actually edits the value,
+ it will be set to the current timezone. See set_datetime. */
tt = icaltime_from_timet_with_zone (*t, FALSE,
model->priv->zone);
tmp_tm.tm_year = tt.year - 1900;
@@ -338,8 +342,8 @@ get_time_t (CalendarModel *model, time_t *t, gboolean show_midnight)
tmp_tm.tm_sec = tt.second;
tmp_tm.tm_isdst = -1;
- /* Call mktime() to set the weekday. */
- mktime (&tmp_tm);
+ tmp_tm.tm_wday = time_day_of_week (tt.day, tt.month - 1,
+ tt.year);
e_time_format_date_and_time (&tmp_tm,
model->priv->use_24_hour_format,
@@ -401,14 +405,13 @@ get_completed (CalendarModel *model,
struct icaltimetype *completed;
time_t t;
- /* FIXME: COMPLETED is in UTC, but we probably want to show it in
- the current timezone. */
-
cal_component_get_completed (comp, &completed);
if (!completed)
t = 0;
else {
+ /* Note that COMPLETED is stored in UTC, though we show it in
+ the current timezone. */
t = icaltime_as_timet_with_zone (*completed, icaltimezone_get_utc_timezone ());
cal_component_free_icaltimetype (completed);
}
@@ -424,8 +427,15 @@ get_and_free_datetime (CalendarModel *model, CalComponentDateTime dt)
if (!dt.value)
t = 0;
- else
- t = icaltime_as_timet (*dt.value);
+ else {
+ CalClientGetStatus status;
+ icaltimezone *zone;
+
+ /* FIXME: TIMEZONES: Handle error. */
+ status = cal_client_get_timezone (model->priv->client, dt.tzid,
+ &zone);
+ t = icaltime_as_timet_with_zone (*dt.value, zone);
+ }
cal_component_free_datetime (&dt);
@@ -601,7 +611,7 @@ is_complete (CalComponent *comp)
* get_color() below.
*/
static gboolean
-is_overdue (CalComponent *comp)
+is_overdue (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
gboolean retval;
@@ -613,7 +623,9 @@ is_overdue (CalComponent *comp)
if (!dt.value)
retval = FALSE;
else {
- time_t t;
+ struct icaltimetype now_tt;
+ CalClientGetStatus status;
+ icaltimezone *zone;
/* Second, is it already completed? */
@@ -624,9 +636,13 @@ is_overdue (CalComponent *comp)
/* Third, are we overdue as of right now? */
- t = icaltime_as_timet (*dt.value);
+ /* Get the current time in the same timezone as the DUE date.*/
+ /* FIXME: TIMEZONES: Handle error. */
+ status = cal_client_get_timezone (model->priv->client, dt.tzid,
+ &zone);
+ now_tt = icaltime_current_time_with_zone (zone);
- if (t <= time (NULL))
+ if (icaltime_compare (*dt.value, now_tt) <= 0)
retval = TRUE;
else
retval = FALSE;
@@ -641,7 +657,7 @@ is_overdue (CalComponent *comp)
/* Computes the color to be used to display a component */
static const char *
-get_color (CalComponent *comp)
+get_color (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
const char *retval;
@@ -653,8 +669,9 @@ get_color (CalComponent *comp)
if (!dt.value)
retval = NULL;
else {
- time_t t, t_now;
- struct tm tm, tm_now;
+ struct icaltimetype now_tt;
+ CalClientGetStatus status;
+ icaltimezone *zone;
/* Second, is it already completed? */
@@ -665,15 +682,13 @@ get_color (CalComponent *comp)
/* Third, is it due today? */
- t = icaltime_as_timet (*dt.value);
- tm = *localtime (&t);
-
- t_now = time (NULL);
- tm_now = *localtime (&t_now);
+ /* Get the current time in the same timezone as the DUE date.*/
+ /* FIXME: TIMEZONES: Handle error. */
+ status = cal_client_get_timezone (model->priv->client, dt.tzid,
+ &zone);
+ now_tt = icaltime_current_time_with_zone (zone);
- if (tm.tm_year == tm_now.tm_year
- && tm.tm_mon == tm_now.tm_mon
- && tm.tm_mday == tm_now.tm_mday) {
+ if (icaltime_compare_date_only (*dt.value, now_tt) == 0) {
retval = calendar_config_get_tasks_due_today_color ();
goto out;
}
@@ -683,7 +698,7 @@ get_color (CalComponent *comp)
* immediately.
*/
- if (t <= t_now)
+ if (icaltime_compare (*dt.value, now_tt) <= 0)
retval = calendar_config_get_tasks_overdue_color ();
else
retval = NULL;
@@ -811,10 +826,10 @@ calendar_model_value_at (ETableModel *etm, int col, int row)
return GINT_TO_POINTER (cal_component_has_recurrences (comp));
case CAL_COMPONENT_FIELD_OVERDUE:
- return GINT_TO_POINTER (is_overdue (comp));
+ return GINT_TO_POINTER (is_overdue (model, comp));
case CAL_COMPONENT_FIELD_COLOR:
- return (void *) get_color (comp);
+ return (void *) get_color (model, comp);
case CAL_COMPONENT_FIELD_STATUS:
return get_status (comp);
@@ -995,9 +1010,6 @@ set_completed (CalendarModel *model, CalComponent *comp, const char *value)
struct tm tmp_tm;
time_t t;
- /* FIXME: COMPLETED is in UTC, but we probably want to show it in
- the current timezone. */
-
status = e_time_parse_date_and_time (value, &tmp_tm);
if (status == E_TIME_PARSE_INVALID) {
@@ -1005,7 +1017,20 @@ set_completed (CalendarModel *model, CalComponent *comp, const char *value)
} else if (status == E_TIME_PARSE_NONE) {
ensure_task_not_complete (comp);
} else {
- t = mktime (&tmp_tm);
+ struct icaltimetype itt = icaltime_null_time ();
+
+ itt.year = tmp_tm.tm_year + 1900;
+ itt.month = tmp_tm.tm_mon + 1;
+ itt.day = tmp_tm.tm_mday;
+ itt.hour = tmp_tm.tm_hour;
+ itt.minute = tmp_tm.tm_min;
+ itt.second = tmp_tm.tm_sec;
+ itt.is_daylight = -1;
+
+ /* We assume that COMPLETED is entered in the current timezone,
+ even though it gets stored in UTC. */
+ t = icaltime_as_timet_with_zone (itt, model->priv->zone);
+
ensure_task_complete (comp, t);
}
}
@@ -2171,7 +2196,6 @@ ensure_task_complete (CalComponent *comp,
time_t completed_date)
{
struct icaltimetype *old_completed = NULL;
- struct icaltimetype new_completed;
int *old_percent, new_percent;
icalproperty_status status;
gboolean set_completed = TRUE;
@@ -2189,7 +2213,14 @@ ensure_task_complete (CalComponent *comp,
}
if (set_completed) {
- new_completed = icaltime_from_timet (completed_date, FALSE);
+ icaltimezone *utc_zone;
+ struct icaltimetype new_completed;
+
+ /* COMPLETED is stored in UTC. */
+ utc_zone = icaltimezone_get_utc_timezone ();
+ new_completed = icaltime_from_timet_with_zone (completed_date,
+ FALSE,
+ utc_zone);
cal_component_set_completed (comp, &new_completed);
}
@@ -2354,6 +2385,11 @@ calendar_model_set_timezone (CalendarModel *model,
{
g_return_if_fail (IS_CALENDAR_MODEL (model));
- if (model->priv->zone != zone)
+ if (model->priv->zone != zone) {
model->priv->zone = zone;
+
+ /* The timezone affects the times shown for COMPLETED and
+ maybe other fields, so we need to redisplay everything. */
+ e_table_model_changed (E_TABLE_MODEL (model));
+ }
}
diff --git a/calendar/gui/dialogs/cal-prefs-dialog.c b/calendar/gui/dialogs/cal-prefs-dialog.c
index 59acefc263..7176354a73 100644
--- a/calendar/gui/dialogs/cal-prefs-dialog.c
+++ b/calendar/gui/dialogs/cal-prefs-dialog.c
@@ -194,7 +194,7 @@ get_widgets (CalPrefsDialog *prefs)
priv->dialog = GW ("cal-prefs-dialog");
- /* The indices must match the mktime() values. */
+ /* The indices must be 0 (Sun) to 6 (Sat). */
priv->working_days[0] = GW ("sun_button");
priv->working_days[1] = GW ("mon_button");
priv->working_days[2] = GW ("tue_button");
diff --git a/calendar/gui/dialogs/comp-editor-util.c b/calendar/gui/dialogs/comp-editor-util.c
index dcad6a44cf..63dd407677 100644
--- a/calendar/gui/dialogs/comp-editor-util.c
+++ b/calendar/gui/dialogs/comp-editor-util.c
@@ -29,6 +29,7 @@
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include <e-util/e-time-utils.h>
+#include <cal-util/timeutil.h>
#include "../calendar-config.h"
#include "comp-editor-util.h"
@@ -109,9 +110,7 @@ write_label_piece (struct icaltimetype *tt, char *buffer, int size,
tmp_tm.tm_sec = tt->second;
tmp_tm.tm_isdst = -1;
- /* Call mktime() to set the weekday. FIXME: Don't do this. mktime()
- could in theory adjust the time if it thought it was invalid. */
- mktime (&tmp_tm);
+ tmp_tm.tm_wday = time_day_of_week (tt->day, tt->month - 1, tt->year);
len = strlen (buffer);
e_time_format_date_and_time (&tmp_tm,
diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c
index 6b6736f041..5d0249bbd0 100644
--- a/calendar/gui/dialogs/event-page.c
+++ b/calendar/gui/dialogs/event-page.c
@@ -698,6 +698,7 @@ date_changed_cb (EDateEdit *dedit, gpointer data)
&end_tt.minute);
g_assert (date_set);
+ /* FIXME: TIMEZONES. */
cmp = icaltime_compare (start_tt, end_tt);
if (cmp >= 0) {
if (cmp == 0 && start_tt.hour == 0
@@ -711,6 +712,9 @@ date_changed_cb (EDateEdit *dedit, gpointer data)
} else if (GTK_WIDGET (dedit) == priv->start_time) {
/* Modify the end time, to be the start + 1 hour. */
+ /* FIXME: TIMEZONES - Probably want to leave the
+ timezone as it is, so we need to convert the time.*/
+
end_tt = start_tt;
icaltime_adjust (&end_tt, 0, 1, 0, 0);
@@ -728,6 +732,9 @@ date_changed_cb (EDateEdit *dedit, gpointer data)
} else if (GTK_WIDGET (dedit) == priv->end_time) {
/* Modify the start time, to be the end - 1 hour. */
+ /* FIXME: TIMEZONES - Probably want to leave the
+ timezone as it is, so we need to convert the time.*/
+
start_tt = end_tt;
icaltime_adjust (&start_tt, 0, -1, 0, 0);
diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c
index 9f5726b01e..c5a66fccde 100644
--- a/calendar/gui/e-calendar-table.c
+++ b/calendar/gui/e-calendar-table.c
@@ -217,6 +217,7 @@ task_compare_cb (gconstpointer a, gconstpointer b)
if (due_a.value && due_b.value) {
int v;
+ /* FIXME: TIMEZONES. */
v = icaltime_compare (*due_a.value, *due_b.value);
if (v == 0)
diff --git a/calendar/gui/e-day-view-main-item.c b/calendar/gui/e-day-view-main-item.c
index cc6224987a..d65193b08b 100644
--- a/calendar/gui/e-day-view-main-item.c
+++ b/calendar/gui/e-day-view-main-item.c
@@ -467,7 +467,7 @@ e_day_view_main_item_draw_day_event (EDayViewMainItem *dvmitem,
CalComponent *comp;
gint num_icons, icon_x, icon_y, icon_x_inc, icon_y_inc;
gint max_icon_w, max_icon_h;
- gboolean draw_reminder_icon, draw_recurrence_icon;
+ gboolean draw_reminder_icon, draw_recurrence_icon, draw_timezone_icon;
GSList *categories_list, *elem;
day_view = dvmitem->day_view;
@@ -563,6 +563,7 @@ e_day_view_main_item_draw_day_event (EDayViewMainItem *dvmitem,
num_icons = 0;
draw_reminder_icon = FALSE;
draw_recurrence_icon = FALSE;
+ draw_timezone_icon = FALSE;
icon_x = item_x + E_DAY_VIEW_BAR_WIDTH + E_DAY_VIEW_ICON_X_PAD;
icon_y = item_y + E_DAY_VIEW_EVENT_BORDER_HEIGHT
+ E_DAY_VIEW_ICON_Y_PAD;
@@ -578,6 +579,14 @@ e_day_view_main_item_draw_day_event (EDayViewMainItem *dvmitem,
num_icons++;
}
+ /* If the DTSTART or DTEND are in a different timezone to our current
+ timezone, we display the timezone icon. */
+ if (!cal_component_compare_event_timezone (comp, day_view->zone)) {
+ draw_timezone_icon = TRUE;
+ num_icons++;
+ }
+
+
cal_component_get_categories_list (comp, &categories_list);
num_icons += g_slist_length (categories_list);
@@ -632,6 +641,25 @@ e_day_view_main_item_draw_day_event (EDayViewMainItem *dvmitem,
icon_y += icon_y_inc;
}
+ if (draw_timezone_icon) {
+ max_icon_w = item_x + item_w - icon_x
+ - E_DAY_VIEW_EVENT_BORDER_WIDTH;
+ max_icon_h = item_y + item_h - icon_y
+ - E_DAY_VIEW_EVENT_BORDER_HEIGHT;
+
+ gdk_gc_set_clip_origin (gc, icon_x, icon_y);
+ gdk_gc_set_clip_mask (gc, day_view->timezone_mask);
+ gdk_draw_pixmap (drawable, gc,
+ day_view->timezone_icon,
+ 0, 0, icon_x, icon_y,
+ MIN (E_DAY_VIEW_ICON_WIDTH,
+ max_icon_w),
+ MIN (E_DAY_VIEW_ICON_HEIGHT,
+ max_icon_h));
+ icon_x += icon_x_inc;
+ icon_y += icon_y_inc;
+ }
+
/* draw categories icons */
for (elem = categories_list; elem; elem = elem->next) {
char *category;
diff --git a/calendar/gui/e-day-view-top-item.c b/calendar/gui/e-day-view-top-item.c
index 1417dfee1e..237e7589ba 100644
--- a/calendar/gui/e-day-view-top-item.c
+++ b/calendar/gui/e-day-view-top-item.c
@@ -31,6 +31,7 @@
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include "e-util/e-categories-config.h"
+#include "cal-util/timeutil.h"
#include "e-day-view-top-item.h"
static void e_day_view_top_item_class_init (EDayViewTopItemClass *class);
@@ -274,10 +275,9 @@ e_day_view_top_item_draw (GnomeCanvasItem *canvas_item,
day_start.tm_mday = day_start_tt.day;
day_start.tm_isdst = -1;
- /* Call mktime() to set the weekday. FIXME: Don't do this.
- mktime() could in theory adjust the time if it thought it
- was invalid. */
- mktime (&day_start);
+ day_start.tm_wday = time_day_of_week (day_start_tt.day,
+ day_start_tt.month - 1,
+ day_start_tt.year);
if (day_view->date_format == E_DAY_VIEW_DATE_FULL)
/* strftime format %A = full weekday name, %d = day of month,
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index d8e9736449..9e38224bb0 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -61,6 +61,7 @@
/* Images */
#include "art/bell.xpm"
#include "art/recur.xpm"
+#include "art/timezone-16.xpm"
/* The minimum amount of space wanted on each side of the date string. */
#define E_DAY_VIEW_DATE_X_PAD 4
@@ -992,6 +993,7 @@ e_day_view_realize (GtkWidget *widget)
/* Create the pixmaps. */
day_view->reminder_icon = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &day_view->reminder_mask, NULL, bell_xpm);
day_view->recurrence_icon = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &day_view->recurrence_mask, NULL, recur_xpm);
+ day_view->timezone_icon = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &day_view->timezone_mask, NULL, timezone_16_xpm);
@@ -2087,7 +2089,7 @@ e_day_view_set_selected_time_range (EDayView *day_view,
start of the day given by start_time, otherwise it is the previous
work-week start day. */
if (!day_view->work_week_view) {
- lower = time_day_begin (start_time);
+ lower = time_day_begin_with_zone (start_time, day_view->zone);
} else {
lower = e_day_view_find_work_week_start (day_view, start_time);
}
@@ -2150,6 +2152,7 @@ e_day_view_find_work_week_start (EDayView *day_view,
{
GDate date;
gint weekday, day, i, offset;
+ struct icaltimetype tt = icaltime_null_time ();
g_date_clear (&date, 1);
g_date_set_time (&date, start_time);
@@ -2175,9 +2178,11 @@ e_day_view_find_work_week_start (EDayView *day_view,
g_date_subtract_days (&date, offset);
- return time_from_day (g_date_year (&date),
- g_date_month (&date) - 1,
- g_date_day (&date));
+ tt.year = g_date_year (&date);
+ tt.month = g_date_month (&date);
+ tt.day = g_date_day (&date);
+
+ return icaltime_as_timet_with_zone (tt, day_view->zone);
}
@@ -2229,11 +2234,13 @@ e_day_view_recalc_day_starts (EDayView *day_view,
day_view->day_starts[0] = start_time;
for (day = 1; day <= day_view->days_shown; day++) {
- day_view->day_starts[day] = time_add_day (day_view->day_starts[day - 1], 1);
+ day_view->day_starts[day] = time_add_day_with_zone (day_view->day_starts[day - 1], 1, day_view->zone);
}
+#if 0
for (day = 0; day <= day_view->days_shown; day++)
g_print ("Day Starts %i: %s", day, ctime (&day_view->day_starts[day]));
+#endif
day_view->lower = start_time;
day_view->upper = day_view->day_starts[day_view->days_shown];
@@ -4508,6 +4515,10 @@ e_day_view_reshape_long_event (EDayView *day_view,
if (cal_component_has_recurrences (comp))
num_icons++;
+ if (!cal_component_compare_event_timezone (comp,
+ day_view->zone))
+ num_icons++;
+
cal_component_get_categories_list (comp, &categories_list);
num_icons += g_slist_length (categories_list);
cal_component_free_categories_list (categories_list);
@@ -4645,6 +4656,10 @@ e_day_view_reshape_day_event (EDayView *day_view,
if (cal_component_has_recurrences (comp))
num_icons++;
+ if (!cal_component_compare_event_timezone (comp,
+ day_view->zone))
+ num_icons++;
+
cal_component_get_categories_list (comp, &categories_list);
num_icons += g_slist_length (categories_list);
cal_component_free_categories_list (categories_list);
diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h
index 94354244ba..bddc36b708 100644
--- a/calendar/gui/e-day-view.h
+++ b/calendar/gui/e-day-view.h
@@ -360,6 +360,8 @@ struct _EDayView
GdkBitmap *reminder_mask;
GdkPixmap *recurrence_icon;
GdkBitmap *recurrence_mask;
+ GdkPixmap *timezone_icon;
+ GdkBitmap *timezone_mask;
/* Colors for drawing. */
GdkColor colors[E_DAY_VIEW_COLOR_LAST];
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index a31961dd98..264827e590 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -1253,8 +1253,10 @@ e_week_view_set_selected_time_range (EWeekView *week_view,
if (!g_date_valid (&week_view->first_day_shown)
|| g_date_compare (&week_view->first_day_shown, &base_date)) {
week_view->first_day_shown = base_date;
- start_time = time_add_day (start_time, -day_offset);
- start_time = time_day_begin (start_time);
+ start_time = time_add_day_with_zone (start_time, -day_offset,
+ week_view->zone);
+ start_time = time_day_begin_with_zone (start_time,
+ week_view->zone);
e_week_view_recalc_day_starts (week_view, start_time);
update_query (week_view);
}
@@ -1263,7 +1265,8 @@ e_week_view_set_selected_time_range (EWeekView *week_view,
week_view->selection_start_day = g_date_julian (&date)
- g_date_julian (&base_date);
if (end_time == start_time
- || end_time <= time_add_day (start_time, 1))
+ || end_time <= time_add_day_with_zone (start_time, 1,
+ week_view->zone))
week_view->selection_end_day = week_view->selection_start_day;
else {
g_date_clear (&end_date, 1);
@@ -1426,7 +1429,8 @@ e_week_view_recalc_day_starts (EWeekView *week_view,
tmp_time = lower;
week_view->day_starts[0] = tmp_time;
for (day = 1; day <= num_days; day++) {
- tmp_time = time_add_day (tmp_time, 1);
+ tmp_time = time_add_day_with_zone (tmp_time, 1,
+ week_view->zone);
week_view->day_starts[day] = tmp_time;
}
}
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 5ea48a4d6e..166f715fa4 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -351,19 +351,14 @@ static struct tm
get_current_time (ECalendarItem *calitem, gpointer data)
{
GnomeCalendar *cal = data;
- char *location;
- icaltimezone *zone;
struct tm tmp_tm = { 0 };
struct icaltimetype tt;
g_return_val_if_fail (cal != NULL, tmp_tm);
g_return_val_if_fail (GNOME_IS_CALENDAR (cal), tmp_tm);
- /* Get the current timezone. */
- location = calendar_config_get_timezone ();
- zone = icaltimezone_get_builtin_timezone (location);
-
- tt = icaltime_from_timet_with_zone (time (NULL), FALSE, zone);
+ tt = icaltime_from_timet_with_zone (time (NULL), FALSE,
+ cal->priv->zone);
/* Now copy it to the struct tm and return it. */
tmp_tm.tm_year = tt.year - 1900;
@@ -505,8 +500,9 @@ gnome_calendar_init (GnomeCalendar *gcal)
setup_widgets (gcal);
- priv->selection_start_time = time_day_begin (time (NULL));
- priv->selection_end_time = time_add_day (priv->selection_start_time, 1);
+ priv->selection_start_time = time_day_begin_with_zone (time (NULL),
+ priv->zone);
+ priv->selection_end_time = time_add_day_with_zone (priv->selection_start_time, 1, priv->zone);
priv->view_collection = NULL;
priv->view_menus = NULL;
@@ -585,8 +581,9 @@ gnome_calendar_goto (GnomeCalendar *gcal, time_t new_time)
priv = gcal->priv;
- priv->selection_start_time = time_day_begin (new_time);
- priv->selection_end_time = time_add_day (priv->selection_start_time, 1);
+ priv->selection_start_time = time_day_begin_with_zone (new_time,
+ priv->zone);
+ priv->selection_end_time = time_add_day_with_zone (priv->selection_start_time, 1, priv->zone);
gnome_calendar_update_view_times (gcal);
gnome_calendar_update_date_navigator (gcal);
@@ -644,23 +641,31 @@ gnome_calendar_direction (GnomeCalendar *gcal, int direction)
switch (priv->current_view_type) {
case GNOME_CAL_DAY_VIEW:
- start_time = time_add_day (start_time, direction);
- end_time = time_add_day (end_time, direction);
+ start_time = time_add_day_with_zone (start_time, direction,
+ priv->zone);
+ end_time = time_add_day_with_zone (end_time, direction,
+ priv->zone);
break;
case GNOME_CAL_WORK_WEEK_VIEW:
- start_time = time_add_week (start_time, direction);
- end_time = time_add_week (end_time, direction);
+ start_time = time_add_week_with_zone (start_time, direction,
+ priv->zone);
+ end_time = time_add_week_with_zone (end_time, direction,
+ priv->zone);
break;
case GNOME_CAL_WEEK_VIEW:
- start_time = time_add_week (start_time, direction);
- end_time = time_add_week (end_time, direction);
+ start_time = time_add_week_with_zone (start_time, direction,
+ priv->zone);
+ end_time = time_add_week_with_zone (end_time, direction,
+ priv->zone);
break;
case GNOME_CAL_MONTH_VIEW:
- start_time = time_add_month (start_time, direction);
- end_time = time_add_month (end_time, direction);
+ start_time = time_add_month_with_zone (start_time, direction,
+ priv->zone);
+ end_time = time_add_month_with_zone (end_time, direction,
+ priv->zone);
break;
default:
@@ -704,8 +709,9 @@ gnome_calendar_dayjump (GnomeCalendar *gcal, time_t time)
priv = gcal->priv;
- priv->selection_start_time = time_day_begin (time);
- priv->selection_end_time = time_add_day (priv->selection_start_time, 1);
+ priv->selection_start_time = time_day_begin_with_zone (time,
+ priv->zone);
+ priv->selection_end_time = time_add_day_with_zone (priv->selection_start_time, 1, priv->zone);
if (priv->day_button)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->day_button), TRUE);
diff --git a/calendar/gui/print.c b/calendar/gui/print.c
index c4feb28575..5fda525e71 100644
--- a/calendar/gui/print.c
+++ b/calendar/gui/print.c
@@ -95,17 +95,8 @@
#define DAY_VIEW_EVENT_X_PAD 8
-/* copied from gnome-month-item.c this should be shared?? */
-
-/* Number of days in a month, for normal and leap years */
-static const int days_in_month[2][12] = {
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
-};
-
-/* The weird month of September 1752, where 3 Sep through 13 Sep were eliminated due to the
- * Gregorian reformation.
- */
+/* The weird month of September 1752, where 3 Sep through 13 Sep were
+ eliminated due to the Gregorian reformation. */
static const int sept_1752[42] = {
0, 0, 1, 2, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23,
@@ -114,11 +105,6 @@ static const int sept_1752[42] = {
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
};
-
-#define REFORMATION_DAY 639787 /* First day of the reformation, counted from 1 Jan 1 */
-#define MISSING_DAYS 11 /* They corrected out 11 days */
-#define THURSDAY 4 /* First day of reformation */
-#define SATURDAY 6 /* Offset value; 1 Jan 1 was a Saturday */
#define SEPT_1752_START 2 /* Start day within month */
#define SEPT_1752_END 20 /* End day within month */
@@ -175,58 +161,43 @@ struct einfo
static const GnomePaper *paper_info = NULL;
-/* Returns the number of leap years since year 1 up to (but not including) the specified year */
-static int
-leap_years_up_to (int year)
-{
- return (year / 4 /* trivial leapness */
- - ((year > 1700) ? (year / 100 - 17) : 0) /* minus centuries since 1700 */
- + ((year > 1600) ? ((year - 1600) / 400) : 0)); /* plus centuries since 1700 divisible by 400 */
-}
-/* Returns whether the specified year is a leap year */
-static int
-is_leap_year (int year)
+/* Convenience function to help the transition to timezone functions.
+ It returns the current timezone. */
+static icaltimezone*
+get_timezone (void)
{
- if (year <= 1752)
- return !(year % 4);
- else
- return (!(year % 4) && (year % 100)) || !(year % 400);
+ char *location = calendar_config_get_timezone ();
+ return icaltimezone_get_builtin_timezone (location);
}
-/* Returns the 1-based day number within the year of the specified date */
-static int
-day_in_year (int day, int month, int year)
-{
- int is_leap, i;
-
- is_leap = is_leap_year (year);
- for (i = 0; i < month; i++)
- day += days_in_month [is_leap][i];
-
- return day;
-}
-
-/* Returns the day of the week (zero-based, zero is Sunday) for the specified date. For the days
- * that were removed on the Gregorian reformation, it returns Thursday.
- */
-static int
-day_in_week (int day, int month, int year)
+/* Convenience function to help the transition to timezone functions.
+ It converts a time_t to a struct tm. */
+static struct tm*
+convert_timet_to_struct_tm (time_t time, icaltimezone *zone)
{
- int n;
+ static struct tm my_tm;
+ struct icaltimetype tt;
- n = (year - 1) * 365 + leap_years_up_to (year - 1) + day_in_year (day, month, year);
+ /* Convert it to an icaltimetype. */
+ tt = icaltime_from_timet_with_zone (time, FALSE, zone);
- if (n < REFORMATION_DAY)
- return (n - 1 + SATURDAY) % 7;
+ /* Fill in the struct tm. */
+ my_tm.tm_year = tt.year - 1900;
+ my_tm.tm_mon = tt.month - 1;
+ my_tm.tm_mday = tt.day;
+ my_tm.tm_hour = tt.hour;
+ my_tm.tm_min = tt.minute;
+ my_tm.tm_sec = tt.second;
+ my_tm.tm_isdst = tt.is_daylight;
- if (n >= (REFORMATION_DAY + MISSING_DAYS))
- return (n - 1 + SATURDAY - MISSING_DAYS) % 7;
+ my_tm.tm_wday = time_day_of_week (tt.day, tt.month - 1, tt.year);
- return THURSDAY;
+ return &my_tm;
}
+
/* Fills the 42-element days array with the day numbers for the specified month. Slots outside the
* bounds of the month are filled with zeros. The starting and ending indexes of the days are
* returned in the start and end arguments.
@@ -254,9 +225,9 @@ build_month (int month, int year, int *days, int *start, int *end)
for (i = 0; i < 42; i++)
days[i] = 0;
- d_month = days_in_month[is_leap_year (year)][month];
+ d_month = time_days_in_month (year, month);
/* Get the start weekday in the month, 0=Sun to 6=Sat. */
- d_week = day_in_week (1, month, year);
+ d_week = time_day_of_week (1, month, year);
/* Get the configuration setting specifying which weekday we put on
the left column, 0=Sun to 6=Sat. */
@@ -463,10 +434,12 @@ static char *days[] = {
static char *
format_date(time_t time, int flags, char *buffer, int bufflen)
{
+ icaltimezone *zone = get_timezone ();
char fmt[64];
struct tm tm;
- tm = *localtime(&time);
+ tm = *convert_timet_to_struct_tm (time, zone);
+
fmt[0] = 0;
if (flags & DATE_DAYNAME) {
strcat(fmt, "%A");
@@ -502,6 +475,7 @@ print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal, time_t month,
int titleflags, time_t greystart, time_t greyend,
int bordertitle)
{
+ icaltimezone *zone = get_timezone ();
CalClient *client;
GnomeFont *font, *font_bold, *font_normal;
time_t now, next;
@@ -552,7 +526,7 @@ print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal, time_t month,
/* get month days */
- tm = *localtime (&month);
+ tm = *convert_timet_to_struct_tm (month, zone);
build_month (tm.tm_mon, tm.tm_year + 1900, days, 0, 0);
font_normal = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0,
@@ -580,7 +554,7 @@ print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal, time_t month,
top -= row_height * 1.4;
- now = time_month_begin (month);
+ now = time_month_begin_with_zone (month, zone);
for (y = 0; y < 6; y++) {
cell_top = top - y * row_height;
@@ -605,11 +579,11 @@ print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal, time_t month,
/* this is a slow messy way to do this ... but easy ... */
uids = cal_client_get_objects_in_range (client,
CALOBJ_TYPE_EVENT,
- now, time_day_end (now));
+ now, time_day_end_with_zone (now, zone));
font = uids ? font_bold : font_normal;
cal_obj_uid_list_free (uids);
- next = time_add_day (now, 1);
+ next = time_add_day_with_zone (now, 1, zone);
if ((now >= greystart && now < greyend)
|| (greystart >= now && greystart < next)) {
print_border (pc,
@@ -831,9 +805,10 @@ print_day_add_event (CalComponent *comp,
GArray **events)
{
+ icaltimezone *zone = get_timezone ();
EDayViewEvent event;
gint day, offset;
- struct tm start_tm, end_tm;
+ struct icaltimetype start_tt, end_tt;
#if 0
g_print ("Day view lower: %s", ctime (&day_starts[0]));
@@ -847,8 +822,8 @@ print_day_add_event (CalComponent *comp,
g_return_val_if_fail (start < day_starts[days_shown], -1);
g_return_val_if_fail (end > day_starts[0], -1);
- start_tm = *(localtime (&start));
- end_tm = *(localtime (&end));
+ start_tt = icaltime_from_timet_with_zone (start, FALSE, zone);
+ end_tt = icaltime_from_timet_with_zone (end, FALSE, zone);
event.comp = comp;
gtk_object_ref (GTK_OBJECT (comp));
@@ -861,8 +836,8 @@ print_day_add_event (CalComponent *comp,
/*offset = day_view->first_hour_shown * 60
+ day_view->first_minute_shown;*/
offset = 0;
- event.start_minute = start_tm.tm_hour * 60 + start_tm.tm_min - offset;
- event.end_minute = end_tm.tm_hour * 60 + end_tm.tm_min - offset;
+ event.start_minute = start_tt.hour * 60 + start_tt.minute - offset;
+ event.end_minute = end_tt.hour * 60 + end_tt.minute - offset;
event.start_row_or_col = -1;
event.num_columns = -1;
@@ -1089,6 +1064,7 @@ static void
print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
double left, double right, double top, double bottom)
{
+ icaltimezone *zone = get_timezone ();
CalClient *client;
EDayViewEvent *event;
GnomeFont *font;
@@ -1097,8 +1073,8 @@ print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
gint rows_in_top_display, i;
double font_size, max_font_size;
- start = time_day_begin (whence);
- end = time_day_end (start);
+ start = time_day_begin_with_zone (whence, zone);
+ end = time_day_end_with_zone (start, zone);
pdi.days_shown = 1;
pdi.day_starts[0] = start;
@@ -1182,134 +1158,6 @@ print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
}
-/*
- * Print Day Summary
- */
-#if 0
-#define TIME_FMT "%X"
-#else
-#define TIME_FMT "%l:%M%p"
-#endif
-
-#if 0
-static gboolean
-print_day_summary_cb (CalComponent *comp, time_t istart, time_t iend, gpointer data)
-{
- CalComponentText text;
- struct psinfo *psi = (struct psinfo *)data;
- struct einfo *ei;
-
- ei = g_new (struct einfo, 1);
-
- cal_component_get_summary (comp, &text);
- ei->text = g_strdup (text.value);
-
- ei->start = istart;
- ei->end = iend;
- ei->count = 0;
-
- psi->events = g_list_append (psi->events, ei);
-
- return TRUE;
-}
-
-static void
-print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
- double left, double right, double top, double bottom,
- double size, int totime, int titleformat)
-{
- CalClient *client;
- struct psinfo psi;
- time_t start, end;
- GList *l;
- GnomeFont *font_summary;
- double y, yend, x, xend, inc, incsmall;
- char buf[100];
- double margin;
- struct tm tm;
-
- client = gnome_calendar_get_cal_client (gcal);
-
- /* fill static detail */
- font_summary = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, size);
-
- gnome_print_setfont (pc, font_summary);
-
- start = time_day_begin(whence);
- end = time_day_end(start);
-
- tm = *localtime(&start);
-
- format_date(start, titleformat, buf, 100);
- titled_box (pc, buf, font_summary, ALIGN_RIGHT | ALIGN_BORDER,
- &left, &right, &top, &bottom, 0.0);
-
- psi.events = NULL;
-
- cal_client_generate_instances (client, CALOBJ_TYPE_EVENT, start, end,
- print_day_summary_cb, &psi);
- inc = size*0.3;
- incsmall = size*0.2;
-
- y = top-inc;
- yend = bottom-incsmall;
-
- /* do a good rough approximation of the 'widest' time */
- tm.tm_year = 2000;
- tm.tm_mon = 12;
- tm.tm_mday = 22;
- tm.tm_sec = 22;
- tm.tm_min = 22;
- tm.tm_hour = 23;
- strftime(buf, 100, TIME_FMT, &tm);
- margin = gnome_font_get_width_string(font_summary, buf);
-
- for (l = psi.events; l; l = l->next) {
- struct einfo *ei = (struct einfo *)l->data;
-
- x = left + incsmall;
- xend = right - inc;
-
- if (y - gnome_font_get_size (font_summary) < bottom)
- break;
-
- tm = *localtime (&ei->start);
- strftime (buf, 100, TIME_FMT, &tm);
- gnome_print_moveto (pc, x + (margin
- - gnome_font_get_width_string (font_summary, buf)),
- y - gnome_font_get_size (font_summary));
- gnome_print_show (pc, buf);
-
- if (totime) {
- tm = *localtime (&ei->end);
- strftime (buf, 100, TIME_FMT, &tm);
- gnome_print_moveto (pc,
- (x + margin + inc
- + (margin
- - gnome_font_get_width_string (font_summary, buf))),
- y - gnome_font_get_size (font_summary));
- gnome_print_show (pc, buf);
-
- y = bound_text (pc, font_summary, ei->text,
- x + margin * 2 + inc * 2, xend,
- y, yend, 0);
- } else {
- /* we also indent back after each time is printed */
- y = bound_text (pc, font_summary, ei->text,
- x + margin + inc, xend,
- y, yend, -margin + inc);
- }
-
- y += gnome_font_get_size (font_summary) - inc;
-
- g_free (ei);
- }
- g_list_free (psi.events);
-
- gtk_object_unref (GTK_OBJECT (font_summary));
-}
-#endif
-
/* This adds one event to the view, adding it to the appropriate array. */
static gboolean
print_week_summary_cb (CalComponent *comp,
@@ -1318,8 +1166,9 @@ print_week_summary_cb (CalComponent *comp,
gpointer data)
{
+ icaltimezone *zone = get_timezone ();
EWeekViewEvent event;
- struct tm start_tm, end_tm;
+ struct icaltimetype start_tt, end_tt;
struct psinfo *psi = (struct psinfo *)data;
@@ -1335,8 +1184,8 @@ print_week_summary_cb (CalComponent *comp,
g_return_val_if_fail (start < psi->day_starts[psi->days_shown], TRUE);
g_return_val_if_fail (end > psi->day_starts[0], TRUE);
- start_tm = *(localtime (&start));
- end_tm = *(localtime (&end));
+ start_tt = icaltime_from_timet_with_zone (start, FALSE, zone);
+ end_tt = icaltime_from_timet_with_zone (end, FALSE, zone);
event.comp = comp;
gtk_object_ref (GTK_OBJECT (event.comp));
@@ -1345,8 +1194,8 @@ print_week_summary_cb (CalComponent *comp,
event.spans_index = 0;
event.num_spans = 0;
- event.start_minute = start_tm.tm_hour * 60 + start_tm.tm_min;
- event.end_minute = end_tm.tm_hour * 60 + end_tm.tm_min;
+ event.start_minute = start_tt.hour * 60 + start_tt.minute;
+ event.end_minute = end_tt.hour * 60 + end_tt.minute;
if (event.end_minute == 0 && start != end)
event.end_minute = 24 * 60;
@@ -1553,6 +1402,7 @@ print_week_view_background (GnomePrintContext *pc, GnomeFont *font,
double left, double top,
double cell_width, double cell_height)
{
+ icaltimezone *zone = get_timezone ();
int day, day_x, day_y, day_h;
double x1, x2, y1, y2, font_size, fillcolor;
struct tm tm;
@@ -1571,7 +1421,7 @@ print_week_view_background (GnomePrintContext *pc, GnomeFont *font,
y1 = top - day_y * cell_height;
y2 = y1 - day_h * cell_height;
- tm = *localtime (&psi->day_starts[day]);
+ tm = *convert_timet_to_struct_tm (psi->day_starts[day], zone);
/* In the month view we draw a grey background for the end
of the previous month and the start of the following. */
@@ -1617,6 +1467,7 @@ print_week_summary (GnomePrintContext *pc, GnomeCalendar *gcal,
int month, double font_size,
double left, double right, double top, double bottom)
{
+ icaltimezone *zone = get_timezone ();
CalClient *client;
EWeekViewEvent *event;
struct psinfo psi;
@@ -1644,10 +1495,10 @@ print_week_summary (GnomePrintContext *pc, GnomeCalendar *gcal,
if (psi.compress_weekend && psi.display_start_weekday == 6)
psi.display_start_weekday = 5;
- day_start = time_day_begin (whence);
+ day_start = time_day_begin_with_zone (whence, zone);
for (day = 0; day <= psi.days_shown; day++) {
psi.day_starts[day] = day_start;
- day_start = time_add_day (day_start, 1);
+ day_start = time_add_day_with_zone (day_start, 1, zone);
}
/* Get the events from the server. */
@@ -1717,6 +1568,7 @@ print_year_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
double left, double right, double top, double bottom,
int morerows)
{
+ icaltimezone *zone = get_timezone ();
double row_height, col_width, l, r, t, b;
time_t now;
int col, row, rows, cols;
@@ -1738,7 +1590,7 @@ print_year_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
col_width = (right - left) / cols;
r = l + col_width;
b = top - row_height;
- now = time_year_begin (whence);
+ now = time_year_begin_with_zone (whence, zone);
for (row = 0; row < rows; row++) {
t = top - row_height * row;
@@ -1749,7 +1601,7 @@ print_year_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
print_month_small (pc, gcal, now,
l + 8, r - 8, t - 8, b + 8,
DATE_MONTH, 0, 0, TRUE);
- now = time_add_month (now, 1);
+ now = time_add_month_with_zone (now, 1, zone);
}
}
}
@@ -1758,8 +1610,10 @@ static void
print_month_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
double left, double right, double top, double bottom)
{
+ icaltimezone *zone = get_timezone ();
time_t date;
struct tm tm;
+ struct icaltimetype tt;
char buffer[100];
GnomeFont *font;
gboolean compress_weekend;
@@ -1770,21 +1624,27 @@ print_month_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
compress_weekend = calendar_config_get_compress_weekend ();
/* Remember which month we want. */
- tm = *localtime (&whence);
- month = tm.tm_mon;
+ tt = icaltime_from_timet_with_zone (whence, FALSE, zone);
+ month = tt.month - 1;
/* Find the start of the month, and then the start of the week on
or before that day. */
- date = time_month_begin (whence);
- date = time_week_begin (date, weekday);
+ date = time_month_begin_with_zone (whence, zone);
+ date = time_week_begin_with_zone (date, weekday, zone);
/* If weekends are compressed then we can't start on a Sunday. */
if (compress_weekend && weekday == 0)
- date = time_add_day (date, -1);
-
- tm = *localtime (&date);
+ date = time_add_day_with_zone (date, -1, zone);
/* do day names ... */
+
+ /* We are only interested in outputting the weekday here, but we want
+ to be able to step through the week without worrying about
+ overflows making strftime choke, so we move near to the start of
+ the month. */
+ tm = *convert_timet_to_struct_tm (date, zone);
+ tm.tm_mday = (tm.tm_mday % 7) + 7;
+
font = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 0,
MONTH_NORMAL_FONT_SIZE);
font_size = gnome_font_get_size (font);
@@ -1800,7 +1660,7 @@ print_month_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
strftime (buffer, sizeof (buffer), "%a/", &tm);
len = strlen (buffer);
tm.tm_mday++;
- mktime (&tm);
+ tm.tm_wday = (tm.tm_wday + 1) % 7;
strftime (buffer + len, sizeof (buffer) - len,
"%a", &tm);
} else {
@@ -1814,7 +1674,7 @@ print_month_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
print_text (pc, font, buffer, ALIGN_CENTER, x1, x2, y1, y2);
tm.tm_mday++;
- mktime (&tm);
+ tm.tm_wday = (tm.tm_wday + 1) % 7;
}
gtk_object_unref (GTK_OBJECT (font));
@@ -1934,6 +1794,7 @@ static const int print_view_map[] = {
static GtkWidget *
range_selector_new (GtkWidget *dialog, time_t at, int *view)
{
+ icaltimezone *zone = get_timezone ();
GtkWidget *box;
GtkWidget *radio;
GSList *group;
@@ -1947,7 +1808,7 @@ range_selector_new (GtkWidget *dialog, time_t at, int *view)
box = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
- tm = *localtime (&at);
+ tm = *convert_timet_to_struct_tm (at, zone);
/* Day */
@@ -1959,15 +1820,15 @@ range_selector_new (GtkWidget *dialog, time_t at, int *view)
/* Week */
week_start_day = calendar_config_get_week_start_day ();
- week_begin = time_week_begin (at, week_start_day);
+ week_begin = time_week_begin_with_zone (at, week_start_day, zone);
/* If the week starts on a Sunday, we have to show the Saturday first,
since the weekend is compressed. */
if (week_start_day == 0)
- week_begin = time_add_day (week_begin, -1);
- week_end = time_add_day (week_end, 6);
+ week_begin = time_add_day_with_zone (week_begin, -1, zone);
+ week_end = time_add_day_with_zone (week_begin, 6, zone);
- week_begin_tm = *localtime (&week_begin);
- week_end_tm = *localtime (&week_end);
+ week_begin_tm = *convert_timet_to_struct_tm (week_begin, zone);
+ week_end_tm = *convert_timet_to_struct_tm (week_end, zone);
if (week_begin_tm.tm_mon == week_end_tm.tm_mon) {
strftime (str1, sizeof (str1), _("%a %b %d"), &week_begin_tm);
@@ -2015,6 +1876,7 @@ static void
print_day_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
double left, double right, double top, double bottom)
{
+ icaltimezone *zone = get_timezone ();
int i, days = 1;
double todo, header, l;
char buf[100];
@@ -2046,7 +1908,8 @@ print_day_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
DATE_MONTH | DATE_YEAR, date, date, FALSE);
l += SMALL_MONTH_SPACING + SMALL_MONTH_WIDTH;
- print_month_small (pc, gcal, time_add_month (date, 1),
+ print_month_small (pc, gcal,
+ time_add_month_with_zone (date, 1, zone),
l, l + SMALL_MONTH_WIDTH,
top - 4, header + 4,
DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
@@ -2063,7 +1926,7 @@ print_day_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
left + 4, todo, top - 32, top - 32 - 18);
gnome_print_showpage (pc);
- date = time_add_day (date, 1);
+ date = time_add_day_with_zone (date, 1, zone);
}
}
@@ -2072,6 +1935,7 @@ static void
print_week_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
double left, double right, double top, double bottom)
{
+ icaltimezone *zone = get_timezone ();
double header, l;
char buf[100];
time_t when;
@@ -2083,11 +1947,11 @@ print_week_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
gnome_print_beginpage (pc, "Calendar Week View");
week_start_day = calendar_config_get_week_start_day ();
- when = time_week_begin (date, week_start_day);
+ when = time_week_begin_with_zone (date, week_start_day, zone);
/* If the week starts on a Sunday, we have to show the Saturday first,
since the weekend is compressed. */
if (week_start_day == 0)
- when = time_add_day (when, -1);
+ when = time_add_day_with_zone (when, -1, zone);
/* Print the main week view. */
print_week_summary (pc, gcal, when, FALSE, 1, 0,
@@ -2107,14 +1971,15 @@ print_week_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
l, l + SMALL_MONTH_WIDTH,
top - 4, header + 4,
DATE_MONTH | DATE_YEAR, when,
- time_add_week (when, 1), FALSE);
+ time_add_week_with_zone (when, 1, zone), FALSE);
l += SMALL_MONTH_SPACING + SMALL_MONTH_WIDTH;
- print_month_small (pc, gcal, time_add_month (when, 1),
+ print_month_small (pc, gcal,
+ time_add_month_with_zone (when, 1, zone),
l, l + SMALL_MONTH_WIDTH,
top - 4, header + 4,
DATE_MONTH | DATE_YEAR, when,
- time_add_week (when, 1), FALSE);
+ time_add_week_with_zone (when, 1, zone), FALSE);
/* Print the start day of the week, e.g. '7th May 2001'. */
format_date (when, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
@@ -2122,7 +1987,7 @@ print_week_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
left + 3, right, top - 4, top - 4 - 24);
/* Print the end day of the week, e.g. '13th May 2001'. */
- when = time_add_day (when, 6);
+ when = time_add_day_with_zone (when, 6, zone);
format_date (when, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
print_text_size (pc, 24, buf, ALIGN_LEFT,
left + 3, right, top - 24 - 3, top - 24 - 3 - 24);
@@ -2135,6 +2000,7 @@ static void
print_month_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
double left, double right, double top, double bottom)
{
+ icaltimezone *zone = get_timezone ();
double header;
char buf[100];
@@ -2150,11 +2016,13 @@ print_month_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
print_border (pc, left, right, top, header, 1.0, 0.9);
/* Print the 2 mini calendar-months. */
- print_month_small (pc, gcal, time_add_month (date, 1),
+ print_month_small (pc, gcal,
+ time_add_month_with_zone (date, 1, zone),
right - (right - left) / 7 + 2, right - 8,
top - 4, header,
DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
- print_month_small (pc, gcal, time_add_month (date, -1),
+ print_month_small (pc, gcal,
+ time_add_month_with_zone (date, -1, zone),
left + 8, left + (right - left) / 7 - 2,
top - 4, header,
DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
@@ -2191,10 +2059,12 @@ print_year_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
static void
write_label_piece (time_t t, char *buffer, int size, char *stext, char *etext)
{
+ icaltimezone *zone = get_timezone ();
struct tm *tmp_tm;
int len;
- tmp_tm = localtime (&t);
+ tmp_tm = convert_timet_to_struct_tm (t, zone);
+
if (stext != NULL)
strcat (buffer, stext);
@@ -2211,22 +2081,30 @@ static void
print_date_label (GnomePrintContext *pc, CalComponent *comp,
double left, double right, double top, double bottom)
{
+ icaltimezone *zone = get_timezone ();
CalComponentDateTime datetime;
time_t start = 0, end = 0, complete = 0, due = 0;
static char buffer[1024];
cal_component_get_dtstart (comp, &datetime);
if (datetime.value)
- start = icaltime_as_timet (*datetime.value);
+ start = icaltime_as_timet_with_zone (*datetime.value, zone);
+ cal_component_free_datetime (&datetime);
+
cal_component_get_dtend (comp, &datetime);
if (datetime.value)
- end = icaltime_as_timet (*datetime.value);
+ end = icaltime_as_timet_with_zone (*datetime.value, zone);
+ cal_component_free_datetime (&datetime);
+
cal_component_get_due (comp, &datetime);
if (datetime.value)
- due = icaltime_as_timet (*datetime.value);
+ due = icaltime_as_timet_with_zone (*datetime.value, zone);
+ cal_component_free_datetime (&datetime);
+
cal_component_get_completed (comp, &datetime.value);
if (datetime.value)
- complete = icaltime_as_timet (*datetime.value);
+ complete = icaltime_as_timet_with_zone (*datetime.value, zone);
+ cal_component_free_icaltimetype (&datetime.value);
buffer[0] = '\0';
diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c
index 11dc82e7a2..967b2d4520 100644
--- a/calendar/pcs/cal-backend-file.c
+++ b/calendar/pcs/cal-backend-file.c
@@ -831,19 +831,24 @@ cal_backend_file_get_timezone_object (CalBackend *backend, const char *tzid)
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
+ g_print ("In cal_backend_file_get_timezone_object: %s\n", tzid);
+
g_return_val_if_fail (tzid != NULL, NULL);
g_return_val_if_fail (priv->icalcomp != NULL, NULL);
g_assert (priv->comp_uid_hash != NULL);
+ g_print (" getting icaltz\n");
icaltz = icalcomponent_get_timezone (priv->icalcomp, tzid);
if (!icaltz)
return NULL;
+ g_print (" getting icalcomp\n");
icalcomp = icaltimezone_get_component (icaltz);
if (!icalcomp)
return NULL;
+ g_print (" getting ical_string\n");
ical_string = icalcomponent_as_ical_string (icalcomp);
/* We dup the string; libical owns that memory. */
if (ical_string)
diff --git a/calendar/pcs/query.c b/calendar/pcs/query.c
index 6f3e276ae0..f96b74b88e 100644
--- a/calendar/pcs/query.c
+++ b/calendar/pcs/query.c
@@ -269,6 +269,9 @@ func_make_time (ESExp *esexp, int argc, ESExpResult **argv, void *data)
* N - int, number of days to add
*
* Adds the specified number of days to a time value.
+ *
+ * FIXME: TIMEZONES - need to use a timezone or daylight saving changes will
+ * make the result incorrect.
*/
static ESExpResult *
func_time_add_day (ESExp *esexp, int argc, ESExpResult **argv, void *data)
@@ -307,6 +310,8 @@ func_time_add_day (ESExp *esexp, int argc, ESExpResult **argv, void *data)
* TIME - time_t, base time
*
* Returns the start of the day, according to the local time.
+ *
+ * FIXME: TIMEZONES - this uses the current Unix timezone.
*/
static ESExpResult *
func_time_day_begin (ESExp *esexp, int argc, ESExpResult **argv, void *data)
@@ -337,6 +342,8 @@ func_time_day_begin (ESExp *esexp, int argc, ESExpResult **argv, void *data)
* TIME - time_t, base time
*
* Returns the end of the day, according to the local time.
+ *
+ * FIXME: TIMEZONES - this uses the current Unix timezone.
*/
static ESExpResult *
func_time_day_end (ESExp *esexp, int argc, ESExpResult **argv, void *data)