Index: servers/google/libgdata/gdata-entry.c
===================================================================
--- servers/google/libgdata/gdata-entry.c	(revision 9117)
+++ servers/google/libgdata/gdata-entry.c	(working copy)
@@ -2145,4 +2145,39 @@ gdata_entry_set_postal_addresses (GDataE
 	priv->entry_needs_update = TRUE;
 }
 
+/**
+ * gdata_entry_get_custom:
+ * entry owns the returned pointer and is valid as long as the item is alive
+ * and the value isn't changed by gdata_entry_set_custom or other method.
+ * Do not use this method if there is direct method for your value!
+ **/
+const gchar *
+gdata_entry_get_custom (GDataEntry *entry, const gchar *name)
+{
+	GDataEntryPrivate *priv;
 
+	g_return_val_if_fail (entry != NULL, NULL);
+	g_return_val_if_fail (name != NULL, NULL);
+	g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL);
+
+	priv = GDATA_ENTRY_GET_PRIVATE (entry);
+	return g_hash_table_lookup (priv->field_table, name);
+}
+
+/**
+ * gdata_entry_set_custom:
+ * Sets the custom value.
+ * Do not use this function when there exists direct method for your value!
+ **/
+void
+gdata_entry_set_custom (GDataEntry *entry, const gchar *name, const gchar *value)
+{
+	GDataEntryPrivate *priv;
+
+	g_return_if_fail (entry != NULL);
+	g_return_if_fail (name != NULL);
+	g_return_if_fail (GDATA_IS_ENTRY (entry));
+
+	priv = GDATA_ENTRY_GET_PRIVATE (entry);
+	g_hash_table_insert (priv->field_table, g_strdup (name), g_strdup (value ? value : ""));
+}
Index: servers/google/libgdata/gdata-feed.c
===================================================================
--- servers/google/libgdata/gdata-feed.c	(revision 9117)
+++ servers/google/libgdata/gdata-feed.c	(working copy)
@@ -82,6 +82,7 @@ struct _GDataFeedPrivate {
 	gchar *summary;
 	gchar *title;
 	gchar *updated;
+	gchar *timezone;
 
 	GHashTable *field_table;
 	gchar *feedXML;
@@ -177,6 +178,7 @@ gdata_feed_init(GTypeInstance *instance,
 	priv->summary = NULL;
 	priv->title = NULL;
 	priv->updated = NULL;
+	priv->timezone = NULL;
 
 	priv->authors = NULL;
 	priv->links = NULL;
@@ -241,6 +243,7 @@ gdata_feed_finalize(GObject *obj)
 	}
 
 	g_free (priv->updated);
+	g_free (priv->timezone);
 
 	if (priv->field_table != NULL)
 		g_hash_table_destroy(priv->field_table);
@@ -578,6 +581,11 @@ gdata_feed_new_from_xml(const gchar* fee
 			value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 			priv->updated = g_strdup ((gchar*)value);
 			xmlFree(value);
+		} else if (!xmlStrcmp(cur->name, (xmlChar *)"timezone")) {
+			value = xmlGetProp (cur, (xmlChar *)"value");
+			g_free (priv->timezone);
+			priv->timezone = g_strdup ((gchar*)value);
+			xmlFree (value);
 		}
 		else if (!xmlStrcmp(cur->name, (xmlChar *)"entry")) {
 			priv->entries = g_slist_prepend(priv->entries, gdata_entry_new_from_xmlptr(doc,cur));
@@ -692,3 +700,20 @@ gdata_feed_get_entries (GDataFeed *feed)
 
 	return priv->entries;
 }
+
+/**
+ * gdata_feed_get_timezone:
+ * Returned pointer owns the feed, its value is like 'Indian/Christmas'
+ **/
+const gchar *
+gdata_feed_get_timezone (GDataFeed *feed)
+{
+	GDataFeedPrivate *priv;
+
+	g_return_val_if_fail (feed != NULL, NULL);
+	g_return_val_if_fail (GDATA_IS_FEED (feed), NULL);
+	
+	priv = GDATA_FEED_GET_PRIVATE (feed);
+
+	return priv->timezone;
+}
Index: servers/google/libgdata/gdata-entry.h
===================================================================
--- servers/google/libgdata/gdata-entry.h	(revision 9117)
+++ servers/google/libgdata/gdata-entry.h	(working copy)
@@ -268,5 +268,8 @@ GDataEntryPhoneNumber * gdata_entry_get_
 
 GDataEntryPostalAddress * gdata_entry_get_primary_postal_address (GDataEntry *entry);
 
+const gchar *gdata_entry_get_custom (GDataEntry *entry, const gchar *name);
+void gdata_entry_set_custom (GDataEntry *entry, const gchar *name, const gchar *value);
+
 #endif
 
Index: servers/google/libgdata/gdata-feed.h
===================================================================
--- servers/google/libgdata/gdata-feed.h	(revision 9117)
+++ servers/google/libgdata/gdata-feed.h	(working copy)
@@ -71,3 +71,5 @@ gchar * gdata_feed_generate_xml(GDataFee
 gchar * gdata_feed_get_updated (GDataFeed *feed);
 
 GSList * gdata_feed_get_entries (GDataFeed *feed);
+
+const gchar *gdata_feed_get_timezone (GDataFeed *feed);
Index: servers/google/libgdata/ChangeLog
===================================================================
--- servers/google/libgdata/ChangeLog	(revision 9117)
+++ servers/google/libgdata/ChangeLog	(working copy)
@@ -1,3 +1,15 @@
+2008-07-18  Milan Crha  <mcrha@redhat.com>
+
+	** Part of fix for bug #468671
+
+	* gdata-entry.h: (gdata_entry_get_custom), (gdata_entry_set_custom):
+	* gdata-entry.c: (gdata_entry_get_custom), (gdata_entry_set_custom):
+	Read/write custom values withing entry.
+	* gdata-feed.h: (gdata_feed_get_timezone):
+	* gdata-feed.c: (gdata_feed_get_timezone), (struct _GDataFeedPrivate),
+	(gdata_feed_init), (gdata_feed_finalize), (gdata_feed_new_from_xml):
+	Read timezone name of the calendar and let it be available for others.
+
 2008-06-13  Wang Xin  <jedy.wang@sun.com>
 
 	** Fix for bug #527544.
Index: calendar/ChangeLog
===================================================================
--- calendar/ChangeLog	(revision 9117)
+++ calendar/ChangeLog	(working copy)
@@ -1,3 +1,11 @@
+2008-07-18  Milan Crha  <mcrha@redhat.com>
+
+	** Fix for bug #468671
+
+	* backends/google/e-cal-backend-google-utils.c: (gd_date_to_ical),
+	(e_go_item_to_cal_component), (utils_update_insertion):
+	Read time values in proper timezone as returned by Google Calendar.
+
 2008-07-04  Milan Crha  <mcrha@redhat.com>
 
 	** Fix for bug #329571
Index: calendar/backends/google/e-cal-backend-google-utils.c
===================================================================
--- calendar/backends/google/e-cal-backend-google-utils.c	(revision 9117)
+++ calendar/backends/google/e-cal-backend-google-utils.c	(working copy)
@@ -68,7 +68,7 @@
 
 /****************************************************** Google Connection Helper Functions ***********************************************/
 
-static gchar * gd_date_to_ical (gchar *string);
+static gboolean gd_date_to_ical (EGoItem *item, const gchar *google_time_string, struct icaltimetype *itt, ECalComponentDateTime *dt, icaltimezone *default_zone);
 static gchar * get_date (ECalComponentDateTime dt);
 static gint utils_compare_ids (gconstpointer cache_id, gconstpointer modified_cache_id);
 static gchar * utils_form_query (const gchar *query);
@@ -404,7 +404,7 @@ e_go_item_to_cal_component (EGoItem *ite
 	ECalComponentOrganizer *org = NULL;
 	icaltimezone *default_zone;
 	const char *description, *uid, *temp;
-	struct icaltimetype itt_utc, itt;
+	struct icaltimetype itt;
 	GSList *category_ids;
 	GSList *go_attendee_list = NULL, *l = NULL, *attendee_list = NULL;
 
@@ -427,34 +427,21 @@ e_go_item_to_cal_component (EGoItem *ite
 		e_cal_component_set_description_list (comp, &l);
 
 	}
-	
-	/*Creation*/
-	temp = gdata_entry_get_start_time (item->entry);
-	temp = gd_date_to_ical (g_strdup(temp));
-
-	if (temp) {
-		itt_utc = icaltime_from_string (temp);
-		itt_utc.zone = default_zone;
-
-		if (!icaltime_get_timezone (itt_utc))
-			icaltime_set_timezone (&itt_utc, icaltimezone_get_utc_timezone());
-		if (default_zone) {
-			itt = icaltime_convert_to_zone (itt_utc, default_zone);
-			icaltime_set_timezone (&itt, default_zone);
-			e_cal_component_set_created (comp, &itt);
-			e_cal_component_set_dtstamp (comp, &itt);
-
-		} else {
-			e_cal_component_set_created (comp, &itt_utc);
-			e_cal_component_set_dtstamp (comp, &itt_utc);
-		}
-	/* dt.value = &itt; */
-	}
-	dt.value = &itt;
-	dt.tzid = icaltimezone_get_tzid (default_zone);
-	e_cal_component_set_dtstart (comp, &dt);
-	e_cal_component_set_created (comp, &itt_utc);
-	e_cal_component_set_dtstamp (comp, &itt_utc);
+
+	/* Creation/Last update */
+	if (gd_date_to_ical (item, gdata_entry_get_custom (item->entry, "published"), &itt, &dt, default_zone))
+		e_cal_component_set_created (comp, &itt);
+
+	if (gd_date_to_ical (item, gdata_entry_get_custom (item->entry, "updated"), &itt, &dt, default_zone))
+		e_cal_component_set_dtstamp (comp, &itt);
+
+	/* Start time */
+	if (gd_date_to_ical (item, gdata_entry_get_start_time (item->entry), &itt, &dt, default_zone))
+		e_cal_component_set_dtstart (comp, &dt);
+
+	/* End time */
+	if (gd_date_to_ical (item, gdata_entry_get_end_time (item->entry), &itt, &dt, default_zone))
+		e_cal_component_set_dtend (comp, &dt);
 
 	/* Summary of the Entry */
 	text.value = gdata_entry_get_title (item->entry);
@@ -531,37 +518,6 @@ e_go_item_to_cal_component (EGoItem *ite
 	/* Location */
 	e_cal_component_set_location (comp, gdata_entry_get_location (item->entry));
 
-	/* End date */
-	temp = gdata_entry_get_end_time (item->entry);
-	temp = gd_date_to_ical (g_strdup(temp));
-
-	if (temp) {
-		itt_utc = icaltime_from_string (temp);
-
-	/*
-	 * TODO : Write a small func to check if its all day and set it to true , and check for it here .
-	 * Evolution Automatically recognises all day event from google . so why bother ?
-	 * Considering not to be a all day event . FIXME needs further work .
-	 */
-		if (FALSE) {
-			if (!icaltime_get_timezone (itt_utc))
-				icaltime_set_timezone (&itt_utc, icaltimezone_get_utc_timezone());
-			if (default_zone) {
-				itt = icaltime_convert_to_zone (itt_utc, default_zone);
-				icaltime_set_timezone (&itt, default_zone);
-				dt.value = &itt;
-				dt.tzid = icaltimezone_get_tzid (default_zone);
-			} else {
-				dt.value = &itt_utc;
-				dt.tzid = g_strdup ("UTC");
-			}
-		} else {
-			itt = icaltime_convert_to_zone (itt_utc, default_zone);
-			icaltime_set_timezone (&itt, default_zone);
-			dt.value = &itt;
-			dt.tzid = icaltimezone_get_tzid (default_zone);
-		}
-	}
 #if 0
 	/* temp hack to see how recurrence work */
 	ECalComponentRange *recur_id;
@@ -753,6 +709,7 @@ utils_update_insertion (ECalBackendGoogl
 
 	comp = e_cal_component_new ();
 	item_t = g_new0 (EGoItem, 1);
+	item_t->feed = item->feed;
 	entries_list = gdata_feed_get_entries (item->feed);
 
 	for (list = uid_list; list != NULL; list = list->next) {
@@ -874,20 +831,30 @@ get_deltas_timeout (gpointer cbgo)
  *
  * gd_date_to_ical:
  * Helper Function to convert a gdata format date to ical date
- * @string date in gdata format eg: '2006-04-17T17:00:00.000Z'
+ * @item item from which the time comes. It's used to get to the feed's timezone
+ * @google_time_string date in gdata format eg: '2006-04-17T17:00:00.000Z' or '2006-04-17T17:00:00.000+07:00'
+ * @iit Resulting icaltimetype.
+ * @dt Resulting ECalComponentDateTime.
+ * @default_zone Default time zone for the backend. If set, then the time will be converted to that timezone.
  *
+ * @note Do not free itt or dt values, those come from buildin structures held by libical
  **/
-/* FIXME use proper functions to manipulate the dates */
-static gchar *
-gd_date_to_ical (gchar *string)
+static gboolean
+gd_date_to_ical (EGoItem *item, const gchar *google_time_string, struct icaltimetype *itt, ECalComponentDateTime *dt, icaltimezone *default_zone)
 {
-	gchar *s, *str;
+	gchar *s, *string, *dup;
 	int count = 0;
+	gboolean is_utc = TRUE;
 
-	s = g_strdup (string);
-	str = string;
+	g_return_val_if_fail (itt != NULL, FALSE);
+	g_return_val_if_fail (dt != NULL, FALSE);
 
-	g_return_val_if_fail (string != NULL, "");
+	if (!google_time_string || !*google_time_string)
+		return FALSE;
+
+	dup = g_strdup (google_time_string);
+	s = dup;
+	string = dup;
 
 	/* Strip of the string to the gdata format */
 	while (s[0] != '\0') {
@@ -900,6 +867,10 @@ gd_date_to_ical (gchar *string)
 			s = s + 1;
 
 		if (count == 15) {
+			if (strlen (s) >= 5) {
+				is_utc = s [4] == 'Z';
+			}
+
 			string[0] = '\0';
 			break;
 		}
@@ -907,5 +878,29 @@ gd_date_to_ical (gchar *string)
 			string[0] = '\0';
 	}
 
-	return str;
+	*itt = icaltime_from_string (dup);
+
+	if (!is_utc) {
+		const char *zone_name = item->feed ? gdata_feed_get_timezone (item->feed) : NULL;
+
+		if (zone_name) {
+			icaltimezone *zone = icaltimezone_get_builtin_timezone (zone_name);
+
+			if (zone)
+				icaltime_set_timezone (itt, zone);
+		}
+	}
+
+	if (!icaltime_get_timezone (*itt))
+		icaltime_set_timezone (itt, icaltimezone_get_utc_timezone ());
+
+	if (default_zone)
+		*itt = icaltime_convert_to_zone (*itt, default_zone);
+
+	dt->value = itt;
+	dt->tzid = icaltimezone_get_tzid ((icaltimezone *) icaltime_get_timezone (*itt));
+
+	g_free (dup);
+
+	return TRUE;
 }
