[libgdata] core: Use gint64 timestamps instead of GTimeVals



commit a6762e29ab0ffb275e907fe927c7fe96e3b1dfc8
Author: Philip Withnall <philip tecnocode co uk>
Date:   Mon Oct 4 00:18:22 2010 +0100

    core: Use gint64 timestamps instead of GTimeVals
    
    This means we no longer have to register GTimeVal with the GType system, and
    everything is generally neater because we never used GTimeVal's microsecond
    precision anyway.

 docs/reference/gdata-sections.txt                 |    2 -
 gdata/exif/gdata-exif-tags.c                      |   22 ++--
 gdata/exif/gdata-exif-tags.h                      |    2 +-
 gdata/gd/gdata-gd-reminder.c                      |   59 +++----
 gdata/gd/gdata-gd-reminder.h                      |    7 +-
 gdata/gd/gdata-gd-when.c                          |  106 ++++++------
 gdata/gd/gdata-gd-when.h                          |   10 +-
 gdata/gdata-access-rule.c                         |   30 ++--
 gdata/gdata-access-rule.h                         |    2 +-
 gdata/gdata-batch-operation.c                     |    4 +-
 gdata/gdata-entry.c                               |   67 ++++----
 gdata/gdata-entry.h                               |    4 +-
 gdata/gdata-feed.c                                |   38 ++--
 gdata/gdata-feed.h                                |    2 +-
 gdata/gdata-parser.c                              |   49 +++++-
 gdata/gdata-parser.h                              |   10 +-
 gdata/gdata-private.h                             |    4 +-
 gdata/gdata-query.c                               |  180 +++++++++-----------
 gdata/gdata-query.h                               |   16 +-
 gdata/gdata-types.c                               |   20 ---
 gdata/gdata-types.h                               |    3 -
 gdata/gdata.symbols                               |    1 -
 gdata/services/calendar/gdata-calendar-calendar.c |   30 ++--
 gdata/services/calendar/gdata-calendar-calendar.h |    2 +-
 gdata/services/calendar/gdata-calendar-event.c    |   40 +++--
 gdata/services/calendar/gdata-calendar-event.h    |    4 +-
 gdata/services/calendar/gdata-calendar-query.c    |  183 +++++++++-----------
 gdata/services/calendar/gdata-calendar-query.h    |   19 +-
 gdata/services/contacts/gdata-contacts-contact.c  |   30 ++--
 gdata/services/contacts/gdata-contacts-contact.h  |    2 +-
 gdata/services/documents/gdata-documents-entry.c  |   58 ++++---
 gdata/services/documents/gdata-documents-entry.h  |    4 +-
 gdata/services/picasaweb/gdata-picasaweb-album.c  |   97 +++++------
 gdata/services/picasaweb/gdata-picasaweb-album.h  |    6 +-
 gdata/services/picasaweb/gdata-picasaweb-file.c   |   91 +++++------
 gdata/services/picasaweb/gdata-picasaweb-file.h   |    6 +-
 gdata/services/youtube/gdata-youtube-group.c      |   22 ++--
 gdata/services/youtube/gdata-youtube-group.h      |    2 +-
 gdata/services/youtube/gdata-youtube-video.c      |   85 +++++-----
 gdata/services/youtube/gdata-youtube-video.h      |    6 +-
 gdata/tests/calendar.c                            |   85 +++++------
 gdata/tests/contacts.c                            |   13 +-
 gdata/tests/general.c                             |  111 ++++++-------
 gdata/tests/picasaweb.c                           |   80 ++-------
 gdata/tests/youtube.c                             |   11 +-
 45 files changed, 753 insertions(+), 872 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 2198384..f11e756 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -585,9 +585,7 @@ gdata_color_from_hexadecimal
 gdata_color_to_hexadecimal
 <SUBSECTION Standard>
 GDATA_TYPE_COLOR
-GDATA_TYPE_G_TIME_VAL
 gdata_color_get_type
-gdata_g_time_val_get_type
 </SECTION>
 
 <SECTION>
diff --git a/gdata/exif/gdata-exif-tags.c b/gdata/exif/gdata-exif-tags.c
index 177b3d2..cd7bf45 100644
--- a/gdata/exif/gdata-exif-tags.c
+++ b/gdata/exif/gdata-exif-tags.c
@@ -62,7 +62,7 @@ struct _GDataExifTagsPrivate {
 	gint iso;
 	gchar *make;
 	gchar *model;
-	GTimeVal _time;
+	gint64 _time; /* in milliseconds! */
 };
 
 G_DEFINE_TYPE (GDataExifTags, gdata_exif_tags, GDATA_TYPE_PARSABLE)
@@ -87,6 +87,7 @@ static void
 gdata_exif_tags_init (GDataExifTags *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_EXIF_TAGS, GDataExifTagsPrivate);
+	self->priv->_time = -1;
 }
 
 static void
@@ -156,8 +157,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		milliseconds = g_ascii_strtoull ((gchar*) time_str, NULL, 10);
 		xmlFree (time_str);
 
-		self->priv->_time.tv_sec = (glong) (milliseconds / 1000);
-		self->priv->_time.tv_usec = (glong) ((milliseconds % 1000) * 1000);
+		self->priv->_time = (gint64) milliseconds;
 	} else {
 		return GDATA_PARSABLE_CLASS (gdata_exif_tags_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
@@ -327,17 +327,17 @@ gdata_exif_tags_get_model (GDataExifTags *self)
 /**
  * gdata_exif_tags_get_time:
  * @self: a #GDataExifTags
- * @_time: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataExifTags:time property and puts it in @_time. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataExifTags:time property as a number of milliseconds since the epoch. If the property is unset, <code class="literal">-1</code> will
+ * be returned.
+ *
+ * Return value: the UNIX timestamp for the time property in milliseconds, or <code class="literal">-1</code>
  *
  * Since: 0.5.0
  **/
-void
-gdata_exif_tags_get_time (GDataExifTags *self, GTimeVal *_time)
+gint64
+gdata_exif_tags_get_time (GDataExifTags *self)
 {
-	g_return_if_fail (GDATA_IS_EXIF_TAGS (self));
-	g_return_if_fail (_time != NULL);
-	*_time = self->priv->_time;
+	g_return_val_if_fail (GDATA_IS_EXIF_TAGS (self), -1);
+	return self->priv->_time;
 }
diff --git a/gdata/exif/gdata-exif-tags.h b/gdata/exif/gdata-exif-tags.h
index c64eac5..2dcb76e 100644
--- a/gdata/exif/gdata-exif-tags.h
+++ b/gdata/exif/gdata-exif-tags.h
@@ -71,7 +71,7 @@ const gchar *gdata_exif_tags_get_image_unique_id (GDataExifTags *self) G_GNUC_PU
 gint gdata_exif_tags_get_iso (GDataExifTags *self) G_GNUC_PURE;
 const gchar *gdata_exif_tags_get_make (GDataExifTags *self) G_GNUC_PURE;
 const gchar *gdata_exif_tags_get_model (GDataExifTags *self) G_GNUC_PURE;
-void gdata_exif_tags_get_time (GDataExifTags *self, GTimeVal *time);
+gint64 gdata_exif_tags_get_time (GDataExifTags *self);
 
 G_END_DECLS
 
diff --git a/gdata/gd/gdata-gd-reminder.c b/gdata/gd/gdata-gd-reminder.c
index 331c0f9..8ed7344 100644
--- a/gdata/gd/gdata-gd-reminder.c
+++ b/gdata/gd/gdata-gd-reminder.c
@@ -48,7 +48,7 @@ static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
 
 struct _GDataGDReminderPrivate {
 	gchar *method;
-	GTimeVal absolute_time;
+	gint64 absolute_time;
 	gint relative_time;
 };
 
@@ -107,9 +107,9 @@ gdata_gd_reminder_class_init (GDataGDReminderClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_ABSOLUTE_TIME,
-	                                 g_param_spec_boxed ("absolute-time",
+	                                 g_param_spec_int64 ("absolute-time",
 	                                                     "Absolute time", "Absolute time at which the reminder should be issued.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -156,9 +156,7 @@ compare_with (GDataComparable *self, GDataComparable *other)
 
 	method_cmp = g_strcmp0 (a->priv->method, b->priv->method);
 	if (gdata_gd_reminder_is_absolute_time (a) == TRUE) {
-		if (method_cmp == 0 &&
-		    a->priv->absolute_time.tv_sec == b->priv->absolute_time.tv_sec &&
-		    a->priv->absolute_time.tv_usec == b->priv->absolute_time.tv_usec)
+		if (method_cmp == 0 && a->priv->absolute_time == b->priv->absolute_time)
 			return 0;
 	} else {
 		if (method_cmp == 0 && a->priv->relative_time == b->priv->relative_time)
@@ -178,6 +176,7 @@ static void
 gdata_gd_reminder_init (GDataGDReminder *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_GD_REMINDER, GDataGDReminderPrivate);
+	self->priv->absolute_time = -1;
 }
 
 static void
@@ -201,7 +200,7 @@ gdata_gd_reminder_get_property (GObject *object, guint property_id, GValue *valu
 			g_value_set_string (value, priv->method);
 			break;
 		case PROP_ABSOLUTE_TIME:
-			g_value_set_boxed (value, &(priv->absolute_time));
+			g_value_set_int64 (value, priv->absolute_time);
 			break;
 		case PROP_IS_ABSOLUTE_TIME:
 			g_value_set_boolean (value, gdata_gd_reminder_is_absolute_time (GDATA_GD_REMINDER (object)));
@@ -226,7 +225,7 @@ gdata_gd_reminder_set_property (GObject *object, guint property_id, const GValue
 			gdata_gd_reminder_set_method (self, g_value_get_string (value));
 			break;
 		case PROP_ABSOLUTE_TIME:
-			gdata_gd_reminder_set_absolute_time (self, g_value_get_boxed (value));
+			gdata_gd_reminder_set_absolute_time (self, g_value_get_int64 (value));
 			break;
 		case PROP_RELATIVE_TIME:
 			gdata_gd_reminder_set_relative_time (self, g_value_get_int (value));
@@ -243,7 +242,7 @@ pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointe
 {
 	GDataGDReminderPrivate *priv = GDATA_GD_REMINDER (parsable)->priv;
 	xmlChar *absolute_time, *relative_time;
-	GTimeVal absolute_time_timeval;
+	gint64 absolute_time_int64;
 	gint relative_time_int = -1;
 	gboolean is_absolute_time = FALSE;
 
@@ -251,7 +250,7 @@ pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointe
 	absolute_time = xmlGetProp (root_node, (xmlChar*) "absoluteTime");
 	if (absolute_time != NULL) {
 		is_absolute_time = TRUE;
-		if (g_time_val_from_iso8601 ((gchar*) absolute_time, &absolute_time_timeval) == FALSE) {
+		if (gdata_parser_int64_from_iso8601 ((gchar*) absolute_time, &absolute_time_int64) == FALSE) {
 			/* Error */
 			gdata_parser_error_not_iso8601_format (root_node, (gchar*) absolute_time, error);
 			xmlFree (absolute_time);
@@ -277,10 +276,10 @@ pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointe
 	xmlFree (relative_time);
 
 	if (is_absolute_time == TRUE) {
-		priv->absolute_time = absolute_time_timeval;
+		priv->absolute_time = absolute_time_int64;
 		priv->relative_time = -1;
 	} else {
-		priv->absolute_time.tv_sec = priv->absolute_time.tv_usec = 0;
+		priv->absolute_time = -1;
 		priv->relative_time = relative_time_int;
 	}
 
@@ -295,7 +294,7 @@ pre_get_xml (GDataParsable *parsable, GString *xml_string)
 	GDataGDReminderPrivate *priv = GDATA_GD_REMINDER (parsable)->priv;
 
 	if (priv->relative_time == -1) {
-		gchar *absolute_time = g_time_val_to_iso8601 (&(priv->absolute_time));
+		gchar *absolute_time = gdata_parser_int64_to_iso8601 (priv->absolute_time);
 		g_string_append_printf (xml_string, " absoluteTime='%s'", absolute_time);
 		g_free (absolute_time);
 	} else {
@@ -315,7 +314,7 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
 /**
  * gdata_gd_reminder_new:
  * @method: (allow-none): the notification method the reminder should use, or %NULL
- * @absolute_time: (allow-none): the absolute time for the reminder, or %NULL
+ * @absolute_time: the absolute time for the reminder, or <code class="literal">-1</code>
  * @relative_time: the relative time for the reminder, in minutes, or <code class="literal">-1</code>
  *
  * Creates a new #GDataGDReminder. More information is available in the <ulink type="http"
@@ -326,9 +325,10 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
  * Since: 0.2.0
  **/
 GDataGDReminder *
-gdata_gd_reminder_new (const gchar *method, const GTimeVal *absolute_time, gint relative_time)
+gdata_gd_reminder_new (const gchar *method, gint64 absolute_time, gint relative_time)
 {
-	g_return_val_if_fail (absolute_time == NULL || relative_time == -1, NULL);
+	g_return_val_if_fail (absolute_time == -1 || relative_time == -1, NULL);
+	g_return_val_if_fail (absolute_time >= -1, NULL);
 	g_return_val_if_fail (relative_time >= -1, NULL);
 	return g_object_new (GDATA_TYPE_GD_REMINDER, "absolute-time", absolute_time, "relative-time", relative_time, "method", method, NULL);
 }
@@ -374,41 +374,38 @@ gdata_gd_reminder_set_method (GDataGDReminder *self, const gchar *method)
 /**
  * gdata_gd_reminder_get_absolute_time:
  * @self: a #GDataGDReminder
- * @absolute_time: (out caller-allocates): return location for the absolute time
  *
- * Gets the #GDataGDReminder:absolute-time property and returns it in @absolute_time. If the
- * property is unset, both fields of @start_time are set to <code class="literal">0</code>.
+ * Gets the #GDataGDReminder:absolute-time property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp of the absolute time for the reminder, or <code class="literal">-1</code>
  *
  * Since: 0.4.0
  **/
-void
-gdata_gd_reminder_get_absolute_time (GDataGDReminder *self, GTimeVal *absolute_time)
+gint64
+gdata_gd_reminder_get_absolute_time (GDataGDReminder *self)
 {
-	g_return_if_fail (GDATA_IS_GD_REMINDER (self));
-	g_return_if_fail (absolute_time != NULL);
-	*absolute_time = self->priv->absolute_time;
+	g_return_val_if_fail (GDATA_IS_GD_REMINDER (self), -1);
+	return self->priv->absolute_time;
 }
 
 /**
  * gdata_gd_reminder_set_absolute_time:
  * @self: a #GDataGDReminder
- * @absolute_time: (allow-none): the new absolute time, or %NULL
+ * @absolute_time: the new absolute time, or <code class="literal">-1</code>
  *
  * Sets the #GDataGDReminder:absolute-time property to @absolute_time.
  *
- * Set @absolute_time to %NULL to unset the property.
+ * Set @absolute_time to <code class="literal">-1</code> to unset the property.
  *
  * Since: 0.4.0
  **/
 void
-gdata_gd_reminder_set_absolute_time (GDataGDReminder *self, const GTimeVal *absolute_time)
+gdata_gd_reminder_set_absolute_time (GDataGDReminder *self, gint64 absolute_time)
 {
 	g_return_if_fail (GDATA_IS_GD_REMINDER (self));
+	g_return_if_fail (absolute_time >= -1);
 
-	if (absolute_time == NULL)
-		self->priv->absolute_time.tv_sec = self->priv->absolute_time.tv_usec = 0;
-	else
-		self->priv->absolute_time = *absolute_time;
+	self->priv->absolute_time = absolute_time;
 	g_object_notify (G_OBJECT (self), "absolute-time");
 }
 
diff --git a/gdata/gd/gdata-gd-reminder.h b/gdata/gd/gdata-gd-reminder.h
index 96a39d7..bccc97b 100644
--- a/gdata/gd/gdata-gd-reminder.h
+++ b/gdata/gd/gdata-gd-reminder.h
@@ -89,14 +89,13 @@ typedef struct {
 
 GType gdata_gd_reminder_get_type (void) G_GNUC_CONST;
 
-GDataGDReminder *gdata_gd_reminder_new (const gchar *method, const GTimeVal *absolute_time,
-                                        gint relative_time) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+GDataGDReminder *gdata_gd_reminder_new (const gchar *method, gint64 absolute_time, gint relative_time) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 const gchar *gdata_gd_reminder_get_method (GDataGDReminder *self) G_GNUC_PURE;
 void gdata_gd_reminder_set_method (GDataGDReminder *self, const gchar *method);
 
-void gdata_gd_reminder_get_absolute_time (GDataGDReminder *self, GTimeVal *absolute_time);
-void gdata_gd_reminder_set_absolute_time (GDataGDReminder *self, const GTimeVal *absolute_time);
+gint64 gdata_gd_reminder_get_absolute_time (GDataGDReminder *self);
+void gdata_gd_reminder_set_absolute_time (GDataGDReminder *self, gint64 absolute_time);
 gboolean gdata_gd_reminder_is_absolute_time (GDataGDReminder *self);
 
 gint gdata_gd_reminder_get_relative_time (GDataGDReminder *self) G_GNUC_PURE;
diff --git a/gdata/gd/gdata-gd-when.c b/gdata/gd/gdata-gd-when.c
index 48832bb..656d878 100644
--- a/gdata/gd/gdata-gd-when.c
+++ b/gdata/gd/gdata-gd-when.c
@@ -53,8 +53,8 @@ static void get_xml (GDataParsable *parsable, GString *xml_string);
 static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
 
 struct _GDataGDWhenPrivate {
-	GTimeVal start_time;
-	GTimeVal end_time;
+	gint64 start_time;
+	gint64 end_time;
 	gboolean is_date;
 	gchar *value_string;
 	GList *reminders;
@@ -103,9 +103,9 @@ gdata_gd_when_class_init (GDataGDWhenClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_START_TIME,
-	                                 g_param_spec_boxed ("start-time",
+	                                 g_param_spec_int64 ("start-time",
 	                                                     "Start time", "The name of the when.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     0, G_MAXINT64, 0,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -119,9 +119,9 @@ gdata_gd_when_class_init (GDataGDWhenClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_END_TIME,
-	                                 g_param_spec_boxed ("end-time",
+	                                 g_param_spec_int64 ("end-time",
 	                                                     "End time", "The title of a person within the when.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -167,8 +167,8 @@ compare_with (GDataComparable *self, GDataComparable *other)
 	if (a->is_date != b->is_date)
 		return CLAMP (b->is_date - a->is_date, -1, 1);
 
-	start_diff = (b->start_time.tv_sec - a->start_time.tv_sec) * 1000000 + (b->start_time.tv_usec - a->start_time.tv_usec);
-	end_diff = (b->end_time.tv_sec - a->end_time.tv_sec) * 1000000 + (b->end_time.tv_usec - a->end_time.tv_usec);
+	start_diff = b->start_time - a->start_time;
+	end_diff = b->end_time - a->end_time;
 
 	if (start_diff == 0)
 		return CLAMP (end_diff, -1, 1);
@@ -185,6 +185,7 @@ static void
 gdata_gd_when_init (GDataGDWhen *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_GD_WHEN, GDataGDWhenPrivate);
+	self->priv->end_time = -1;
 }
 
 static void
@@ -220,10 +221,10 @@ gdata_gd_when_get_property (GObject *object, guint property_id, GValue *value, G
 
 	switch (property_id) {
 		case PROP_START_TIME:
-			g_value_set_boxed (value, &(priv->start_time));
+			g_value_set_int64 (value, priv->start_time);
 			break;
 		case PROP_END_TIME:
-			g_value_set_boxed (value, &(priv->end_time));
+			g_value_set_int64 (value, priv->end_time);
 			break;
 		case PROP_IS_DATE:
 			g_value_set_boolean (value, priv->is_date);
@@ -245,10 +246,10 @@ gdata_gd_when_set_property (GObject *object, guint property_id, const GValue *va
 
 	switch (property_id) {
 		case PROP_START_TIME:
-			gdata_gd_when_set_start_time (self, g_value_get_boxed (value));
+			gdata_gd_when_set_start_time (self, g_value_get_int64 (value));
 			break;
 		case PROP_END_TIME:
-			gdata_gd_when_set_end_time (self, g_value_get_boxed (value));
+			gdata_gd_when_set_end_time (self, g_value_get_int64 (value));
 			break;
 		case PROP_IS_DATE:
 			gdata_gd_when_set_is_date (self, g_value_get_boolean (value));
@@ -268,14 +269,14 @@ pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointe
 {
 	GDataGDWhenPrivate *priv = GDATA_GD_WHEN (parsable)->priv;
 	xmlChar *start_time, *end_time;
-	GTimeVal start_time_timeval, end_time_timeval;
+	gint64 start_time_int64, end_time_int64;
 	gboolean is_date = FALSE;
 
 	/* Start time */
 	start_time = xmlGetProp (root_node, (xmlChar*) "startTime");
-	if (gdata_parser_time_val_from_date ((gchar*) start_time, &start_time_timeval) == TRUE) {
+	if (gdata_parser_int64_from_date ((gchar*) start_time, &start_time_int64) == TRUE) {
 		is_date = TRUE;
-	} else if (g_time_val_from_iso8601 ((gchar*) start_time, &start_time_timeval) == FALSE) {
+	} else if (gdata_parser_int64_from_iso8601 ((gchar*) start_time, &start_time_int64) == FALSE) {
 		/* Error */
 		gdata_parser_error_not_iso8601_format (root_node, (gchar*) start_time, error);
 		xmlFree (start_time);
@@ -289,9 +290,9 @@ pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointe
 		gboolean success;
 
 		if (is_date == TRUE)
-			success = gdata_parser_time_val_from_date ((gchar*) end_time, &end_time_timeval);
+			success = gdata_parser_int64_from_date ((gchar*) end_time, &end_time_int64);
 		else
-			success = g_time_val_from_iso8601 ((gchar*) end_time, &end_time_timeval);
+			success = gdata_parser_int64_from_iso8601 ((gchar*) end_time, &end_time_int64);
 
 		if (success == FALSE) {
 			/* Error */
@@ -302,11 +303,11 @@ pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointe
 		xmlFree (end_time);
 	} else {
 		/* Give a default */
-		end_time_timeval.tv_sec = end_time_timeval.tv_usec = 0;
+		end_time_int64 = -1;
 	}
 
-	priv->start_time = start_time_timeval;
-	priv->end_time = end_time_timeval;
+	priv->start_time = start_time_int64;
+	priv->end_time = end_time_int64;
 	priv->is_date = is_date;
 	priv->value_string = (gchar*) xmlGetProp (root_node, (xmlChar*) "valueString");
 
@@ -345,20 +346,20 @@ pre_get_xml (GDataParsable *parsable, GString *xml_string)
 	gchar *start_time;
 
 	if (priv->is_date == TRUE)
-		start_time = gdata_parser_date_from_time_val (&(priv->start_time));
+		start_time = gdata_parser_date_from_int64 (priv->start_time);
 	else
-		start_time = g_time_val_to_iso8601 (&(priv->start_time));
+		start_time = gdata_parser_int64_to_iso8601 (priv->start_time);
 
 	g_string_append_printf (xml_string, " startTime='%s'", start_time);
 	g_free (start_time);
 
-	if (priv->end_time.tv_sec != 0 || priv->end_time.tv_usec != 0) {
+	if (priv->end_time != -1) {
 		gchar *end_time;
 
 		if (priv->is_date == TRUE)
-			end_time = gdata_parser_date_from_time_val (&(priv->end_time));
+			end_time = gdata_parser_date_from_int64 (priv->end_time);
 		else
-			end_time = g_time_val_to_iso8601 (&(priv->end_time));
+			end_time = gdata_parser_int64_to_iso8601 (priv->end_time);
 
 		g_string_append_printf (xml_string, " endTime='%s'", end_time);
 		g_free (end_time);
@@ -387,7 +388,7 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
 /**
  * gdata_gd_when_new:
  * @start_time: when the event starts or (for zero-duration events) when it occurs
- * @end_time: (allow-none): when the event ends, or %NULL
+ * @end_time: when the event ends, or <code class="literal">-1</code>
  * @is_date: %TRUE if @start_time and @end_time specify dates rather than times, %FALSE otherwise
  *
  * Creates a new #GDataGDWhen. More information is available in the <ulink type="http"
@@ -398,27 +399,29 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
  * Since: 0.2.0
  **/
 GDataGDWhen *
-gdata_gd_when_new (const GTimeVal *start_time, const GTimeVal *end_time, gboolean is_date)
+gdata_gd_when_new (gint64 start_time, gint64 end_time, gboolean is_date)
 {
-	g_return_val_if_fail (start_time != NULL, NULL);
+	g_return_val_if_fail (start_time >= 0, NULL);
+	g_return_val_if_fail (end_time >= -1, NULL);
+
 	return g_object_new (GDATA_TYPE_GD_WHEN, "start-time", start_time, "end-time", end_time, "is-date", is_date, NULL);
 }
 
 /**
  * gdata_gd_when_get_start_time:
  * @self: a #GDataGDWhen
- * @start_time: (out caller-allocates): return location for the start time
  *
- * Gets the #GDataGDWhen:start-time property and returns it in @start_time.
+ * Gets the #GDataGDWhen:start-time property.
+ *
+ * Return value: the UNIX timestamp for the start time of the event
  *
  * Since: 0.4.0
  **/
-void
-gdata_gd_when_get_start_time (GDataGDWhen *self, GTimeVal *start_time)
+gint64
+gdata_gd_when_get_start_time (GDataGDWhen *self)
 {
-	g_return_if_fail (GDATA_IS_GD_WHEN (self));
-	g_return_if_fail (start_time != NULL);
-	*start_time = self->priv->start_time;
+	g_return_val_if_fail (GDATA_IS_GD_WHEN (self), -1);
+	return self->priv->start_time;
 }
 
 /**
@@ -431,55 +434,50 @@ gdata_gd_when_get_start_time (GDataGDWhen *self, GTimeVal *start_time)
  * Since: 0.4.0
  **/
 void
-gdata_gd_when_set_start_time (GDataGDWhen *self, const GTimeVal *start_time)
+gdata_gd_when_set_start_time (GDataGDWhen *self, gint64 start_time)
 {
 	g_return_if_fail (GDATA_IS_GD_WHEN (self));
-	g_return_if_fail (start_time != NULL);
+	g_return_if_fail (start_time >= 0);
 
-	self->priv->start_time = *start_time;
+	self->priv->start_time = start_time;
 	g_object_notify (G_OBJECT (self), "start-time");
 }
 
 /**
  * gdata_gd_when_get_end_time:
  * @self: a #GDataGDWhen
- * @end_time: (out caller-allocates): return location for the end time
  *
- * Gets the #GDataGDWhen:end-time property and returns it in @end_time.
+ * Gets the #GDataGDWhen:end-time property.
  *
- * If the end time is unset, both fields of the #GTimeVal will be <code class="literal">0</code>.
+ * If the end time is unset, <code class="literal">-1</code> will be returned.
  *
  * Since: 0.4.0
  **/
-void
-gdata_gd_when_get_end_time (GDataGDWhen *self, GTimeVal *end_time)
+gint64
+gdata_gd_when_get_end_time (GDataGDWhen *self)
 {
-	g_return_if_fail (GDATA_IS_GD_WHEN (self));
-	g_return_if_fail (end_time != NULL);
-	*end_time = self->priv->end_time;
+	g_return_val_if_fail (GDATA_IS_GD_WHEN (self), -1);
+	return self->priv->end_time;
 }
 
 /**
  * gdata_gd_when_set_end_time:
  * @self: a #GDataGDWhen
- * @end_time: (allow-none): the new end time, or %NULL
+ * @end_time: the new end time, or <code class="literal">-1</code>
  *
  * Sets the #GDataGDWhen:end-time property to @end_time.
  *
- * Set @end_time to %NULL to unset the property.
+ * Set @end_time to <code class="literal">-1</code> to unset the property.
  *
  * Since: 0.4.0
  **/
 void
-gdata_gd_when_set_end_time (GDataGDWhen *self, const GTimeVal *end_time)
+gdata_gd_when_set_end_time (GDataGDWhen *self, gint64 end_time)
 {
 	g_return_if_fail (GDATA_IS_GD_WHEN (self));
+	g_return_if_fail (end_time >= -1);
 
-	if (end_time != NULL)
-		self->priv->end_time = *end_time;
-	else
-		self->priv->end_time.tv_sec = self->priv->end_time.tv_usec = 0;
-
+	self->priv->end_time = end_time;
 	g_object_notify (G_OBJECT (self), "end-time");
 }
 
diff --git a/gdata/gd/gdata-gd-when.h b/gdata/gd/gdata-gd-when.h
index 8ab33b0..d916e44 100644
--- a/gdata/gd/gdata-gd-when.h
+++ b/gdata/gd/gdata-gd-when.h
@@ -144,13 +144,13 @@ typedef struct {
 
 GType gdata_gd_when_get_type (void) G_GNUC_CONST;
 
-GDataGDWhen *gdata_gd_when_new (const GTimeVal *start_time, const GTimeVal *end_time, gboolean is_date) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+GDataGDWhen *gdata_gd_when_new (gint64 start_time, gint64 end_time, gboolean is_date) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
-void gdata_gd_when_get_start_time (GDataGDWhen *self, GTimeVal *start_time);
-void gdata_gd_when_set_start_time (GDataGDWhen *self, const GTimeVal *start_time);
+gint64 gdata_gd_when_get_start_time (GDataGDWhen *self);
+void gdata_gd_when_set_start_time (GDataGDWhen *self, gint64 start_time);
 
-void gdata_gd_when_get_end_time (GDataGDWhen *self, GTimeVal *end_time);
-void gdata_gd_when_set_end_time (GDataGDWhen *self, const GTimeVal *end_time);
+gint64 gdata_gd_when_get_end_time (GDataGDWhen *self);
+void gdata_gd_when_set_end_time (GDataGDWhen *self, gint64 end_time);
 
 gboolean gdata_gd_when_is_date (GDataGDWhen *self) G_GNUC_PURE;
 void gdata_gd_when_set_is_date (GDataGDWhen *self, gboolean is_date);
diff --git a/gdata/gdata-access-rule.c b/gdata/gdata-access-rule.c
index 7064584..326ff86 100644
--- a/gdata/gdata-access-rule.c
+++ b/gdata/gdata-access-rule.c
@@ -53,7 +53,7 @@ struct _GDataAccessRulePrivate {
 	gchar *role;
 	gchar *scope_type;
 	gchar *scope_value;
-	GTimeVal edited;
+	gint64 edited;
 };
 
 enum {
@@ -137,9 +137,9 @@ gdata_access_rule_class_init (GDataAccessRuleClass *klass)
 	 * Since: 0.7.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_EDITED,
-	                                 g_param_spec_boxed ("edited",
+	                                 g_param_spec_int64 ("edited",
 	                                                     "Edited", "The last time the access rule was edited.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 }
 
@@ -167,6 +167,7 @@ static void
 gdata_access_rule_init (GDataAccessRule *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_ACCESS_RULE, GDataAccessRulePrivate);
+	self->priv->edited = -1;
 
 	/* Listen to change notifications for the entry's title, since it's linked to GDataAccessRule:role */
 	g_signal_connect (self, "notify::title", (GCallback) notify_title_cb, self);
@@ -184,10 +185,12 @@ gdata_access_rule_constructor (GType type, guint n_construct_params, GObjectCons
 	/* We can't create these in init, or they would collide with the group and control created when parsing the XML */
 	if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
 		GDataAccessRulePrivate *priv = GDATA_ACCESS_RULE (object)->priv;
+		GTimeVal time_val;
 
 		/* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
 		 * setting it from parse_xml() to fail (duplicate element). */
-		g_get_current_time (&(priv->edited));
+		g_get_current_time (&time_val);
+		priv->edited = time_val.tv_sec;
 
 		/* Set up the role and scope type */
 		priv->role = g_strdup (GDATA_ACCESS_ROLE_NONE);
@@ -226,7 +229,7 @@ gdata_access_rule_get_property (GObject *object, guint property_id, GValue *valu
 			g_value_set_string (value, priv->scope_value);
 			break;
 		case PROP_EDITED:
-			g_value_set_boxed (value, &(priv->edited));
+			g_value_set_int64 (value, priv->edited);
 			break;
 		default:
 			/* We don't have any other property... */
@@ -268,7 +271,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	GDataAccessRule *self = GDATA_ACCESS_RULE (parsable);
 
 	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
-	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+	    gdata_parser_int64_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
 	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/acl/2007";) == TRUE) {
 		if (xmlStrcmp (node->name, (xmlChar*) "role") == 0) {
@@ -447,17 +450,16 @@ gdata_access_rule_get_scope (GDataAccessRule *self, const gchar **type, const gc
 /**
  * gdata_access_rule_get_edited:
  * @self: a #GDataAccessRule
- * @edited: (out caller-allocates): return location for the edited time
  *
- * Gets the #GDataAccessRule:edited property and puts it in @edited. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataAccessRule:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the access rule was last edited, or <code class="literal">-1</code>
  *
  * Since: 0.7.0
  **/
-void
-gdata_access_rule_get_edited (GDataAccessRule *self, GTimeVal *edited)
+gint64
+gdata_access_rule_get_edited (GDataAccessRule *self)
 {
-	g_return_if_fail (GDATA_IS_ACCESS_RULE (self));
-	g_return_if_fail (edited != NULL);
-	*edited = self->priv->edited;
+	g_return_val_if_fail (GDATA_IS_ACCESS_RULE (self), -1);
+	return self->priv->edited;
 }
diff --git a/gdata/gdata-access-rule.h b/gdata/gdata-access-rule.h
index 0725406..483a871 100644
--- a/gdata/gdata-access-rule.h
+++ b/gdata/gdata-access-rule.h
@@ -105,7 +105,7 @@ const gchar *gdata_access_rule_get_role (GDataAccessRule *self) G_GNUC_PURE;
 void gdata_access_rule_set_role (GDataAccessRule *self, const gchar *role);
 void gdata_access_rule_get_scope (GDataAccessRule *self, const gchar **type, const gchar **value);
 void gdata_access_rule_set_scope (GDataAccessRule *self, const gchar *type, const gchar *value);
-void gdata_access_rule_get_edited (GDataAccessRule *self, GTimeVal *edited);
+gint64 gdata_access_rule_get_edited (GDataAccessRule *self);
 
 G_END_DECLS
 
diff --git a/gdata/gdata-batch-operation.c b/gdata/gdata-batch-operation.c
index 3fb9123..df3617a 100644
--- a/gdata/gdata-batch-operation.c
+++ b/gdata/gdata-batch-operation.c
@@ -525,7 +525,7 @@ run_cb (gpointer key, BatchOperation *op, GDataFeed *feed)
 		g_free (entry_uri);
 
 		gdata_entry_set_title (entry, "Batch operation query");
-		_gdata_entry_set_updated (entry, &updated);
+		_gdata_entry_set_updated (entry, updated.tv_sec);
 
 		_gdata_entry_set_batch_data (entry, op->id, op->type);
 		_gdata_feed_add_entry (feed, entry);
@@ -578,7 +578,7 @@ gdata_batch_operation_run (GDataBatchOperation *self, GCancellable *cancellable,
 
 	/* Build the request */
 	g_get_current_time (&updated);
-	feed = _gdata_feed_new ("Batch operation feed", "batch1", &updated);
+	feed = _gdata_feed_new ("Batch operation feed", "batch1", updated.tv_sec);
 	g_hash_table_foreach (priv->operations, (GHFunc) run_cb, feed);
 
 	upload_data = gdata_parsable_get_xml (GDATA_PARSABLE (feed));
diff --git a/gdata/gdata-entry.c b/gdata/gdata-entry.c
index ee8c4b8..1a18ade 100644
--- a/gdata/gdata-entry.c
+++ b/gdata/gdata-entry.c
@@ -61,8 +61,8 @@ struct _GDataEntryPrivate {
 	gchar *summary;
 	gchar *id;
 	gchar *etag;
-	GTimeVal updated;
-	GTimeVal published;
+	gint64 updated;
+	gint64 published;
 	GList *categories; /* GDataCategory */
 	gchar *content;
 	gboolean content_is_uri;
@@ -184,9 +184,9 @@ gdata_entry_class_init (GDataEntryClass *klass)
 	 * url="http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.updated";>Atom specification</ulink>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_UPDATED,
-	                                 g_param_spec_boxed ("updated",
+	                                 g_param_spec_int64 ("updated",
 	                                                     "Updated", "The date and time when the entry was most recently updated significantly.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -198,9 +198,9 @@ gdata_entry_class_init (GDataEntryClass *klass)
 	 * url="http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.published";>Atom specification</ulink>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_PUBLISHED,
-	                                 g_param_spec_boxed ("published",
+	                                 g_param_spec_int64 ("published",
 	                                                     "Published", "The date and time the entry was first published or made available.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -266,6 +266,8 @@ static void
 gdata_entry_init (GDataEntry *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_ENTRY, GDataEntryPrivate);
+	self->priv->updated = -1;
+	self->priv->published = -1;
 }
 
 static void
@@ -349,10 +351,10 @@ gdata_entry_get_property (GObject *object, guint property_id, GValue *value, GPa
 			g_value_set_string (value, priv->etag);
 			break;
 		case PROP_UPDATED:
-			g_value_set_boxed (value, &(priv->updated));
+			g_value_set_int64 (value, priv->updated);
 			break;
 		case PROP_PUBLISHED:
-			g_value_set_boxed (value, &(priv->published));
+			g_value_set_int64 (value, priv->published);
 			break;
 		case PROP_CONTENT:
 			g_value_set_string (value, (priv->content_is_uri == FALSE) ? priv->content : NULL);
@@ -429,8 +431,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		    gdata_parser_string_from_element (node, "id", P_REQUIRED | P_NON_EMPTY | P_NO_DUPES, &(priv->id), &success, error) == TRUE ||
 		    gdata_parser_string_from_element (node, "summary", P_NONE, &(priv->summary), &success, error) == TRUE ||
 		    gdata_parser_string_from_element (node, "rights", P_NONE, &(priv->rights), &success, error) == TRUE ||
-		    gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(priv->updated), &success, error) == TRUE ||
-		    gdata_parser_time_val_from_element (node, "published", P_REQUIRED | P_NO_DUPES, &(priv->published), &success, error) == TRUE ||
+		    gdata_parser_int64_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(priv->updated), &success, error) == TRUE ||
+		    gdata_parser_int64_from_element (node, "published", P_REQUIRED | P_NO_DUPES, &(priv->published), &success, error) == TRUE ||
 		    gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_CATEGORY,
 		                                             gdata_entry_add_category, parsable, &success, error) == TRUE ||
 		    gdata_parser_object_from_element_setter (node, "link", P_REQUIRED, GDATA_TYPE_LINK,
@@ -505,14 +507,14 @@ get_xml (GDataParsable *parsable, GString *xml_string)
 	if (priv->id != NULL)
 		g_string_append_printf (xml_string, "<id>%s</id>", priv->id);
 
-	if (priv->updated.tv_sec != 0 || priv->updated.tv_usec != 0) {
-		gchar *updated = g_time_val_to_iso8601 (&(priv->updated));
+	if (priv->updated != -1) {
+		gchar *updated = gdata_parser_int64_to_iso8601 (priv->updated);
 		g_string_append_printf (xml_string, "<updated>%s</updated>", updated);
 		g_free (updated);
 	}
 
-	if (priv->published.tv_sec != 0 || priv->published.tv_usec != 0) {
-		gchar *published = g_time_val_to_iso8601 (&(priv->published));
+	if (priv->published != -1) {
+		gchar *published = gdata_parser_int64_to_iso8601 (priv->published);
 		g_string_append_printf (xml_string, "<published>%s</published>", published);
 		g_free (published);
 	}
@@ -700,16 +702,16 @@ gdata_entry_get_etag (GDataEntry *self)
 /**
  * gdata_entry_get_updated:
  * @self: a #GDataEntry
- * @updated: (out caller-allocates): a #GTimeVal
  *
- * Puts the time the entry was last updated into @updated.
+ * Gets the time the entry was last updated.
+ *
+ * Return value: the UNIX timestamp for the last update of the entry
  **/
-void
-gdata_entry_get_updated (GDataEntry *self, GTimeVal *updated)
+gint64
+gdata_entry_get_updated (GDataEntry *self)
 {
-	g_return_if_fail (GDATA_IS_ENTRY (self));
-	g_return_if_fail (updated != NULL);
-	*updated = self->priv->updated;
+	g_return_val_if_fail (GDATA_IS_ENTRY (self), -1);
+	return self->priv->updated;
 }
 
 /*
@@ -722,27 +724,25 @@ gdata_entry_get_updated (GDataEntry *self, GTimeVal *updated)
  * Since: 0.6.0
  */
 void
-_gdata_entry_set_updated (GDataEntry *self, GTimeVal *updated)
+_gdata_entry_set_updated (GDataEntry *self, gint64 updated)
 {
 	g_return_if_fail (GDATA_IS_ENTRY (self));
-	g_return_if_fail (updated != NULL);
-
-	self->priv->updated = *updated;
+	self->priv->updated = updated;
 }
 
 /**
  * gdata_entry_get_published:
  * @self: a #GDataEntry
- * @published: (out caller-allocates): a #GTimeVal
  *
- * Puts the time the entry was originally published into @published.
+ * Gets the time the entry was originally published.
+ *
+ * Return value: the UNIX timestamp for the original publish time of the entry
  **/
-void
-gdata_entry_get_published (GDataEntry *self, GTimeVal *published)
+gint64
+gdata_entry_get_published (GDataEntry *self)
 {
-	g_return_if_fail (GDATA_IS_ENTRY (self));
-	g_return_if_fail (published != NULL);
-	*published = self->priv->published;
+	g_return_val_if_fail (GDATA_IS_ENTRY (self), -1);
+	return self->priv->published;
 }
 
 /**
@@ -1008,8 +1008,7 @@ gdata_entry_is_inserted (GDataEntry *self)
 {
 	g_return_val_if_fail (GDATA_IS_ENTRY (self), FALSE);
 
-	if (self->priv->id != NULL ||
-	    self->priv->updated.tv_sec != 0 || self->priv->updated.tv_usec != 0)
+	if (self->priv->id != NULL || self->priv->updated != -1)
 		return TRUE;
 	return FALSE;
 }
diff --git a/gdata/gdata-entry.h b/gdata/gdata-entry.h
index c44e746..b0d83bb 100644
--- a/gdata/gdata-entry.h
+++ b/gdata/gdata-entry.h
@@ -75,8 +75,8 @@ const gchar *gdata_entry_get_summary (GDataEntry *self) G_GNUC_PURE;
 void gdata_entry_set_summary (GDataEntry *self, const gchar *summary);
 const gchar *gdata_entry_get_id (GDataEntry *self) G_GNUC_PURE;
 const gchar *gdata_entry_get_etag (GDataEntry *self) G_GNUC_PURE;
-void gdata_entry_get_updated (GDataEntry *self, GTimeVal *updated);
-void gdata_entry_get_published (GDataEntry *self, GTimeVal *published);
+gint64 gdata_entry_get_updated (GDataEntry *self);
+gint64 gdata_entry_get_published (GDataEntry *self);
 void gdata_entry_add_category (GDataEntry *self, GDataCategory *category);
 GList *gdata_entry_get_categories (GDataEntry *self) G_GNUC_PURE;
 const gchar *gdata_entry_get_content (GDataEntry *self) G_GNUC_PURE;
diff --git a/gdata/gdata-feed.c b/gdata/gdata-feed.c
index e1e6825..c270f42 100644
--- a/gdata/gdata-feed.c
+++ b/gdata/gdata-feed.c
@@ -63,7 +63,7 @@ struct _GDataFeedPrivate {
 	gchar *subtitle;
 	gchar *id;
 	gchar *etag;
-	GTimeVal updated;
+	gint64 updated;
 	GList *categories; /* GDataCategory */
 	gchar *logo;
 	gchar *icon;
@@ -176,9 +176,9 @@ gdata_feed_class_init (GDataFeedClass *klass)
 	 * atom:updated</ulink>
 	 **/
 	g_object_class_install_property (gobject_class, PROP_UPDATED,
-	                                 g_param_spec_boxed ("updated",
+	                                 g_param_spec_int64 ("updated",
 	                                                     "Updated", "The time the feed was last updated.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     0, G_MAXINT64, 0,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -295,6 +295,7 @@ static void
 gdata_feed_init (GDataFeed *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_FEED, GDataFeedPrivate);
+	self->priv->updated = -1;
 }
 
 static void
@@ -370,7 +371,7 @@ gdata_feed_get_property (GObject *object, guint property_id, GValue *value, GPar
 			g_value_set_string (value, priv->etag);
 			break;
 		case PROP_UPDATED:
-			g_value_set_boxed (value, &(priv->updated));
+			g_value_set_int64 (value, priv->updated);
 			break;
 		case PROP_LOGO:
 			g_value_set_string (value, priv->logo);
@@ -461,8 +462,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		                                                    _gdata_feed_add_author, self, &success, error) == TRUE ||
 		           gdata_parser_object_from_element (node, "generator", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_GENERATOR,
 		                                             &(self->priv->generator), &success, error) == TRUE ||
-		           gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES,
-		                                               &(self->priv->updated), &success, error) == TRUE ||
+		           gdata_parser_int64_from_element (node, "updated", P_REQUIRED | P_NO_DUPES,
+		                                            &(self->priv->updated), &success, error) == TRUE ||
 		           gdata_parser_string_from_element (node, "rights", P_NONE, &(self->priv->rights), &success, error) == TRUE) {
 			return success;
 		} else {
@@ -534,7 +535,7 @@ post_parse_xml (GDataParsable *parsable, gpointer user_data, GError **error)
 		return gdata_parser_error_required_element_missing ("title", "feed", error);
 	if (priv->id == NULL)
 		return gdata_parser_error_required_element_missing ("id", "feed", error);
-	if (priv->updated.tv_sec == 0 && priv->updated.tv_usec == 0)
+	if (priv->updated == -1)
 		return gdata_parser_error_required_element_missing ("updated", "feed", error);
 
 	/* Reverse our lists of stuff */
@@ -557,7 +558,7 @@ get_xml (GDataParsable *parsable, GString *xml_string)
 	gdata_parser_string_append_escaped (xml_string, "<title type='text'>", priv->title, "</title>");
 	g_string_append_printf (xml_string, "<id>%s</id>", priv->id);
 
-	updated = g_time_val_to_iso8601 (&(priv->updated));
+	updated = gdata_parser_int64_to_iso8601 (priv->updated);
 	g_string_append_printf (xml_string, "<updated>%s</updated>", updated);
 	g_free (updated);
 
@@ -591,19 +592,18 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
  * Since: 0.6.0
  */
 GDataFeed *
-_gdata_feed_new (const gchar *title, const gchar *id, GTimeVal *updated)
+_gdata_feed_new (const gchar *title, const gchar *id, gint64 updated)
 {
 	GDataFeed *feed;
 
 	g_return_val_if_fail (title != NULL, NULL);
 	g_return_val_if_fail (id != NULL, NULL);
-	g_return_val_if_fail (updated != NULL, NULL);
+	g_return_val_if_fail (updated >= 0, NULL);
 
 	feed = g_object_new (GDATA_TYPE_FEED, NULL);
 	feed->priv->title = g_strdup (title);
 	feed->priv->id = g_strdup (id);
-	feed->priv->updated.tv_sec = updated->tv_sec;
-	feed->priv->updated.tv_usec = updated->tv_usec;
+	feed->priv->updated = updated;
 
 	return feed;
 }
@@ -832,16 +832,16 @@ gdata_feed_get_etag (GDataFeed *self)
 /**
  * gdata_feed_get_updated:
  * @self: a #GDataFeed
- * @updated: (out caller-allocates): a #GTimeVal
  *
- * Puts the time the feed was last updated into @updated.
+ * Gets the time the feed was last updated.
+ *
+ * Return value: the UNIX timestamp for the time the feed was last updated
  **/
-void
-gdata_feed_get_updated (GDataFeed *self, GTimeVal *updated)
+gint64
+gdata_feed_get_updated (GDataFeed *self)
 {
-	g_return_if_fail (GDATA_IS_FEED (self));
-	g_return_if_fail (updated != NULL);
-	*updated = self->priv->updated;
+	g_return_val_if_fail (GDATA_IS_FEED (self), -1);
+	return self->priv->updated;
 }
 
 /**
diff --git a/gdata/gdata-feed.h b/gdata/gdata-feed.h
index 3b6e9cd..d1e544e 100644
--- a/gdata/gdata-feed.h
+++ b/gdata/gdata-feed.h
@@ -73,7 +73,7 @@ const gchar *gdata_feed_get_title (GDataFeed *self) G_GNUC_PURE;
 const gchar *gdata_feed_get_subtitle (GDataFeed *self) G_GNUC_PURE;
 const gchar *gdata_feed_get_id (GDataFeed *self) G_GNUC_PURE;
 const gchar *gdata_feed_get_etag (GDataFeed *self) G_GNUC_PURE;
-void gdata_feed_get_updated (GDataFeed *self, GTimeVal *updated);
+gint64 gdata_feed_get_updated (GDataFeed *self);
 const gchar *gdata_feed_get_logo (GDataFeed *self) G_GNUC_PURE;
 GDataGenerator *gdata_feed_get_generator (GDataFeed *self) G_GNUC_PURE;
 const gchar *gdata_feed_get_rights (GDataFeed *self) G_GNUC_PURE;
diff --git a/gdata/gdata-parser.c b/gdata/gdata-parser.c
index 6a4104f..4f8eb48 100644
--- a/gdata/gdata-parser.c
+++ b/gdata/gdata-parser.c
@@ -201,35 +201,63 @@ gdata_parser_error_duplicate_element (xmlNode *element, GError **error)
 }
 
 gboolean
-gdata_parser_time_val_from_date (const gchar *date, GTimeVal *_time)
+gdata_parser_int64_from_date (const gchar *date, gint64 *_time)
 {
 	gchar *iso8601_date;
 	gboolean success;
+	GTimeVal time_val;
 
 	if (strlen (date) != 10 && strlen (date) != 8)
 		return FALSE;
 
 	/* Note: This doesn't need translating, as it's outputting an ISO 8601 time string */
 	iso8601_date = g_strdup_printf ("%sT00:00:00Z", date);
-	success = g_time_val_from_iso8601 (iso8601_date, _time);
+	success = g_time_val_from_iso8601 (iso8601_date, &time_val);
 	g_free (iso8601_date);
 
+	if (success == TRUE)
+		*_time = time_val.tv_sec;
+
 	return success;
 }
 
 gchar *
-gdata_parser_date_from_time_val (const GTimeVal *_time)
+gdata_parser_date_from_int64 (gint64 _time)
 {
 	time_t secs;
 	struct tm *tm;
 
-	secs = _time->tv_sec;
+	secs = _time;
 	tm = gmtime (&secs);
 
 	/* Note: This doesn't need translating, as it's outputting an ISO 8601 date string */
 	return g_strdup_printf ("%04d-%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
 }
 
+gchar *
+gdata_parser_int64_to_iso8601 (gint64 _time)
+{
+	GTimeVal time_val;
+
+	time_val.tv_sec = _time;
+	time_val.tv_usec = 0;
+
+	return g_time_val_to_iso8601 (&time_val);
+}
+
+gboolean
+gdata_parser_int64_from_iso8601 (const gchar *date, gint64 *_time)
+{
+	GTimeVal time_val;
+
+	if (g_time_val_from_iso8601 (date, &time_val) == TRUE) {
+		*_time = time_val.tv_sec;
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 /*
  * gdata_parser_boolean_from_property:
  * @element: the XML element which owns the property to parse
@@ -370,7 +398,7 @@ gdata_parser_string_from_element (xmlNode *element, const gchar *element_name, G
  * @error: a #GError, or %NULL
  *
  * Gets the time value of @element if its name is @element_name, subject to various checks specified by @options. It expects the text content
- * of @element to be a date or time value in ISO 8601 format.
+ * of @element to be a date or time value in ISO 8601 format. The returned time value will be a UNIX timestamp (seconds since the epoch).
  *
  * If @element doesn't match @element_name, %FALSE will be returned, @error will be unset and @success will be unset.
  *
@@ -389,17 +417,18 @@ gdata_parser_string_from_element (xmlNode *element, const gchar *element_name, G
  * Since: 0.7.0
  */
 gboolean
-gdata_parser_time_val_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
-                                    GTimeVal *output, gboolean *success, GError **error)
+gdata_parser_int64_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
+                                 gint64 *output, gboolean *success, GError **error)
 {
 	xmlChar *text;
+	GTimeVal time_val;
 
 	/* Check it's the right element */
 	if (xmlStrcmp (element->name, (xmlChar*) element_name) != 0)
 		return FALSE;
 
 	/* Check if the output time val has already been set */
-	if (options & P_NO_DUPES && (output->tv_sec != 0 || output->tv_usec != 0)) {
+	if (options & P_NO_DUPES && *output != -1) {
 		*success = gdata_parser_error_duplicate_element (element, error);
 		return TRUE;
 	}
@@ -413,12 +442,14 @@ gdata_parser_time_val_from_element (xmlNode *element, const gchar *element_name,
 	}
 
 	/* Attempt to parse the string as a GTimeVal */
-	if (g_time_val_from_iso8601 ((gchar*) text, output) == FALSE) {
+	if (g_time_val_from_iso8601 ((gchar*) text, &time_val) == FALSE) {
 		*success = gdata_parser_error_not_iso8601_format (element, (gchar*) text, error);
 		xmlFree (text);
 		return TRUE;
 	}
 
+	*output = time_val.tv_sec;
+
 	/* Success! */
 	xmlFree (text);
 	*success = TRUE;
diff --git a/gdata/gdata-parser.h b/gdata/gdata-parser.h
index c2d8fd1..997de5c 100644
--- a/gdata/gdata-parser.h
+++ b/gdata/gdata-parser.h
@@ -35,8 +35,10 @@ gboolean gdata_parser_error_mutexed_properties (xmlNode *element, const gchar *p
 gboolean gdata_parser_error_required_element_missing (const gchar *element_name, const gchar *parent_element_name, GError **error);
 gboolean gdata_parser_error_duplicate_element (xmlNode *element, GError **error);
 
-gboolean gdata_parser_time_val_from_date (const gchar *date, GTimeVal *_time);
-gchar *gdata_parser_date_from_time_val (const GTimeVal *_time) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+gboolean gdata_parser_int64_from_date (const gchar *date, gint64 *_time);
+gchar *gdata_parser_date_from_int64 (gint64 _time) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+gchar *gdata_parser_int64_to_iso8601 (gint64 _time) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+gboolean gdata_parser_int64_from_iso8601 (const gchar *date, gint64 *_time);
 
 /*
  * GDataParserOptions:
@@ -69,8 +71,8 @@ gboolean gdata_parser_is_namespace (xmlNode *element, const gchar *namespace_uri
 
 gboolean gdata_parser_string_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
                                            gchar **output, gboolean *success, GError **error);
-gboolean gdata_parser_time_val_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
-                                             GTimeVal *output, gboolean *success, GError **error);
+gboolean gdata_parser_int64_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
+                                          gint64 *output, gboolean *success, GError **error);
 gboolean gdata_parser_object_from_element_setter (xmlNode *element, const gchar *element_name, GDataParserOptions options, GType object_type,
                                                   gpointer /* GDataParserSetterFunc */ _setter, gpointer /* GDataParsable * */ _parent_parsable,
                                                   gboolean *success, GError **error);
diff --git a/gdata/gdata-private.h b/gdata/gdata-private.h
index 786a257..e3f4adf 100644
--- a/gdata/gdata-private.h
+++ b/gdata/gdata-private.h
@@ -70,7 +70,7 @@ G_GNUC_INTERNAL void _gdata_parsable_string_append_escaped (GString *xml_string,
 G_GNUC_INTERNAL gboolean _gdata_parsable_is_constructed_from_xml (GDataParsable *self);
 
 #include "gdata-feed.h"
-G_GNUC_INTERNAL GDataFeed *_gdata_feed_new (const gchar *title, const gchar *id, GTimeVal *updated) G_GNUC_WARN_UNUSED_RESULT;
+G_GNUC_INTERNAL GDataFeed *_gdata_feed_new (const gchar *title, const gchar *id, gint64 updated) G_GNUC_WARN_UNUSED_RESULT;
 G_GNUC_INTERNAL GDataFeed *_gdata_feed_new_from_xml (GType feed_type, const gchar *xml, gint length, GType entry_type,
                                                      GDataQueryProgressCallback progress_callback, gpointer progress_user_data,
                                                      GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
@@ -81,7 +81,7 @@ G_GNUC_INTERNAL void _gdata_feed_call_progress_callback (GDataFeed *self, gpoint
 
 #include "gdata-entry.h"
 #include "gdata-batch-operation.h"
-G_GNUC_INTERNAL void _gdata_entry_set_updated (GDataEntry *self, GTimeVal *updated);
+G_GNUC_INTERNAL void _gdata_entry_set_updated (GDataEntry *self, gint64 updated);
 G_GNUC_INTERNAL void _gdata_entry_set_batch_data (GDataEntry *self, guint id, GDataBatchOperationType type);
 
 #include "gdata/services/documents/gdata-documents-service.h"
diff --git a/gdata/gdata-query.c b/gdata/gdata-query.c
index d6f4477..5d34816 100644
--- a/gdata/gdata-query.c
+++ b/gdata/gdata-query.c
@@ -58,10 +58,10 @@ struct _GDataQueryPrivate {
 	gchar *q;
 	gchar *categories;
 	gchar *author;
-	GTimeVal updated_min;
-	GTimeVal updated_max;
-	GTimeVal published_min;
-	GTimeVal published_max;
+	gint64 updated_min;
+	gint64 updated_max;
+	gint64 published_min;
+	gint64 published_max;
 	gint start_index;
 	gboolean is_strict;
 	gint max_results;
@@ -175,9 +175,9 @@ gdata_query_class_init (GDataQueryClass *klass)
 	 * Lower bound on the entry update date, inclusive.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_UPDATED_MIN,
-	                                 g_param_spec_boxed ("updated-min",
+	                                 g_param_spec_int64 ("updated-min",
 	                                                     "Minimum update date", "Minimum date for updates on returned entries.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -186,9 +186,9 @@ gdata_query_class_init (GDataQueryClass *klass)
 	 * Upper bound on the entry update date, exclusive.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_UPDATED_MAX,
-	                                 g_param_spec_boxed ("updated-max",
+	                                 g_param_spec_int64 ("updated-max",
 	                                                     "Maximum update date", "Maximum date for updates on returned entries.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -197,9 +197,9 @@ gdata_query_class_init (GDataQueryClass *klass)
 	 * Lower bound on the entry publish date, inclusive.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_PUBLISHED_MIN,
-	                                 g_param_spec_boxed ("published-min",
+	                                 g_param_spec_int64 ("published-min",
 	                                                     "Minimum publish date", "Minimum date for returned entries to be published.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -208,9 +208,9 @@ gdata_query_class_init (GDataQueryClass *klass)
 	 * Upper bound on the entry publish date, exclusive.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_PUBLISHED_MAX,
-	                                 g_param_spec_boxed ("published-max",
+	                                 g_param_spec_int64 ("published-max",
 	                                                     "Maximum publish date", "Maximum date for returned entries to be published.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -277,6 +277,10 @@ static void
 gdata_query_init (GDataQuery *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_QUERY, GDataQueryPrivate);
+	self->priv->updated_min = -1;
+	self->priv->updated_max = -1;
+	self->priv->published_min = -1;
+	self->priv->published_max = -1;
 }
 
 static void
@@ -311,16 +315,16 @@ gdata_query_get_property (GObject *object, guint property_id, GValue *value, GPa
 			g_value_set_string (value, priv->author);
 			break;
 		case PROP_UPDATED_MIN:
-			g_value_set_boxed (value, &(priv->updated_min));
+			g_value_set_int64 (value, priv->updated_min);
 			break;
 		case PROP_UPDATED_MAX:
-			g_value_set_boxed (value, &(priv->updated_max));
+			g_value_set_int64 (value, priv->updated_max);
 			break;
 		case PROP_PUBLISHED_MIN:
-			g_value_set_boxed (value, &(priv->published_min));
+			g_value_set_int64 (value, priv->published_min);
 			break;
 		case PROP_PUBLISHED_MAX:
-			g_value_set_boxed (value, &(priv->published_max));
+			g_value_set_int64 (value, priv->published_max);
 			break;
 		case PROP_START_INDEX:
 			g_value_set_uint (value, priv->start_index);
@@ -357,16 +361,16 @@ gdata_query_set_property (GObject *object, guint property_id, const GValue *valu
 			gdata_query_set_author (self, g_value_get_string (value));
 			break;
 		case PROP_UPDATED_MIN:
-			gdata_query_set_updated_min (self, g_value_get_boxed (value));
+			gdata_query_set_updated_min (self, g_value_get_int64 (value));
 			break;
 		case PROP_UPDATED_MAX:
-			gdata_query_set_updated_max (self, g_value_get_boxed (value));
+			gdata_query_set_updated_max (self, g_value_get_int64 (value));
 			break;
 		case PROP_PUBLISHED_MIN:
-			gdata_query_set_published_min (self, g_value_get_boxed (value));
+			gdata_query_set_published_min (self, g_value_get_int64 (value));
 			break;
 		case PROP_PUBLISHED_MAX:
-			gdata_query_set_published_max (self, g_value_get_boxed (value));
+			gdata_query_set_published_max (self, g_value_get_int64 (value));
 			break;
 		case PROP_START_INDEX:
 			gdata_query_set_start_index (self, g_value_get_uint (value));
@@ -413,42 +417,42 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 		g_string_append_uri_escaped (query_uri, priv->author, NULL, FALSE);
 	}
 
-	if (priv->updated_min.tv_sec != 0 || priv->updated_min.tv_usec != 0) {
+	if (priv->updated_min != -1) {
 		gchar *updated_min;
 
 		APPEND_SEP
 		g_string_append (query_uri, "updated-min=");
-		updated_min = g_time_val_to_iso8601 (&(priv->updated_min));
+		updated_min = gdata_parser_int64_to_iso8601 (priv->updated_min);
 		g_string_append (query_uri, updated_min);
 		g_free (updated_min);
 	}
 
-	if (priv->updated_max.tv_sec != 0 || priv->updated_max.tv_usec != 0) {
+	if (priv->updated_max != -1) {
 		gchar *updated_max;
 
 		APPEND_SEP
 		g_string_append (query_uri, "updated-max=");
-		updated_max = g_time_val_to_iso8601 (&(priv->updated_max));
+		updated_max = gdata_parser_int64_to_iso8601 (priv->updated_max);
 		g_string_append (query_uri, updated_max);
 		g_free (updated_max);
 	}
 
-	if (priv->published_min.tv_sec != 0 || priv->published_min.tv_usec != 0) {
+	if (priv->published_min != -1) {
 		gchar *published_min;
 
 		APPEND_SEP
 		g_string_append (query_uri, "published-min=");
-		published_min = g_time_val_to_iso8601 (&(priv->published_min));
+		published_min = gdata_parser_int64_to_iso8601 (priv->published_min);
 		g_string_append (query_uri, published_min);
 		g_free (published_min);
 	}
 
-	if (priv->published_max.tv_sec != 0 || priv->published_max.tv_usec != 0) {
+	if (priv->published_max != -1) {
 		gchar *published_max;
 
 		APPEND_SEP
 		g_string_append (query_uri, "published-max=");
-		published_max = g_time_val_to_iso8601 (&(priv->published_max));
+		published_max = gdata_parser_int64_to_iso8601 (priv->published_max);
 		g_string_append (query_uri, published_max);
 		g_free (published_max);
 	}
@@ -659,40 +663,34 @@ gdata_query_set_author (GDataQuery *self, const gchar *author)
 /**
  * gdata_query_get_updated_min:
  * @self: a #GDataQuery
- * @updated_min: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataQuery:updated-min property and puts it in @updated_min. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataQuery:updated-min property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the updated-min property, or <code class="literal">-1</code>
  **/
-void
-gdata_query_get_updated_min (GDataQuery *self, GTimeVal *updated_min)
+gint64
+gdata_query_get_updated_min (GDataQuery *self)
 {
-	g_return_if_fail (GDATA_IS_QUERY (self));
-	g_return_if_fail (updated_min != NULL);
-	*updated_min = self->priv->updated_min;
+	g_return_val_if_fail (GDATA_IS_QUERY (self), -1);
+	return self->priv->updated_min;
 }
 
 /**
  * gdata_query_set_updated_min:
  * @self: a #GDataQuery
- * @updated_min: (allow-none): the new minimum update time, or %NULL
+ * @updated_min: the new minimum update time, or <code class="literal">-1</code>
  *
  * Sets the #GDataQuery:updated-min property of the #GDataQuery to the new minimum update time, @updated_min.
  *
- * Set @updated_min to %NULL to unset the property in the query URI.
+ * Set @updated_min to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_query_set_updated_min (GDataQuery *self, const GTimeVal *updated_min)
+gdata_query_set_updated_min (GDataQuery *self, gint64 updated_min)
 {
 	g_return_if_fail (GDATA_IS_QUERY (self));
+	g_return_if_fail (updated_min >= -1);
 
-	if (updated_min == NULL) {
-		self->priv->updated_min.tv_sec = 0;
-		self->priv->updated_min.tv_usec = 0;
-	} else {
-		self->priv->updated_min = *updated_min;
-	}
-
+	self->priv->updated_min = updated_min;
 	g_object_notify (G_OBJECT (self), "updated-min");
 
 	/* Our current ETag will no longer be relevant */
@@ -702,40 +700,34 @@ gdata_query_set_updated_min (GDataQuery *self, const GTimeVal *updated_min)
 /**
  * gdata_query_get_updated_max:
  * @self: a #GDataQuery
- * @updated_max: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataQuery:updated-max property and puts it in @updated_max. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataQuery:updated-max property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the updated-max property, or <code class="literal">-1</code>
  **/
-void
-gdata_query_get_updated_max (GDataQuery *self, GTimeVal *updated_max)
+gint64
+gdata_query_get_updated_max (GDataQuery *self)
 {
-	g_return_if_fail (GDATA_IS_QUERY (self));
-	g_return_if_fail (updated_max != NULL);
-	*updated_max = self->priv->updated_max;
+	g_return_val_if_fail (GDATA_IS_QUERY (self), -1);
+	return self->priv->updated_max;
 }
 
 /**
  * gdata_query_set_updated_max:
  * @self: a #GDataQuery
- * @updated_max: (allow-none): the new maximum update time, or %NULL
+ * @updated_max: the new maximum update time, or <code class="literal">-1</code>
  *
  * Sets the #GDataQuery:updated-max property of the #GDataQuery to the new maximum update time, @updated_max.
  *
- * Set @updated_max to %NULL to unset the property in the query URI.
+ * Set @updated_max to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_query_set_updated_max (GDataQuery *self, const GTimeVal *updated_max)
+gdata_query_set_updated_max (GDataQuery *self, gint64 updated_max)
 {
 	g_return_if_fail (GDATA_IS_QUERY (self));
+	g_return_if_fail (updated_max >= -1);
 
-	if (updated_max == NULL) {
-		self->priv->updated_max.tv_sec = 0;
-		self->priv->updated_max.tv_usec = 0;
-	} else {
-		self->priv->updated_max = *updated_max;
-	}
-
+	self->priv->updated_max = updated_max;
 	g_object_notify (G_OBJECT (self), "updated-max");
 
 	/* Our current ETag will no longer be relevant */
@@ -745,40 +737,34 @@ gdata_query_set_updated_max (GDataQuery *self, const GTimeVal *updated_max)
 /**
  * gdata_query_get_published_min:
  * @self: a #GDataQuery
- * @published_min: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataQuery:published-min property and puts it in @published_min. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataQuery:published-min property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the published-min property, or <code class="literal">-1</code>
  **/
-void
-gdata_query_get_published_min (GDataQuery *self, GTimeVal *published_min)
+gint64
+gdata_query_get_published_min (GDataQuery *self)
 {
-	g_return_if_fail (GDATA_IS_QUERY (self));
-	g_return_if_fail (published_min != NULL);
-	*published_min = self->priv->published_min;
+	g_return_val_if_fail (GDATA_IS_QUERY (self), -1);
+	return self->priv->published_min;
 }
 
 /**
  * gdata_query_set_published_min:
  * @self: a #GDataQuery
- * @published_min: (allow-none): the new minimum publish time, or %NULL
+ * @published_min: the new minimum publish time, or <code class="literal">-1</code>
  *
  * Sets the #GDataQuery:published-min property of the #GDataQuery to the new minimum publish time, @published_min.
  *
- * Set @published_min to %NULL to unset the property in the query URI.
+ * Set @published_min to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_query_set_published_min (GDataQuery *self, const GTimeVal *published_min)
+gdata_query_set_published_min (GDataQuery *self, gint64 published_min)
 {
 	g_return_if_fail (GDATA_IS_QUERY (self));
+	g_return_if_fail (published_min >= -1);
 
-	if (published_min == NULL) {
-		self->priv->published_min.tv_sec = 0;
-		self->priv->published_min.tv_usec = 0;
-	} else {
-		self->priv->published_min = *published_min;
-	}
-
+	self->priv->published_min = published_min;
 	g_object_notify (G_OBJECT (self), "published-min");
 
 	/* Our current ETag will no longer be relevant */
@@ -788,40 +774,34 @@ gdata_query_set_published_min (GDataQuery *self, const GTimeVal *published_min)
 /**
  * gdata_query_get_published_max:
  * @self: a #GDataQuery
- * @published_max: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataQuery:published-max property and puts it in @published_max. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataQuery:published-max property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the published-max property, or <code class="literal">-1</code>
  **/
-void
-gdata_query_get_published_max (GDataQuery *self, GTimeVal *published_max)
+gint64
+gdata_query_get_published_max (GDataQuery *self)
 {
-	g_return_if_fail (GDATA_IS_QUERY (self));
-	g_return_if_fail (published_max != NULL);
-	*published_max = self->priv->published_max;
+	g_return_val_if_fail (GDATA_IS_QUERY (self), -1);
+	return self->priv->published_max;
 }
 
 /**
  * gdata_query_set_published_max:
  * @self: a #GDataQuery
- * @published_max: (allow-none): the new maximum publish time, or %NULL
+ * @published_max: the new maximum publish time, or <code class="literal">-1</code>
  *
  * Sets the #GDataQuery:published-max property of the #GDataQuery to the new maximum publish time, @published_max.
  *
- * Set @published_max to %NULL to unset the property in the query URI.
+ * Set @published_max to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_query_set_published_max (GDataQuery *self, const GTimeVal *published_max)
+gdata_query_set_published_max (GDataQuery *self, gint64 published_max)
 {
 	g_return_if_fail (GDATA_IS_QUERY (self));
+	g_return_if_fail (published_max >= -1);
 
-	if (published_max == NULL) {
-		self->priv->published_max.tv_sec = 0;
-		self->priv->published_max.tv_usec = 0;
-	} else {
-		self->priv->published_max = *published_max;
-	}
-
+	self->priv->published_max = published_max;
 	g_object_notify (G_OBJECT (self), "published-max");
 
 	/* Our current ETag will no longer be relevant */
diff --git a/gdata/gdata-query.h b/gdata/gdata-query.h
index 858c2db..4286625 100644
--- a/gdata/gdata-query.h
+++ b/gdata/gdata-query.h
@@ -71,14 +71,14 @@ const gchar *gdata_query_get_categories (GDataQuery *self) G_GNUC_PURE;
 void gdata_query_set_categories (GDataQuery *self, const gchar *categories);
 const gchar *gdata_query_get_author (GDataQuery *self) G_GNUC_PURE;
 void gdata_query_set_author (GDataQuery *self, const gchar *author);
-void gdata_query_get_updated_min (GDataQuery *self, GTimeVal *updated_min);
-void gdata_query_set_updated_min (GDataQuery *self, const GTimeVal *updated_min);
-void gdata_query_get_updated_max (GDataQuery *self, GTimeVal *updated_max);
-void gdata_query_set_updated_max (GDataQuery *self, const GTimeVal *updated_max);
-void gdata_query_get_published_min (GDataQuery *self, GTimeVal *published_min);
-void gdata_query_set_published_min (GDataQuery *self, const GTimeVal *published_min);
-void gdata_query_get_published_max (GDataQuery *self, GTimeVal *published_max);
-void gdata_query_set_published_max (GDataQuery *self, const GTimeVal *published_max);
+gint64 gdata_query_get_updated_min (GDataQuery *self);
+void gdata_query_set_updated_min (GDataQuery *self, gint64 updated_min);
+gint64 gdata_query_get_updated_max (GDataQuery *self);
+void gdata_query_set_updated_max (GDataQuery *self, gint64 updated_max);
+gint64 gdata_query_get_published_min (GDataQuery *self);
+void gdata_query_set_published_min (GDataQuery *self, gint64 published_min);
+gint64 gdata_query_get_published_max (GDataQuery *self);
+void gdata_query_set_published_max (GDataQuery *self, gint64 published_max);
 guint gdata_query_get_start_index (GDataQuery *self) G_GNUC_PURE;
 void gdata_query_set_start_index (GDataQuery *self, guint start_index);
 gboolean gdata_query_is_strict (GDataQuery *self) G_GNUC_PURE;
diff --git a/gdata/gdata-types.c b/gdata/gdata-types.c
index e5612e2..ecc6a9d 100644
--- a/gdata/gdata-types.c
+++ b/gdata/gdata-types.c
@@ -36,26 +36,6 @@
 #include "gdata-types.h"
 
 static gpointer
-gdata_g_time_val_copy (gpointer time_val)
-{
-	return g_memdup (time_val, sizeof (GTimeVal));
-}
-
-GType
-gdata_g_time_val_get_type (void)
-{
-	static GType type_id = 0;
-
-	if (type_id == 0) {
-		type_id = g_boxed_type_register_static (g_intern_static_string ("GDataTimeVal"),
-		                                        (GBoxedCopyFunc) gdata_g_time_val_copy,
-		                                        (GBoxedFreeFunc) g_free);
-	}
-
-	return type_id;
-}
-
-static gpointer
 gdata_color_copy (gpointer color)
 {
 	return g_memdup (color, sizeof (GDataColor));
diff --git a/gdata/gdata-types.h b/gdata/gdata-types.h
index 9bb2f37..5b1cb1e 100644
--- a/gdata/gdata-types.h
+++ b/gdata/gdata-types.h
@@ -24,9 +24,6 @@
 
 G_BEGIN_DECLS
 
-#define GDATA_TYPE_G_TIME_VAL (gdata_g_time_val_get_type ())
-GType gdata_g_time_val_get_type (void) G_GNUC_CONST;
-
 /**
  * GDataColor:
  * @red: red color intensity, from 0â??255
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index 5eb1ee1..119cb9b 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -99,7 +99,6 @@ gdata_query_get_max_results
 gdata_query_set_max_results
 gdata_query_get_etag
 gdata_query_set_etag
-gdata_g_time_val_get_type
 gdata_youtube_standard_feed_type_get_type
 gdata_youtube_service_error_get_type
 gdata_youtube_service_get_type
diff --git a/gdata/services/calendar/gdata-calendar-calendar.c b/gdata/services/calendar/gdata-calendar-calendar.c
index 2b5708c..c31a838 100644
--- a/gdata/services/calendar/gdata-calendar-calendar.c
+++ b/gdata/services/calendar/gdata-calendar-calendar.c
@@ -63,7 +63,7 @@ struct _GDataCalendarCalendarPrivate {
 	gboolean is_selected;
 	gchar *access_level;
 
-	GTimeVal edited;
+	gint64 edited;
 };
 
 enum {
@@ -180,9 +180,9 @@ gdata_calendar_calendar_class_init (GDataCalendarCalendarClass *klass)
 	 * Atom Publishing Protocol specification</ulink>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_EDITED,
-	                                 g_param_spec_boxed ("edited",
+	                                 g_param_spec_int64 ("edited",
 	                                                     "Edited", "The last time the calendar was edited.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 }
 
@@ -202,6 +202,7 @@ static void
 gdata_calendar_calendar_init (GDataCalendarCalendar *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_CALENDAR_CALENDAR, GDataCalendarCalendarPrivate);
+	self->priv->edited = -1;
 }
 
 static GObject *
@@ -214,10 +215,12 @@ gdata_calendar_calendar_constructor (GType type, guint n_construct_params, GObje
 
 	if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
 		GDataCalendarCalendarPrivate *priv = GDATA_CALENDAR_CALENDAR (object)->priv;
+		GTimeVal time_val;
 
 		/* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
 		 * setting it from parse_xml() to fail (duplicate element). */
-		g_get_current_time (&(priv->edited));
+		g_get_current_time (&time_val);
+		priv->edited = time_val.tv_sec;
 	}
 
 	return object;
@@ -260,7 +263,7 @@ gdata_calendar_calendar_get_property (GObject *object, guint property_id, GValue
 			g_value_set_string (value, priv->access_level);
 			break;
 		case PROP_EDITED:
-			g_value_set_boxed (value, &(priv->edited));
+			g_value_set_int64 (value, priv->edited);
 			break;
 		default:
 			/* We don't have any other property... */
@@ -301,7 +304,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	GDataCalendarCalendar *self = GDATA_CALENDAR_CALENDAR (parsable);
 
 	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
-	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+	    gdata_parser_int64_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
 	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/gCal/2005";) == TRUE) {
 		if (xmlStrcmp (node->name, (xmlChar*) "timezone") == 0) {
@@ -585,15 +588,14 @@ gdata_calendar_calendar_get_access_level (GDataCalendarCalendar *self)
 /**
  * gdata_calendar_calendar_get_edited:
  * @self: a #GDataCalendarCalendar
- * @edited: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataCalendarCalendar:edited property and puts it in @edited. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataCalendarCalendar:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the calendar was last edited, or <code class="literal">-1</code>
  **/
-void
-gdata_calendar_calendar_get_edited (GDataCalendarCalendar *self, GTimeVal *edited)
+gint64
+gdata_calendar_calendar_get_edited (GDataCalendarCalendar *self)
 {
-	g_return_if_fail (GDATA_IS_CALENDAR_CALENDAR (self));
-	g_return_if_fail (edited != NULL);
-	*edited = self->priv->edited;
+	g_return_val_if_fail (GDATA_IS_CALENDAR_CALENDAR (self), -1);
+	return self->priv->edited;
 }
diff --git a/gdata/services/calendar/gdata-calendar-calendar.h b/gdata/services/calendar/gdata-calendar-calendar.h
index 820fbc7..f7cb7d6 100644
--- a/gdata/services/calendar/gdata-calendar-calendar.h
+++ b/gdata/services/calendar/gdata-calendar-calendar.h
@@ -117,7 +117,7 @@ void gdata_calendar_calendar_set_color (GDataCalendarCalendar *self, const GData
 gboolean gdata_calendar_calendar_is_selected (GDataCalendarCalendar *self) G_GNUC_PURE;
 void gdata_calendar_calendar_set_is_selected (GDataCalendarCalendar *self, gboolean is_selected);
 const gchar *gdata_calendar_calendar_get_access_level (GDataCalendarCalendar *self) G_GNUC_PURE;
-void gdata_calendar_calendar_get_edited (GDataCalendarCalendar *self, GTimeVal *edited);
+gint64 gdata_calendar_calendar_get_edited (GDataCalendarCalendar *self);
 
 G_END_DECLS
 
diff --git a/gdata/services/calendar/gdata-calendar-event.c b/gdata/services/calendar/gdata-calendar-event.c
index de93484..b3aeb89 100644
--- a/gdata/services/calendar/gdata-calendar-event.c
+++ b/gdata/services/calendar/gdata-calendar-event.c
@@ -52,7 +52,7 @@ static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node,
 static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
 
 struct _GDataCalendarEventPrivate {
-	GTimeVal edited;
+	gint64 edited;
 	gchar *status;
 	gchar *visibility;
 	gchar *transparency;
@@ -119,9 +119,9 @@ gdata_calendar_event_class_init (GDataCalendarEventClass *klass)
 	 * Atom Publishing Protocol specification</ulink>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_EDITED,
-	                                 g_param_spec_boxed ("edited",
+	                                 g_param_spec_int64 ("edited",
 	                                                     "Edited", "The last time the event was edited.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -294,6 +294,7 @@ static void
 gdata_calendar_event_init (GDataCalendarEvent *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_CALENDAR_EVENT, GDataCalendarEventPrivate);
+	self->priv->edited = -1;
 }
 
 static GObject *
@@ -306,10 +307,12 @@ gdata_calendar_event_constructor (GType type, guint n_construct_params, GObjectC
 
 	if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
 		GDataCalendarEventPrivate *priv = GDATA_CALENDAR_EVENT (object)->priv;
+		GTimeVal time_val;
 
 		/* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
 		 * setting it from parse_xml() to fail (duplicate element). */
-		g_get_current_time (&(priv->edited));
+		g_get_current_time (&time_val);
+		priv->edited = time_val.tv_sec;
 	}
 
 	return object;
@@ -366,7 +369,7 @@ gdata_calendar_event_get_property (GObject *object, guint property_id, GValue *v
 
 	switch (property_id) {
 		case PROP_EDITED:
-			g_value_set_boxed (value, &(priv->edited));
+			g_value_set_int64 (value, priv->edited);
 			break;
 		case PROP_STATUS:
 			g_value_set_string (value, priv->status);
@@ -461,7 +464,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	GDataCalendarEvent *self = GDATA_CALENDAR_EVENT (parsable);
 
 	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
-	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+	    gdata_parser_int64_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
 	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE) {
 		if (gdata_parser_object_from_element_setter (node, "when", P_REQUIRED, GDATA_TYPE_GD_WHEN,
@@ -651,17 +654,16 @@ gdata_calendar_event_new (const gchar *id)
 /**
  * gdata_calendar_event_get_edited:
  * @self: a #GDataCalendarEvent
- * @edited: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataCalendarEvent:edited property and puts it in @edited. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataCalendarEvent:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the event was last edited, or <code class="literal">-1</code>
  **/
-void
-gdata_calendar_event_get_edited (GDataCalendarEvent *self, GTimeVal *edited)
+gint64
+gdata_calendar_event_get_edited (GDataCalendarEvent *self)
 {
-	g_return_if_fail (GDATA_IS_CALENDAR_EVENT (self));
-	g_return_if_fail (edited != NULL);
-	*edited = self->priv->edited;
+	g_return_val_if_fail (GDATA_IS_CALENDAR_EVENT (self), -1);
+	return self->priv->edited;
 }
 
 /**
@@ -1068,8 +1070,8 @@ gdata_calendar_event_get_times (GDataCalendarEvent *self)
 /**
  * gdata_calendar_event_get_primary_time:
  * @self: a #GDataCalendarEvent
- * @start_time: (out caller-allocates): a #GTimeVal for the start time, or %NULL
- * @end_time: (out caller-allocates): a #GTimeVal for the end time, or %NULL
+ * @start_time: (out caller-allocates): a #gint64 for the start time, or %NULL
+ * @end_time: (out caller-allocates): a #gint64 for the end time, or %NULL
  * @when: (out callee-allocates) (transfer none): a #GDataGDWhen for the primary time structure, or %NULL
  *
  * Gets the first time period associated with the event, conveniently returning just its start and
@@ -1083,7 +1085,7 @@ gdata_calendar_event_get_times (GDataCalendarEvent *self)
  * Since: 0.2.0
  **/
 gboolean
-gdata_calendar_event_get_primary_time (GDataCalendarEvent *self, GTimeVal *start_time, GTimeVal *end_time, GDataGDWhen **when)
+gdata_calendar_event_get_primary_time (GDataCalendarEvent *self, gint64 *start_time, gint64 *end_time, GDataGDWhen **when)
 {
 	GDataGDWhen *primary_when;
 
@@ -1094,9 +1096,9 @@ gdata_calendar_event_get_primary_time (GDataCalendarEvent *self, GTimeVal *start
 
 	primary_when = GDATA_GD_WHEN (self->priv->times->data);
 	if (start_time != NULL)
-		gdata_gd_when_get_start_time (primary_when, start_time);
+		*start_time = gdata_gd_when_get_start_time (primary_when);
 	if (end_time != NULL)
-		gdata_gd_when_get_end_time (primary_when, end_time);
+		*end_time = gdata_gd_when_get_end_time (primary_when);
 	if (when != NULL)
 		*when = primary_when;
 
diff --git a/gdata/services/calendar/gdata-calendar-event.h b/gdata/services/calendar/gdata-calendar-event.h
index f096322..801db56 100644
--- a/gdata/services/calendar/gdata-calendar-event.h
+++ b/gdata/services/calendar/gdata-calendar-event.h
@@ -64,7 +64,7 @@ GType gdata_calendar_event_get_type (void) G_GNUC_CONST;
 
 GDataCalendarEvent *gdata_calendar_event_new (const gchar *id) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
-void gdata_calendar_event_get_edited (GDataCalendarEvent *self, GTimeVal *edited);
+gint64 gdata_calendar_event_get_edited (GDataCalendarEvent *self);
 const gchar *gdata_calendar_event_get_status (GDataCalendarEvent *self) G_GNUC_PURE;
 void gdata_calendar_event_set_status (GDataCalendarEvent *self, const gchar *status);
 const gchar *gdata_calendar_event_get_visibility (GDataCalendarEvent *self) G_GNUC_PURE;
@@ -89,7 +89,7 @@ void gdata_calendar_event_add_place (GDataCalendarEvent *self, GDataGDWhere *whe
 GList *gdata_calendar_event_get_places (GDataCalendarEvent *self) G_GNUC_PURE;
 void gdata_calendar_event_add_time (GDataCalendarEvent *self, GDataGDWhen *when);
 GList *gdata_calendar_event_get_times (GDataCalendarEvent *self) G_GNUC_PURE;
-gboolean gdata_calendar_event_get_primary_time (GDataCalendarEvent *self, GTimeVal *start_time, GTimeVal *end_time, GDataGDWhen **when);
+gboolean gdata_calendar_event_get_primary_time (GDataCalendarEvent *self, gint64 *start_time, gint64 *end_time, GDataGDWhen **when);
 const gchar *gdata_calendar_event_get_recurrence (GDataCalendarEvent *self) G_GNUC_PURE;
 void gdata_calendar_event_set_recurrence (GDataCalendarEvent *self, const gchar *recurrence);
 void gdata_calendar_event_get_original_event_details (GDataCalendarEvent *self, gchar **event_id, gchar **event_uri);
diff --git a/gdata/services/calendar/gdata-calendar-query.c b/gdata/services/calendar/gdata-calendar-query.c
index 58cdc60..26bbc1e 100644
--- a/gdata/services/calendar/gdata-calendar-query.c
+++ b/gdata/services/calendar/gdata-calendar-query.c
@@ -37,6 +37,7 @@
 
 #include "gdata-calendar-query.h"
 #include "gdata-query.h"
+#include "gdata-parser.h"
 
 static void gdata_calendar_query_finalize (GObject *object);
 static void gdata_calendar_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -46,12 +47,12 @@ static void get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *que
 struct _GDataCalendarQueryPrivate {
 	gboolean future_events;
 	gchar *order_by; /* TODO: enum? #defined values? */
-	GTimeVal recurrence_expansion_start;
-	GTimeVal recurrence_expansion_end;
+	gint64 recurrence_expansion_start;
+	gint64 recurrence_expansion_end;
 	gboolean single_events;
 	gchar *sort_order; /* TODO: enum? */
-	GTimeVal start_min;
-	GTimeVal start_max;
+	gint64 start_min;
+	gint64 start_max;
 	gchar *timezone;
 };
 
@@ -114,9 +115,9 @@ gdata_calendar_query_class_init (GDataCalendarQueryClass *klass)
 	 * Specifies the beginning of the time period to expand recurring events for, inclusive.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_RECURRENCE_EXPANSION_START,
-	                                 g_param_spec_boxed ("recurrence-expansion-start",
+	                                 g_param_spec_int64 ("recurrence-expansion-start",
 	                                                     "Recurrence expansion start", "Specifies start of period to expand recurrences for.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -125,9 +126,9 @@ gdata_calendar_query_class_init (GDataCalendarQueryClass *klass)
 	 * Specifies the end of the time period to expand recurring events for, exclusive.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_RECURRENCE_EXPANSION_END,
-	                                 g_param_spec_boxed ("recurrence-expansion-end",
+	                                 g_param_spec_int64 ("recurrence-expansion-end",
 	                                                     "Recurrence expansion end", "Specifies end of period to expand recurrences for.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -164,9 +165,9 @@ gdata_calendar_query_class_init (GDataCalendarQueryClass *klass)
 	 * If not specified, the default #GDataCalendarQuery:start-min is <literal>1970-01-01</literal>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_START_MIN,
-	                                 g_param_spec_boxed ("start-min",
+	                                 g_param_spec_int64 ("start-min",
 	                                                     "Start min", "A timespan such that only events within the timespan are returned.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -180,9 +181,9 @@ gdata_calendar_query_class_init (GDataCalendarQueryClass *klass)
 	 * If not specified, the default #GDataCalendarQuery:start-max is <literal>2031-01-01</literal>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_START_MAX,
-	                                 g_param_spec_boxed ("start-max",
+	                                 g_param_spec_int64 ("start-max",
 	                                                     "Start max", "A timespan such that only events within the timespan are returned.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -203,6 +204,10 @@ static void
 gdata_calendar_query_init (GDataCalendarQuery *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_CALENDAR_QUERY, GDataCalendarQueryPrivate);
+	self->priv->recurrence_expansion_start = -1;
+	self->priv->recurrence_expansion_end = -1;
+	self->priv->start_min = -1;
+	self->priv->start_max = -1;
 }
 
 static void
@@ -231,10 +236,10 @@ gdata_calendar_query_get_property (GObject *object, guint property_id, GValue *v
 			g_value_set_string (value, priv->order_by);
 			break;
 		case PROP_RECURRENCE_EXPANSION_START:
-			g_value_set_boxed (value, &(priv->recurrence_expansion_start));
+			g_value_set_int64 (value, priv->recurrence_expansion_start);
 			break;
 		case PROP_RECURRENCE_EXPANSION_END:
-			g_value_set_boxed (value, &(priv->recurrence_expansion_end));
+			g_value_set_int64 (value, priv->recurrence_expansion_end);
 			break;
 		case PROP_SINGLE_EVENTS:
 			g_value_set_boolean (value, priv->single_events);
@@ -243,10 +248,10 @@ gdata_calendar_query_get_property (GObject *object, guint property_id, GValue *v
 			g_value_set_string (value, priv->sort_order);
 			break;
 		case PROP_START_MIN:
-			g_value_set_boxed (value, &(priv->start_min));
+			g_value_set_int64 (value, priv->start_min);
 			break;
 		case PROP_START_MAX:
-			g_value_set_boxed (value, &(priv->start_max));
+			g_value_set_int64 (value, priv->start_max);
 			break;
 		case PROP_TIMEZONE:
 			g_value_set_string (value, priv->timezone);
@@ -271,10 +276,10 @@ gdata_calendar_query_set_property (GObject *object, guint property_id, const GVa
 			gdata_calendar_query_set_order_by (self, g_value_get_string (value));
 			break;
 		case PROP_RECURRENCE_EXPANSION_START:
-			gdata_calendar_query_set_recurrence_expansion_start (self, g_value_get_boxed (value));
+			gdata_calendar_query_set_recurrence_expansion_start (self, g_value_get_int64 (value));
 			break;
 		case PROP_RECURRENCE_EXPANSION_END:
-			gdata_calendar_query_set_recurrence_expansion_end (self, g_value_get_boxed (value));
+			gdata_calendar_query_set_recurrence_expansion_end (self, g_value_get_int64 (value));
 			break;
 		case PROP_SINGLE_EVENTS:
 			gdata_calendar_query_set_single_events (self, g_value_get_boolean (value));
@@ -283,10 +288,10 @@ gdata_calendar_query_set_property (GObject *object, guint property_id, const GVa
 			gdata_calendar_query_set_sort_order (self, g_value_get_string (value));
 			break;
 		case PROP_START_MIN:
-			gdata_calendar_query_set_start_min (self, g_value_get_boxed (value));
+			gdata_calendar_query_set_start_min (self, g_value_get_int64 (value));
 			break;
 		case PROP_START_MAX:
-			gdata_calendar_query_set_start_max (self, g_value_get_boxed (value));
+			gdata_calendar_query_set_start_max (self, g_value_get_int64 (value));
 			break;
 		case PROP_TIMEZONE:
 			gdata_calendar_query_set_timezone (self, g_value_get_string (value));
@@ -320,22 +325,22 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 		g_string_append_uri_escaped (query_uri, priv->order_by, NULL, FALSE);
 	}
 
-	if (priv->recurrence_expansion_start.tv_sec != 0 || priv->recurrence_expansion_start.tv_usec != 0) {
+	if (priv->recurrence_expansion_start != -1) {
 		gchar *recurrence_expansion_start;
 
 		APPEND_SEP
 		g_string_append (query_uri, "recurrence-expansion-start=");
-		recurrence_expansion_start = g_time_val_to_iso8601 (&(priv->recurrence_expansion_start));
+		recurrence_expansion_start = gdata_parser_int64_to_iso8601 (priv->recurrence_expansion_start);
 		g_string_append (query_uri, recurrence_expansion_start);
 		g_free (recurrence_expansion_start);
 	}
 
-	if (priv->recurrence_expansion_end.tv_sec != 0 || priv->recurrence_expansion_end.tv_usec != 0) {
+	if (priv->recurrence_expansion_end != -1) {
 		gchar *recurrence_expansion_end;
 
 		APPEND_SEP
 		g_string_append (query_uri, "recurrence-expansion-end=");
-		recurrence_expansion_end = g_time_val_to_iso8601 (&(priv->recurrence_expansion_end));
+		recurrence_expansion_end = gdata_parser_int64_to_iso8601 (priv->recurrence_expansion_end);
 		g_string_append (query_uri, recurrence_expansion_end);
 		g_free (recurrence_expansion_end);
 	}
@@ -352,22 +357,22 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 		g_string_append_uri_escaped (query_uri, priv->sort_order, NULL, FALSE);
 	}
 
-	if (priv->start_min.tv_sec != 0 || priv->start_min.tv_usec != 0) {
+	if (priv->start_min != -1) {
 		gchar *start_min;
 
 		APPEND_SEP
 		g_string_append (query_uri, "start-min=");
-		start_min = g_time_val_to_iso8601 (&(priv->start_min));
+		start_min = gdata_parser_int64_to_iso8601 (priv->start_min);
 		g_string_append (query_uri, start_min);
 		g_free (start_min);
 	}
 
-	if (priv->start_max.tv_sec != 0 || priv->start_max.tv_usec != 0) {
+	if (priv->start_max != -1) {
 		gchar *start_max;
 
 		APPEND_SEP
 		g_string_append (query_uri, "start-max=");
-		start_max = g_time_val_to_iso8601 (&(priv->start_max));
+		start_max = gdata_parser_int64_to_iso8601 (priv->start_max);
 		g_string_append (query_uri, start_max);
 		g_free (start_max);
 	}
@@ -405,7 +410,7 @@ gdata_calendar_query_new (const gchar *q)
  * Return value: a new #GDataCalendarQuery
  **/
 GDataCalendarQuery *
-gdata_calendar_query_new_with_limits (const gchar *q, const GTimeVal *start_min, const GTimeVal *start_max)
+gdata_calendar_query_new_with_limits (const gchar *q, gint64 start_min, gint64 start_max)
 {
 	return g_object_new (GDATA_TYPE_CALENDAR_QUERY,
 	                     "q", q,
@@ -487,41 +492,35 @@ gdata_calendar_query_set_order_by (GDataCalendarQuery *self, const gchar *order_
 /**
  * gdata_calendar_query_get_recurrence_expansion_start:
  * @self: a #GDataCalendarQuery
- * @start: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataCalendarQuery:recurrence-expansion-start property and puts it
- * in @start. If the property is unset, both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataCalendarQuery:recurrence-expansion-start property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the recurrence-expansion-start property, or <code class="literal">-1</code>
  **/
-void
-gdata_calendar_query_get_recurrence_expansion_start (GDataCalendarQuery *self, GTimeVal *start)
+gint64
+gdata_calendar_query_get_recurrence_expansion_start (GDataCalendarQuery *self)
 {
-	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
-	g_return_if_fail (start != NULL);
-	*start = self->priv->recurrence_expansion_start;
+	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1);
+	return self->priv->recurrence_expansion_start;
 }
 
 /**
  * gdata_calendar_query_set_recurrence_expansion_start:
  * @self: a #GDataCalendarQuery
- * @start: (allow-none): a new start time, or %NULL
+ * @start: a new start time, or <code class="literal">-1</code>
  *
  * Sets the #GDataCalendarQuery:recurrence-expansion-start property of the #GDataCalendarQuery
  * to the new time/date, @start.
  *
- * Set @start to %NULL to unset the property in the query URI.
+ * Set @start to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_calendar_query_set_recurrence_expansion_start (GDataCalendarQuery *self, const GTimeVal *start)
+gdata_calendar_query_set_recurrence_expansion_start (GDataCalendarQuery *self, gint64 start)
 {
 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
+	g_return_if_fail (start >= -1);
 
-	if (start == NULL) {
-		self->priv->recurrence_expansion_start.tv_sec = 0;
-		self->priv->recurrence_expansion_start.tv_usec = 0;
-	} else {
-		self->priv->recurrence_expansion_start = *start;
-	}
-
+	self->priv->recurrence_expansion_start = start;
 	g_object_notify (G_OBJECT (self), "recurrence-expansion-start");
 
 	/* Our current ETag will no longer be relevant */
@@ -531,41 +530,35 @@ gdata_calendar_query_set_recurrence_expansion_start (GDataCalendarQuery *self, c
 /**
  * gdata_calendar_query_get_recurrence_expansion_end:
  * @self: a #GDataCalendarQuery
- * @end: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataCalendarQuery:recurrence-expansion-end property and puts it
- * in @end. If the property is unset, both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataCalendarQuery:recurrence-expansion-end property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the recurrence-expansion-end property, or <code class="literal">-1</code>
  **/
-void
-gdata_calendar_query_get_recurrence_expansion_end (GDataCalendarQuery *self, GTimeVal *end)
+gint64
+gdata_calendar_query_get_recurrence_expansion_end (GDataCalendarQuery *self)
 {
-	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
-	g_return_if_fail (end != NULL);
-	*end = self->priv->recurrence_expansion_end;
+	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1	);
+	return self->priv->recurrence_expansion_end;
 }
 
 /**
  * gdata_calendar_query_set_recurrence_expansion_end:
  * @self: a #GDataCalendarQuery
- * @end: (allow-none): a new end time, or %NULL
+ * @end: a new end time, or <code class="literal">-1</code>
  *
  * Sets the #GDataCalendarQuery:recurrence-expansion-end property of the #GDataCalendarQuery
  * to the new time/date, @end.
  *
- * Set @end to %NULL to unset the property in the query URI.
+ * Set @end to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_calendar_query_set_recurrence_expansion_end (GDataCalendarQuery *self, const GTimeVal *end)
+gdata_calendar_query_set_recurrence_expansion_end (GDataCalendarQuery *self, gint64 end)
 {
 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
+	g_return_if_fail (end >= -1);
 
-	if (end == NULL) {
-		self->priv->recurrence_expansion_end.tv_sec = 0;
-		self->priv->recurrence_expansion_end.tv_usec = 0;
-	} else {
-		self->priv->recurrence_expansion_end = *end;
-	}
-
+	self->priv->recurrence_expansion_end = end;
 	g_object_notify (G_OBJECT (self), "recurrence-expansion-end");
 
 	/* Our current ETag will no longer be relevant */
@@ -645,41 +638,35 @@ gdata_calendar_query_set_sort_order (GDataCalendarQuery *self, const gchar *sort
 /**
  * gdata_calendar_query_get_start_min:
  * @self: a #GDataCalendarQuery
- * @start_min: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataCalendarQuery:start-min property and puts it
- * in @start_min. If the property is unset, both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataCalendarQuery:start-min property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the start-min property, or <code class="literal">-1</code>
  **/
-void
-gdata_calendar_query_get_start_min (GDataCalendarQuery *self, GTimeVal *start_min)
+gint64
+gdata_calendar_query_get_start_min (GDataCalendarQuery *self)
 {
-	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
-	g_return_if_fail (start_min != NULL);
-	*start_min = self->priv->start_min;
+	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1);
+	return self->priv->start_min;
 }
 
 /**
  * gdata_calendar_query_set_start_min:
  * @self: a #GDataCalendarQuery
- * @start_min: (allow-none): a new minimum start time, or %NULL
+ * @start_min: a new minimum start time, or <code class="literal">-1</code>
  *
  * Sets the #GDataCalendarQuery:start-min property of the #GDataCalendarQuery
  * to the new time/date, @start_min.
  *
- * Set @start_min to %NULL to unset the property in the query URI.
+ * Set @start_min to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_calendar_query_set_start_min (GDataCalendarQuery *self, const GTimeVal *start_min)
+gdata_calendar_query_set_start_min (GDataCalendarQuery *self, gint64 start_min)
 {
 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
+	g_return_if_fail (start_min >= -1);
 
-	if (start_min == NULL) {
-		self->priv->start_min.tv_sec = 0;
-		self->priv->start_min.tv_usec = 0;
-	} else {
-		self->priv->start_min = *start_min;
-	}
-
+	self->priv->start_min = start_min;
 	g_object_notify (G_OBJECT (self), "start-min");
 
 	/* Our current ETag will no longer be relevant */
@@ -689,41 +676,35 @@ gdata_calendar_query_set_start_min (GDataCalendarQuery *self, const GTimeVal *st
 /**
  * gdata_calendar_query_get_start_max:
  * @self: a #GDataCalendarQuery
- * @start_max: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataCalendarQuery:start-max property and puts it
- * in @start_max. If the property is unset, both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataCalendarQuery:start-max property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the start-max property, or <code class="literal">-1</code>
  **/
-void
-gdata_calendar_query_get_start_max (GDataCalendarQuery *self, GTimeVal *start_max)
+gint64
+gdata_calendar_query_get_start_max (GDataCalendarQuery *self)
 {
-	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
-	g_return_if_fail (start_max != NULL);
-	*start_max = self->priv->start_max;
+	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1);
+	return self->priv->start_max;
 }
 
 /**
  * gdata_calendar_query_set_start_max:
  * @self: a #GDataCalendarQuery
- * @start_max: (allow-none): a new maximum start time, or %NULL
+ * @start_max: a new maximum start time, or <code class="literal">-1</code>
  *
  * Sets the #GDataCalendarQuery:start-max property of the #GDataCalendarQuery
  * to the new time/date, @start_max.
  *
- * Set @start_max to %NULL to unset the property in the query URI.
+ * Set @start_max to <code class="literal">-1</code> to unset the property in the query URI.
  **/
 void
-gdata_calendar_query_set_start_max (GDataCalendarQuery *self, const GTimeVal *start_max)
+gdata_calendar_query_set_start_max (GDataCalendarQuery *self, gint64 start_max)
 {
 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
+	g_return_if_fail (start_max >= -1);
 
-	if (start_max == NULL) {
-		self->priv->start_max.tv_sec = 0;
-		self->priv->start_max.tv_usec = 0;
-	} else {
-		self->priv->start_max = *start_max;
-	}
-
+	self->priv->start_max = start_max;
 	g_object_notify (G_OBJECT (self), "start-max");
 
 	/* Our current ETag will no longer be relevant */
diff --git a/gdata/services/calendar/gdata-calendar-query.h b/gdata/services/calendar/gdata-calendar-query.h
index 9aecef9..65807b6 100644
--- a/gdata/services/calendar/gdata-calendar-query.h
+++ b/gdata/services/calendar/gdata-calendar-query.h
@@ -60,25 +60,24 @@ typedef struct {
 GType gdata_calendar_query_get_type (void) G_GNUC_CONST;
 
 GDataCalendarQuery *gdata_calendar_query_new (const gchar *q) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
-GDataCalendarQuery *gdata_calendar_query_new_with_limits (const gchar *q, const GTimeVal *start_min,
-                                                          const GTimeVal *start_max) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+GDataCalendarQuery *gdata_calendar_query_new_with_limits (const gchar *q, gint64 start_min, gint64 start_max) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 gboolean gdata_calendar_query_get_future_events (GDataCalendarQuery *self) G_GNUC_PURE;
 void gdata_calendar_query_set_future_events (GDataCalendarQuery *self, gboolean future_events);
 const gchar *gdata_calendar_query_get_order_by (GDataCalendarQuery *self) G_GNUC_PURE;
 void gdata_calendar_query_set_order_by (GDataCalendarQuery *self, const gchar *order_by);
-void gdata_calendar_query_get_recurrence_expansion_start (GDataCalendarQuery *self, GTimeVal *start);
-void gdata_calendar_query_set_recurrence_expansion_start (GDataCalendarQuery *self, const GTimeVal *start);
-void gdata_calendar_query_get_recurrence_expansion_end (GDataCalendarQuery *self, GTimeVal *end);
-void gdata_calendar_query_set_recurrence_expansion_end (GDataCalendarQuery *self, const GTimeVal *end);
+gint64 gdata_calendar_query_get_recurrence_expansion_start (GDataCalendarQuery *self);
+void gdata_calendar_query_set_recurrence_expansion_start (GDataCalendarQuery *self, gint64 start);
+gint64 gdata_calendar_query_get_recurrence_expansion_end (GDataCalendarQuery *self);
+void gdata_calendar_query_set_recurrence_expansion_end (GDataCalendarQuery *self, gint64 end);
 gboolean gdata_calendar_query_get_single_events (GDataCalendarQuery *self) G_GNUC_PURE;
 void gdata_calendar_query_set_single_events (GDataCalendarQuery *self, gboolean single_events);
 const gchar *gdata_calendar_query_get_sort_order (GDataCalendarQuery *self) G_GNUC_PURE;
 void gdata_calendar_query_set_sort_order (GDataCalendarQuery *self, const gchar *sort_order);
-void gdata_calendar_query_get_start_min (GDataCalendarQuery *self, GTimeVal *start_min);
-void gdata_calendar_query_set_start_min (GDataCalendarQuery *self, const GTimeVal *start_min);
-void gdata_calendar_query_get_start_max (GDataCalendarQuery *self, GTimeVal *start_max);
-void gdata_calendar_query_set_start_max (GDataCalendarQuery *self, const GTimeVal *start_max);
+gint64 gdata_calendar_query_get_start_min (GDataCalendarQuery *self);
+void gdata_calendar_query_set_start_min (GDataCalendarQuery *self, gint64 start_min);
+gint64 gdata_calendar_query_get_start_max (GDataCalendarQuery *self);
+void gdata_calendar_query_set_start_max (GDataCalendarQuery *self, gint64 start_max);
 const gchar *gdata_calendar_query_get_timezone (GDataCalendarQuery *self) G_GNUC_PURE;
 void gdata_calendar_query_set_timezone (GDataCalendarQuery *self, const gchar *_timezone);
 
diff --git a/gdata/services/contacts/gdata-contacts-contact.c b/gdata/services/contacts/gdata-contacts-contact.c
index d8b9e8f..a833e55 100644
--- a/gdata/services/contacts/gdata-contacts-contact.c
+++ b/gdata/services/contacts/gdata-contacts-contact.c
@@ -67,7 +67,7 @@ static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
 static gchar *get_entry_uri (const gchar *id) G_GNUC_WARN_UNUSED_RESULT;
 
 struct _GDataContactsContactPrivate {
-	GTimeVal edited;
+	gint64 edited;
 	GDataGDName *name;
 	GList *email_addresses; /* GDataGDEmailAddress */
 	GList *im_addresses; /* GDataGDIMAddress */
@@ -159,9 +159,9 @@ gdata_contacts_contact_class_init (GDataContactsContactClass *klass)
 	 * Since: 0.2.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_EDITED,
-	                                 g_param_spec_boxed ("edited",
+	                                 g_param_spec_int64 ("edited",
 	                                                     "Edited", "The last time the contact was edited.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -414,6 +414,7 @@ gdata_contacts_contact_init (GDataContactsContact *self)
 	self->priv->extended_properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 	self->priv->user_defined_fields = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 	self->priv->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	self->priv->edited = -1;
 
 	/* Create a default name, so the name's properties can be set for a blank contact */
 	self->priv->name = gdata_gd_name_new (NULL, NULL);
@@ -460,10 +461,12 @@ gdata_contacts_contact_constructor (GType type, guint n_construct_params, GObjec
 
 	if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
 		GDataContactsContactPrivate *priv = GDATA_CONTACTS_CONTACT (object)->priv;
+		GTimeVal time_val;
 
 		/* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
 		 * setting it from parse_xml() to fail (duplicate element). */
-		g_get_current_time (&(priv->edited));
+		g_get_current_time (&time_val);
+		priv->edited = time_val.tv_sec;
 	}
 
 	return object;
@@ -533,7 +536,7 @@ gdata_contacts_contact_get_property (GObject *object, guint property_id, GValue
 
 	switch (property_id) {
 		case PROP_EDITED:
-			g_value_set_boxed (value, &(priv->edited));
+			g_value_set_int64 (value, priv->edited);
 			break;
 		case PROP_DELETED:
 			g_value_set_boolean (value, priv->deleted);
@@ -658,7 +661,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	GDataContactsContact *self = GDATA_CONTACTS_CONTACT (parsable);
 
 	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
-	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+	    gdata_parser_int64_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
 	} else if (gdata_parser_is_namespace (node, "http://www.w3.org/2005/Atom";) == TRUE && xmlStrcmp (node->name, (xmlChar*) "id") == 0) {
 		/* We have to override <id> parsing to fix the projection. Modify it in-place so that the parser in GDataEntry will pick up
@@ -1088,19 +1091,18 @@ gdata_contacts_contact_new (const gchar *id)
 /**
  * gdata_contacts_contact_get_edited:
  * @self: a #GDataContactsContact
- * @edited: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataContactsContact:edited property and puts it in @edited. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataContactsContact:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the contact was last edited, or <code class="literal">-1</code>
  *
  * Since: 0.2.0
  **/
-void
-gdata_contacts_contact_get_edited (GDataContactsContact *self, GTimeVal *edited)
+gint64
+gdata_contacts_contact_get_edited (GDataContactsContact *self)
 {
-	g_return_if_fail (GDATA_IS_CONTACTS_CONTACT (self));
-	g_return_if_fail (edited != NULL);
-	*edited = self->priv->edited;
+	g_return_val_if_fail (GDATA_IS_CONTACTS_CONTACT (self), -1);
+	return self->priv->edited;
 }
 
 /**
diff --git a/gdata/services/contacts/gdata-contacts-contact.h b/gdata/services/contacts/gdata-contacts-contact.h
index 7eb86e3..1c2f999 100644
--- a/gdata/services/contacts/gdata-contacts-contact.h
+++ b/gdata/services/contacts/gdata-contacts-contact.h
@@ -158,7 +158,7 @@ GType gdata_contacts_contact_get_type (void) G_GNUC_CONST;
 
 GDataContactsContact *gdata_contacts_contact_new (const gchar *id) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
-void gdata_contacts_contact_get_edited (GDataContactsContact *self, GTimeVal *edited);
+gint64 gdata_contacts_contact_get_edited (GDataContactsContact *self);
 gboolean gdata_contacts_contact_is_deleted (GDataContactsContact *self) G_GNUC_PURE;
 
 GDataGDName *gdata_contacts_contact_get_name (GDataContactsContact *self) G_GNUC_PURE;
diff --git a/gdata/services/documents/gdata-documents-entry.c b/gdata/services/documents/gdata-documents-entry.c
index 14cf552..f401e9c 100644
--- a/gdata/services/documents/gdata-documents-entry.c
+++ b/gdata/services/documents/gdata-documents-entry.c
@@ -59,8 +59,8 @@ static void gdata_documents_entry_set_property (GObject *object, guint property_
 static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error);
 
 struct _GDataDocumentsEntryPrivate {
-	GTimeVal edited;
-	GTimeVal last_viewed;
+	gint64 edited;
+	gint64 last_viewed;
 	gchar *document_id;
 	gboolean writers_can_invite;
 	gboolean is_deleted;
@@ -108,9 +108,9 @@ gdata_documents_entry_class_init (GDataDocumentsEntryClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_EDITED,
-	                                 g_param_spec_boxed ("edited",
+	                                 g_param_spec_int64 ("edited",
 	                                                     "Edited", "The last time the document was edited.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -121,9 +121,9 @@ gdata_documents_entry_class_init (GDataDocumentsEntryClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_LAST_VIEWED,
-	                                 g_param_spec_boxed ("last-viewed",
+	                                 g_param_spec_int64 ("last-viewed",
 	                                                     "Last viewed", "The last time the document was viewed.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -197,6 +197,8 @@ static void
 gdata_documents_entry_init (GDataDocumentsEntry *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_DOCUMENTS_ENTRY, GDataDocumentsEntryPrivate);
+	self->priv->edited = -1;
+	self->priv->last_viewed = -1;
 }
 
 static GObject *
@@ -210,10 +212,12 @@ gdata_documents_entry_constructor (GType type, guint n_construct_params, GObject
 	/* We can't create these in init, or they would collide with the group and control created when parsing the XML */
 	if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
 		GDataDocumentsEntryPrivate *priv = GDATA_DOCUMENTS_ENTRY (object)->priv;
+		GTimeVal time_val;
 
 		/* This can't be put in the init function of #GDataDocumentsEntry, as it would then be called even for entries parsed from XML from
 		 * the server, which would break duplicate element detection for the app:edited element. */
-		g_get_current_time (&(priv->edited));
+		g_get_current_time (&time_val);
+		priv->edited = time_val.tv_sec;
 	}
 
 	return object;
@@ -259,10 +263,10 @@ gdata_documents_entry_get_property (GObject *object, guint property_id, GValue *
 			g_value_set_boolean (value, priv->is_deleted);
 			break;
 		case PROP_EDITED:
-			g_value_set_boxed (value, &(priv->edited));
+			g_value_set_int64 (value, priv->edited);
 			break;
 		case PROP_LAST_VIEWED:
-			g_value_set_boxed (value, &(priv->last_viewed));
+			g_value_set_int64 (value, priv->last_viewed);
 			break;
 		case PROP_LAST_MODIFIED_BY:
 			g_value_set_object (value, priv->last_modified_by);
@@ -297,11 +301,11 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	GDataDocumentsEntry *self = GDATA_DOCUMENTS_ENTRY (parsable);
 
 	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
-	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+	    gdata_parser_int64_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
 	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE) {
-		if (gdata_parser_time_val_from_element (node, "lastViewed", P_REQUIRED | P_NO_DUPES,
-		                                        &(self->priv->last_viewed), &success, error) == TRUE ||
+		if (gdata_parser_int64_from_element (node, "lastViewed", P_REQUIRED | P_NO_DUPES,
+		                                     &(self->priv->last_viewed), &success, error) == TRUE ||
 		    gdata_parser_object_from_element_setter (node, "feedLink", P_REQUIRED, GDATA_TYPE_LINK,
 		                                             gdata_entry_add_link, self,  &success, error) == TRUE ||
 		    gdata_parser_object_from_element (node, "lastModifiedBy", P_REQUIRED, GDATA_TYPE_AUTHOR,
@@ -376,37 +380,35 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
 /**
  * gdata_documents_entry_get_edited:
  * @self: a #GDataDocumentsEntry
- * @edited: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataDocumentsEntry:edited property and puts it in @edited. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataDocumentsEntry:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the document was last edited, or <code class="literal">-1</code>
  *
  * Since: 0.4.0
  **/
-void
-gdata_documents_entry_get_edited (GDataDocumentsEntry *self, GTimeVal *edited)
+gint64
+gdata_documents_entry_get_edited (GDataDocumentsEntry *self)
 {
-	g_return_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self));
-	g_return_if_fail (edited != NULL);
-	*edited = self->priv->edited;
+	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), -1);
+	return self->priv->edited;
 }
 
 /**
  * gdata_documents_entry_get_last_viewed:
  * @self: a #GDataDocumentsEntry
- * @last_viewed: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataDocumentsEntry:last-viewed property and puts it in @last_viewed. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataDocumentsEntry:last-viewed property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the document was last viewed, or <code class="literal">-1</code>
  *
  * Since: 0.4.0
  **/
-void
-gdata_documents_entry_get_last_viewed (GDataDocumentsEntry *self, GTimeVal *last_viewed)
+gint64
+gdata_documents_entry_get_last_viewed (GDataDocumentsEntry *self)
 {
-	g_return_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self));
-	g_return_if_fail (last_viewed != NULL);
-	*last_viewed = self->priv->last_viewed;
+	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), -1);
+	return self->priv->last_viewed;
 }
 
 /**
diff --git a/gdata/services/documents/gdata-documents-entry.h b/gdata/services/documents/gdata-documents-entry.h
index 82de8a0..fdc63c3 100644
--- a/gdata/services/documents/gdata-documents-entry.h
+++ b/gdata/services/documents/gdata-documents-entry.h
@@ -96,8 +96,8 @@ gchar *gdata_documents_entry_get_path (GDataDocumentsEntry *self) G_GNUC_WARN_UN
 
 const gchar *gdata_documents_entry_get_document_id (GDataDocumentsEntry *self) G_GNUC_PURE;
 
-void gdata_documents_entry_get_edited (GDataDocumentsEntry *self, GTimeVal *edited);
-void gdata_documents_entry_get_last_viewed (GDataDocumentsEntry *self, GTimeVal *last_viewed);
+gint64 gdata_documents_entry_get_edited (GDataDocumentsEntry *self);
+gint64 gdata_documents_entry_get_last_viewed (GDataDocumentsEntry *self);
 
 void gdata_documents_entry_set_writers_can_invite (GDataDocumentsEntry *self, gboolean writers_can_invite);
 gboolean gdata_documents_entry_writers_can_invite (GDataDocumentsEntry *self) G_GNUC_PURE;
diff --git a/gdata/services/picasaweb/gdata-picasaweb-album.c b/gdata/services/picasaweb/gdata-picasaweb-album.c
index f790ccd..d1cd344 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-album.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-album.c
@@ -43,7 +43,7 @@
  *		GDataPicasaWebAlbum *album;
  *		guint num_photos;
  *		const gchar *owner_nickname, *title, *summary;
- *		GTimeVal timeval;
+ *		gint64 timestamp;
  *		GList *thumbnails;
  *
  *		album = GDATA_PICASAWEB_ALBUM (album_entries->data);
@@ -53,8 +53,8 @@
  *		owner_nickname = gdata_picasaweb_album_get_nickname (album);
  *		title = gdata_entry_get_title (GDATA_ENTRY (album));
  *		summary = gdata_entry_get_summary (GDATA_ENTRY (album));
- *		/<!-- -->* Get the day the album was shot on or, if not set, when it was uploaded *<!-- -->/
- *		gdata_picasaweb_album_get_timestamp (album, &timeval);
+ *		/<!-- -->* Get the day the album was shot on or, if not set, when it was uploaded. This is in milliseconds since the epoch. *<!-- -->/
+ *		timestamp = gdata_picasaweb_album_get_timestamp (album);
  *
  *		for (thumbnails = gdata_picasaweb_album_get_thumbnails (album); thumbnails != NULL; thumbnails = thumbnails->next) {
  *			GDataMediaThumbnail *thumbnail;
@@ -110,10 +110,10 @@ struct _GDataPicasaWebAlbumPrivate {
 	gchar *album_id;
 	gchar *user;
 	gchar *nickname;
-	GTimeVal edited;
+	gint64 edited;
 	gchar *location;
 	GDataPicasaWebVisibility visibility;
-	GTimeVal timestamp;
+	gint64 timestamp; /* in milliseconds! */
 	guint num_photos;
 	guint num_photos_remaining;
 	glong bytes_used;
@@ -228,9 +228,9 @@ gdata_picasaweb_album_class_init (GDataPicasaWebAlbumClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_EDITED,
-	                                 g_param_spec_boxed ("edited",
+	                                 g_param_spec_int64 ("edited",
 	                                                     "Edited", "The time this album was last edited.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -268,7 +268,7 @@ gdata_picasaweb_album_class_init (GDataPicasaWebAlbumClass *klass)
 	/**
 	 * GDataPicasaWebAlbum:timestamp
 	 *
-	 * The timestamp of when the album occurred, settable by the user.
+	 * The timestamp of when the album occurred, settable by the user. This a UNIX timestamp in milliseconds (not seconds) since the epoch.
 	 *
 	 * For more information, see the <ulink type="http" url="http://code.google.com/apis/picasaweb/reference.html#gphoto_timestamp";>
 	 * gphoto specification</ulink>.
@@ -276,9 +276,9 @@ gdata_picasaweb_album_class_init (GDataPicasaWebAlbumClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_TIMESTAMP,
-	                                 g_param_spec_boxed ("timestamp",
+	                                 g_param_spec_int64 ("timestamp",
 	                                                     "Timestamp", "The timestamp of when the album occurred, settable by the user.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/* TODO: Change to photo-count? */
@@ -478,6 +478,8 @@ gdata_picasaweb_album_init (GDataPicasaWebAlbum *self)
 	self->priv->media_group = g_object_new (GDATA_TYPE_MEDIA_GROUP, NULL);
 	self->priv->georss_where = g_object_new (GDATA_TYPE_GEORSS_WHERE, NULL);
 	self->priv->visibility = GDATA_PICASAWEB_PRIVATE;
+	self->priv->edited = -1;
+	self->priv->timestamp = -1;
 
 	/* Connect to the notify::title signal from GDataEntry so our media:group title can be kept in sync
 	 * (the title of an album is duplicated in atom:title and media:group/media:title) */
@@ -501,11 +503,13 @@ gdata_picasaweb_album_constructor (GType type, guint n_construct_params, GObject
 
 	if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
 		GDataPicasaWebAlbumPrivate *priv = GDATA_PICASAWEB_ALBUM (object)->priv;
+		GTimeVal time_val;
 
 		/* Set the edited and timestamp properties to the current time (creation time). bgo#599140
 		 * We don't do this in *_init() since that would cause setting it from parse_xml() to fail (duplicate element). */
-		g_get_current_time (&(priv->timestamp));
-		g_get_current_time (&(priv->edited));
+		g_get_current_time (&time_val);
+		priv->timestamp = time_val.tv_sec * 1000;
+		priv->edited = time_val.tv_sec;
 	}
 
 	return object;
@@ -558,7 +562,7 @@ gdata_picasaweb_album_get_property (GObject *object, guint property_id, GValue *
 			g_value_set_string (value, priv->nickname);
 			break;
 		case PROP_EDITED:
-			g_value_set_boxed (value, &(priv->edited));
+			g_value_set_int64 (value, priv->edited);
 			break;
 		case PROP_LOCATION:
 			g_value_set_string (value, priv->location);
@@ -567,7 +571,7 @@ gdata_picasaweb_album_get_property (GObject *object, guint property_id, GValue *
 			g_value_set_enum (value, priv->visibility);
 			break;
 		case PROP_TIMESTAMP:
-			g_value_set_boxed (value, &(priv->timestamp));
+			g_value_set_int64 (value, priv->timestamp);
 			break;
 		case PROP_NUM_PHOTOS:
 			g_value_set_uint (value, priv->num_photos);
@@ -618,7 +622,7 @@ gdata_picasaweb_album_set_property (GObject *object, guint property_id, const GV
 			gdata_picasaweb_album_set_visibility (self, g_value_get_enum (value));
 			break;
 		case PROP_TIMESTAMP:
-			gdata_picasaweb_album_set_timestamp (self, g_value_get_boxed (value));
+			gdata_picasaweb_album_set_timestamp (self, g_value_get_int64 (value));
 			break;
 		case PROP_IS_COMMENTING_ENABLED:
 			gdata_picasaweb_album_set_is_commenting_enabled (self, g_value_get_boolean (value));
@@ -650,7 +654,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	/* TODO: media:group should also be P_NO_DUPES, but we can't, as priv->media_group has to be pre-populated
 	 * in order for things like gdata_picasaweb_album_get_tags() to work. */
 	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
-	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+	    gdata_parser_int64_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
 	} else if (gdata_parser_is_namespace (node, "http://search.yahoo.com/mrss/";) == TRUE &&
 	           gdata_parser_object_from_element (node, "group", P_REQUIRED, GDATA_TYPE_MEDIA_GROUP,
@@ -684,16 +688,12 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 			/* gphoto:timestamp */
 			xmlChar *timestamp_str;
 			guint64 milliseconds;
-			GTimeVal timestamp;
 
 			timestamp_str = xmlNodeListGetString (doc, node->children, TRUE);
 			milliseconds = g_ascii_strtoull ((gchar*) timestamp_str, NULL, 10);
 			xmlFree (timestamp_str);
 
-			timestamp.tv_sec = (glong) (milliseconds / 1000);
-			timestamp.tv_usec = (glong) ((milliseconds % 1000) * 1000);
-
-			gdata_picasaweb_album_set_timestamp (self, &timestamp);
+			gdata_picasaweb_album_set_timestamp (self, (gint64) milliseconds);
 		} else if (xmlStrcmp (node->name, (xmlChar*) "numphotos") == 0) {
 			/* gphoto:numphotos */
 			xmlChar *num_photos = xmlNodeListGetString (doc, node->children, TRUE);
@@ -781,10 +781,9 @@ get_xml (GDataParsable *parsable, GString *xml_string)
 			g_assert_not_reached ();
 	}
 
-	if (priv->timestamp.tv_sec != 0 || priv->timestamp.tv_usec != 0) {
+	if (priv->timestamp != -1) {
 		/* in milliseconds */
-		g_string_append_printf (xml_string, "<gphoto:timestamp>%" G_GUINT64_FORMAT "</gphoto:timestamp>",
-		                        ((guint64) priv->timestamp.tv_sec) * 1000 + priv->timestamp.tv_usec / 1000);
+		g_string_append_printf (xml_string, "<gphoto:timestamp>%" G_GINT64_FORMAT "</gphoto:timestamp>", priv->timestamp);
 	}
 
 	if (priv->is_commenting_enabled == FALSE)
@@ -914,19 +913,18 @@ gdata_picasaweb_album_get_nickname (GDataPicasaWebAlbum *self)
 /**
  * gdata_picasaweb_album_get_edited:
  * @self: a #GDataPicasaWebAlbum
- * @edited: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataPicasaWebAlbum:edited property and puts it in @edited. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataPicasaWebAlbum:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the album was last edited, or <code class="literal">-1</code>
  *
  * Since: 0.4.0
  **/
-void
-gdata_picasaweb_album_get_edited (GDataPicasaWebAlbum *self, GTimeVal *edited)
+gint64
+gdata_picasaweb_album_get_edited (GDataPicasaWebAlbum *self)
 {
-	g_return_if_fail (GDATA_IS_PICASAWEB_ALBUM (self));
-	g_return_if_fail (edited != NULL);
-	*edited = self->priv->edited;
+	g_return_val_if_fail (GDATA_IS_PICASAWEB_ALBUM (self), -1);
+	return self->priv->edited;
 }
 
 /**
@@ -1005,43 +1003,40 @@ gdata_picasaweb_album_set_visibility (GDataPicasaWebAlbum *self, GDataPicasaWebV
 /**
  * gdata_picasaweb_album_get_timestamp:
  * @self: a #GDataPicasaWebAlbum
- * @timestamp: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataPicasaWebAlbum:timestamp property and puts it in
- * @timestamp. This value usually holds either the date that best
- * corresponds to the album of photos, or to the day it was uploaded.
- * If the property is unset, both fields in the #GTimeVal will be set
- * to <code class="literal">0</code>.
+ * Gets the #GDataPicasaWebAlbum:timestamp property. This value usually holds either the date that best corresponds to the album of photos, or to the
+ * day it was uploaded. It's a UNIX timestamp in milliseconds (not seconds) since the epoch. If the property is unset, <code class="literal">-1</code>
+ * will be returned.
+ *
+ * Return value: the UNIX timestamp for the timestamp property in milliseconds, or <code class="literal">-1</code>
  *
  * Since: 0.4.0
  **/
-void
-gdata_picasaweb_album_get_timestamp (GDataPicasaWebAlbum *self, GTimeVal *timestamp)
+gint64
+gdata_picasaweb_album_get_timestamp (GDataPicasaWebAlbum *self)
 {
-	g_return_if_fail (GDATA_IS_PICASAWEB_ALBUM (self));
-	g_return_if_fail (timestamp != NULL);
-	*timestamp = self->priv->timestamp;
+	g_return_val_if_fail (GDATA_IS_PICASAWEB_ALBUM (self), -1);
+	return self->priv->timestamp;
 }
 
 /**
  * gdata_picasaweb_album_set_timestamp:
  * @self: a #GDataPicasaWebAlbum
- * @timestamp: (allow-none): a #GTimeVal, or %NULL
+ * @timestamp: a UNIX timestamp, or <code class="literal">-1</code>
  *
- * Sets the #GDataPicasaWebAlbum:timestamp property from values supplied by @timestamp.
+ * Sets the #GDataPicasaWebAlbum:timestamp property from @timestamp. This should be a UNIX timestamp in milliseconds (not seconds) since the epoch.
  *
- * Set @timestamp to %NULL to unset the property.
+ * Set @timestamp to <code class="literal">-1</code> to unset the property.
  *
  * Since: 0.4.0
  **/
 void
-gdata_picasaweb_album_set_timestamp (GDataPicasaWebAlbum *self, const GTimeVal *timestamp)
+gdata_picasaweb_album_set_timestamp (GDataPicasaWebAlbum *self, gint64 timestamp)
 {
 	g_return_if_fail (GDATA_IS_PICASAWEB_ALBUM (self));
-	if (timestamp == NULL)
-		self->priv->timestamp.tv_sec = self->priv->timestamp.tv_usec = 0;
-	else
-		self->priv->timestamp = *timestamp;
+	g_return_if_fail (timestamp >= -1);
+
+	self->priv->timestamp = timestamp;
 	g_object_notify (G_OBJECT (self), "timestamp");
 }
 
diff --git a/gdata/services/picasaweb/gdata-picasaweb-album.h b/gdata/services/picasaweb/gdata-picasaweb-album.h
index 1cec2d2..5075e11 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-album.h
+++ b/gdata/services/picasaweb/gdata-picasaweb-album.h
@@ -83,13 +83,13 @@ GDataPicasaWebAlbum *gdata_picasaweb_album_new (const gchar *id) G_GNUC_WARN_UNU
 const gchar *gdata_picasaweb_album_get_id (GDataPicasaWebAlbum *self) G_GNUC_PURE;
 const gchar *gdata_picasaweb_album_get_user (GDataPicasaWebAlbum *self) G_GNUC_PURE;
 const gchar *gdata_picasaweb_album_get_nickname (GDataPicasaWebAlbum *self) G_GNUC_PURE;
-void gdata_picasaweb_album_get_edited (GDataPicasaWebAlbum *self, GTimeVal *edited);
+gint64 gdata_picasaweb_album_get_edited (GDataPicasaWebAlbum *self);
 const gchar *gdata_picasaweb_album_get_location (GDataPicasaWebAlbum *self) G_GNUC_PURE;
 void gdata_picasaweb_album_set_location (GDataPicasaWebAlbum *self, const gchar *location);
 GDataPicasaWebVisibility gdata_picasaweb_album_get_visibility (GDataPicasaWebAlbum *self) G_GNUC_PURE;
 void gdata_picasaweb_album_set_visibility (GDataPicasaWebAlbum *self, GDataPicasaWebVisibility visibility);
-void gdata_picasaweb_album_get_timestamp (GDataPicasaWebAlbum *self, GTimeVal *timestamp);
-void gdata_picasaweb_album_set_timestamp (GDataPicasaWebAlbum *self, const GTimeVal *timestamp);
+gint64 gdata_picasaweb_album_get_timestamp (GDataPicasaWebAlbum *self);
+void gdata_picasaweb_album_set_timestamp (GDataPicasaWebAlbum *self, gint64 timestamp);
 guint gdata_picasaweb_album_get_num_photos (GDataPicasaWebAlbum *self) G_GNUC_PURE;
 guint gdata_picasaweb_album_get_num_photos_remaining (GDataPicasaWebAlbum *self) G_GNUC_PURE;
 glong gdata_picasaweb_album_get_bytes_used (GDataPicasaWebAlbum *self) G_GNUC_PURE;
diff --git a/gdata/services/picasaweb/gdata-picasaweb-file.c b/gdata/services/picasaweb/gdata-picasaweb-file.c
index 356ff9e..c3a9a3b 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-file.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-file.c
@@ -43,7 +43,7 @@
  *		GDataPicasaWebFile *photo;
  *		guint height, width;
  *		gsize file_size;
- *		GTimeVal timestamp;
+ *		gint64 timestamp;
  *		const gchar *title, *summary;
  *		GList *contents;
  *
@@ -53,7 +53,7 @@
  *		height = gdata_picasaweb_file_get_height (photo);
  *		width = gdata_picasaweb_file_get_width (photo);
  *		file_size = gdata_picasaweb_file_get_size (photo);
- *		gdata_picasaweb_file_get_timestamp (photo, &timestamp);
+ *		timestamp = gdata_picasaweb_file_get_timestamp (photo);
  *		title = gdata_entry_get_title (GDATA_ENTRY (photo));
  *		summary = gdata_entry_get_summary (GDATA_ENTRY (photo));
  *
@@ -107,7 +107,7 @@ static gchar *get_entry_uri (const gchar *id) G_GNUC_WARN_UNUSED_RESULT;
 
 struct _GDataPicasaWebFilePrivate {
 	gchar *file_id;
-	GTimeVal edited;
+	gint64 edited;
 	gchar *version;
 	gdouble position;
 	gchar *album_id;
@@ -116,7 +116,7 @@ struct _GDataPicasaWebFilePrivate {
 	gsize size;
 	gchar *client;
 	gchar *checksum;
-	GTimeVal timestamp;
+	gint64 timestamp; /* in milliseconds! */
 	gboolean is_commenting_enabled;
 	guint comment_count;
 	guint rotation;
@@ -360,15 +360,15 @@ gdata_picasaweb_file_class_init (GDataPicasaWebFileClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_EDITED,
-	                                 g_param_spec_boxed ("edited",
+	                                 g_param_spec_int64 ("edited",
 	                                                     "Edited", "The time this file was last edited.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * GDataPicasaWebFile:timestamp:
 	 *
-	 * The time the file was purportedly taken.
+	 * The time the file was purportedly taken. This a UNIX timestamp in milliseconds (not seconds) since the epoch.
 	 *
 	 * For more information, see the <ulink type="http" url="http://code.google.com/apis/picasaweb/reference.html#gphoto_timestamp";>
 	 * gphoto specification</ulink>.
@@ -376,9 +376,9 @@ gdata_picasaweb_file_class_init (GDataPicasaWebFileClass *klass)
 	 * Since: 0.4.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_TIMESTAMP,
-	                                 g_param_spec_boxed ("timestamp",
+	                                 g_param_spec_int64 ("timestamp",
 	                                                     "Timestamp", "The time the file was purportedly taken.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -676,6 +676,8 @@ gdata_picasaweb_file_init (GDataPicasaWebFile *self)
 	self->priv->exif_tags = g_object_new (GDATA_TYPE_EXIF_TAGS, NULL);
 	self->priv->georss_where = g_object_new (GDATA_TYPE_GEORSS_WHERE, NULL);
 	self->priv->is_commenting_enabled = TRUE;
+	self->priv->edited = -1;
+	self->priv->timestamp = -1;
 
 	/* We need to keep atom:title (the canonical title for the file) in sync with media:group/media:title */
 	g_signal_connect (self, "notify::title", G_CALLBACK (notify_title_cb), NULL);
@@ -693,11 +695,13 @@ gdata_picasaweb_file_constructor (GType type, guint n_construct_params, GObjectC
 
 	if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
 		GDataPicasaWebFilePrivate *priv = GDATA_PICASAWEB_FILE (object)->priv;
+		GTimeVal time_val;
 
 		/* Set the edited and timestamp properties to the current time (creation time). bgo#599140
 		 * We don't do this in *_init() since that would cause setting it from parse_xml() to fail (duplicate element). */
-		g_get_current_time (&(priv->timestamp));
-		g_get_current_time (&(priv->edited));
+		g_get_current_time (&time_val);
+		priv->timestamp = time_val.tv_sec * 1000;
+		priv->edited = time_val.tv_sec;
 	}
 
 	return object;
@@ -750,7 +754,7 @@ gdata_picasaweb_file_get_property (GObject *object, guint property_id, GValue *v
 			g_value_set_string (value, priv->file_id);
 			break;
 		case PROP_EDITED:
-			g_value_set_boxed (value, &(priv->edited));
+			g_value_set_int64 (value, priv->edited);
 			break;
 		case PROP_VERSION:
 			g_value_set_string (value, priv->version);
@@ -777,7 +781,7 @@ gdata_picasaweb_file_get_property (GObject *object, guint property_id, GValue *v
 			g_value_set_string (value, priv->checksum);
 			break;
 		case PROP_TIMESTAMP:
-			g_value_set_boxed (value, &(priv->timestamp));
+			g_value_set_int64 (value, priv->timestamp);
 			break;
 		case PROP_IS_COMMENTING_ENABLED:
 			g_value_set_boolean (value, priv->is_commenting_enabled);
@@ -871,7 +875,7 @@ gdata_picasaweb_file_set_property (GObject *object, guint property_id, const GVa
 			gdata_picasaweb_file_set_checksum (self, g_value_get_string (value));
 			break;
 		case PROP_TIMESTAMP:
-			gdata_picasaweb_file_set_timestamp (self, g_value_get_boxed (value));
+			gdata_picasaweb_file_set_timestamp (self, g_value_get_int64 (value));
 			break;
 		case PROP_IS_COMMENTING_ENABLED: /* TODO I don't think we can change this on a per file basis */
 			gdata_picasaweb_file_set_is_commenting_enabled (self, g_value_get_boolean (value));
@@ -909,7 +913,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	/* TODO: media:group should also be P_NO_DUPES, but we can't, as priv->media_group has to be pre-populated
 	 * in order for things like gdata_picasaweb_file_set_description() to work. */
 	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
-	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+	    gdata_parser_int64_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
 	} else if (gdata_parser_is_namespace (node, "http://search.yahoo.com/mrss/";) == TRUE &&
 	           gdata_parser_object_from_element (node, "group", P_REQUIRED, GDATA_TYPE_MEDIA_GROUP,
@@ -956,16 +960,12 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 			/* gphoto:timestamp */
 			xmlChar *timestamp_str;
 			guint64 milliseconds;
-			GTimeVal timestamp;
 
 			timestamp_str = xmlNodeListGetString (doc, node->children, TRUE);
 			milliseconds = g_ascii_strtoull ((gchar*) timestamp_str, NULL, 10);
 			xmlFree (timestamp_str);
 
-			timestamp.tv_sec = (glong) (milliseconds / 1000);
-			timestamp.tv_usec = (glong) ((milliseconds % 1000) * 1000);
-
-			gdata_picasaweb_file_set_timestamp (self, &timestamp);
+			gdata_picasaweb_file_set_timestamp (self, (gint64) milliseconds);
 		} else if (xmlStrcmp (node->name, (xmlChar*) "commentingEnabled") == 0) {
 			/* gphoto:commentingEnabled */
 			xmlChar *is_commenting_enabled = xmlNodeListGetString (doc, node->children, TRUE);
@@ -1026,10 +1026,9 @@ get_xml (GDataParsable *parsable, GString *xml_string)
 	if (priv->checksum != NULL)
 		gdata_parser_string_append_escaped (xml_string, "<gphoto:checksum>", priv->checksum, "</gphoto:checksum>");
 
-	if (priv->timestamp.tv_sec != 0 || priv->timestamp.tv_usec != 0) {
+	if (priv->timestamp != -1) {
 		/* timestamp is in milliseconds */
-		g_string_append_printf (xml_string, "<gphoto:timestamp>%" G_GUINT64_FORMAT "</gphoto:timestamp>",
-		                        ((guint64) priv->timestamp.tv_sec) * 1000 + priv->timestamp.tv_usec / 1000);
+		g_string_append_printf (xml_string, "<gphoto:timestamp>%" G_GINT64_FORMAT "</gphoto:timestamp>", priv->timestamp);
 	}
 
 	if (priv->is_commenting_enabled == TRUE)
@@ -1141,19 +1140,18 @@ gdata_picasaweb_file_get_id (GDataPicasaWebFile *self)
 /**
  * gdata_picasaweb_file_get_edited:
  * @self: a #GDataPicasaWebFile
- * @edited: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataPicasaWebFile:edited property and puts it in @edited. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataPicasaWebFile:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the file was last edited, or <code class="literal">-1</code>
  *
  * Since: 0.4.0
  **/
-void
-gdata_picasaweb_file_get_edited (GDataPicasaWebFile *self, GTimeVal *edited)
+gint64
+gdata_picasaweb_file_get_edited (GDataPicasaWebFile *self)
 {
-	g_return_if_fail (GDATA_IS_PICASAWEB_FILE (self));
-	g_return_if_fail (edited != NULL);
-	*edited = self->priv->edited;
+	g_return_val_if_fail (GDATA_IS_PICASAWEB_FILE (self), -1);
+	return self->priv->edited;
 }
 
 /**
@@ -1374,33 +1372,33 @@ gdata_picasaweb_file_set_checksum (GDataPicasaWebFile *self, const gchar *checks
 /**
  * gdata_picasaweb_file_get_timestamp:
  * @self: a #GDataPicasaWebFile
- * @timestamp: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataPicasaWebFile:timestamp property and puts it in @timestamp. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataPicasaWebFile:timestamp property. It's a UNIX timestamp in milliseconds (not seconds) since the epoch. If the property is unset,
+ * <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the timestamp property in milliseconds, or <code class="literal">-1</code>
  *
  * Since: 0.4.0
  **/
-void
-gdata_picasaweb_file_get_timestamp (GDataPicasaWebFile *self, GTimeVal *timestamp)
+gint64
+gdata_picasaweb_file_get_timestamp (GDataPicasaWebFile *self)
 {
-	g_return_if_fail (GDATA_IS_PICASAWEB_FILE (self));
-	g_return_if_fail (timestamp != NULL);
-	*timestamp = self->priv->timestamp;
+	g_return_val_if_fail (GDATA_IS_PICASAWEB_FILE (self), -1);
+	return self->priv->timestamp;
 }
 
 /**
  * gdata_picasaweb_file_set_timestamp:
  * @self: a #GDataPicasaWebFile
- * @timestamp: (allow-none): a #GTimeVal, or %NULL
+ * @timestamp: a UNIX timestamp, or <code class="literal">-1</code>
  *
- * Sets the #GDataPicasaWebFile:timestamp property from values supplied by @timestamp. If @timestamp is %NULL,
- * the property will be unset.
+ * Sets the #GDataPicasaWebFile:timestamp property from @timestamp. This should be a UNIX timestamp in milliseconds (not seconds) since the epoch. If
+ * @timestamp is <code class="literal">-1</code>, the property will be unset.
  *
  * Since: 0.4.0
  **/
 void
-gdata_picasaweb_file_set_timestamp (GDataPicasaWebFile *self, const GTimeVal *timestamp)
+gdata_picasaweb_file_set_timestamp (GDataPicasaWebFile *self, gint64 timestamp)
 {
 	/* RHSTODO: I think the timestamp value is just being
 	   over-ridden by the file's actual EXIF time value; unless
@@ -1408,10 +1406,9 @@ gdata_picasaweb_file_set_timestamp (GDataPicasaWebFile *self, const GTimeVal *ti
 	/* RHSTODO: improve testing of setters in tests/picasa.c */
 
 	g_return_if_fail (GDATA_IS_PICASAWEB_FILE (self));
-	if (timestamp == NULL)
-		self->priv->timestamp.tv_sec = self->priv->timestamp.tv_usec = 0;
-	else
-		self->priv->timestamp = *timestamp;
+	g_return_if_fail (timestamp >= -1);
+
+	self->priv->timestamp = timestamp;
 	g_object_notify (G_OBJECT (self), "timestamp");
 }
 
diff --git a/gdata/services/picasaweb/gdata-picasaweb-file.h b/gdata/services/picasaweb/gdata-picasaweb-file.h
index ae23789..764b219 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-file.h
+++ b/gdata/services/picasaweb/gdata-picasaweb-file.h
@@ -103,7 +103,7 @@ GType gdata_picasaweb_file_get_type (void) G_GNUC_CONST;
 GDataPicasaWebFile *gdata_picasaweb_file_new (const gchar *id) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 const gchar *gdata_picasaweb_file_get_id (GDataPicasaWebFile *self) G_GNUC_PURE;
-void gdata_picasaweb_file_get_edited (GDataPicasaWebFile *self, GTimeVal *edited);
+gint64 gdata_picasaweb_file_get_edited (GDataPicasaWebFile *self);
 const gchar *gdata_picasaweb_file_get_version (GDataPicasaWebFile *self) G_GNUC_PURE;
 gdouble gdata_picasaweb_file_get_position (GDataPicasaWebFile *self) G_GNUC_PURE;
 void gdata_picasaweb_file_set_position (GDataPicasaWebFile *self, gdouble position);
@@ -117,8 +117,8 @@ const gchar *gdata_picasaweb_file_get_client (GDataPicasaWebFile *self) G_GNUC_P
 void gdata_picasaweb_file_set_client (GDataPicasaWebFile *self, const gchar *client);
 const gchar *gdata_picasaweb_file_get_checksum (GDataPicasaWebFile *self) G_GNUC_PURE;
 void gdata_picasaweb_file_set_checksum (GDataPicasaWebFile *self, const gchar *checksum);
-void gdata_picasaweb_file_get_timestamp (GDataPicasaWebFile *self, GTimeVal *timestamp);
-void gdata_picasaweb_file_set_timestamp (GDataPicasaWebFile *self, const GTimeVal *timestamp);
+gint64 gdata_picasaweb_file_get_timestamp (GDataPicasaWebFile *self);
+void gdata_picasaweb_file_set_timestamp (GDataPicasaWebFile *self, gint64 timestamp);
 gboolean gdata_picasaweb_file_is_commenting_enabled (GDataPicasaWebFile *self) G_GNUC_PURE;
 void gdata_picasaweb_file_set_is_commenting_enabled (GDataPicasaWebFile *self, gboolean is_commenting_enabled);
 guint gdata_picasaweb_file_get_comment_count (GDataPicasaWebFile *self) G_GNUC_PURE;
diff --git a/gdata/services/youtube/gdata-youtube-group.c b/gdata/services/youtube/gdata-youtube-group.c
index 59868c6..d2a291a 100644
--- a/gdata/services/youtube/gdata-youtube-group.c
+++ b/gdata/services/youtube/gdata-youtube-group.c
@@ -47,7 +47,7 @@ static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
 struct _GDataYouTubeGroupPrivate {
 	guint duration;
 	gboolean is_private;
-	GTimeVal uploaded;
+	gint64 uploaded;
 	gchar *video_id;
 	gchar *aspect_ratio;
 };
@@ -73,6 +73,7 @@ static void
 gdata_youtube_group_init (GDataYouTubeGroup *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_YOUTUBE_GROUP, GDataYouTubeGroupPrivate);
+	self->priv->uploaded = -1;
 }
 
 static void
@@ -102,8 +103,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		if (gdata_parser_string_from_element (node, "videoid", P_NO_DUPES, &(self->priv->video_id), &success, error) == TRUE ||
 		    gdata_parser_string_from_element (node, "aspectRatio", P_REQUIRED | P_NO_DUPES,
 		                                      &(self->priv->aspect_ratio), &success, error) == TRUE ||
-		    gdata_parser_time_val_from_element (node, "uploaded", P_REQUIRED | P_NO_DUPES,
-		                                        &(self->priv->uploaded), &success, error) == TRUE) {
+		    gdata_parser_int64_from_element (node, "uploaded", P_REQUIRED | P_NO_DUPES,
+		                                     &(self->priv->uploaded), &success, error) == TRUE) {
 			return success;
 		} else if (xmlStrcmp (node->name, (xmlChar*) "duration") == 0) {
 			/* yt:duration */
@@ -194,17 +195,16 @@ gdata_youtube_group_set_is_private (GDataYouTubeGroup *self, gboolean is_private
 /**
  * gdata_youtube_group_get_uploaded:
  * @self: a #GDataYouTubeGroup
- * @uploaded: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataYouTubeGroup:uploaded property and puts it in @uploaded. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataYouTubeGroup:uploaded property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the group was uploaded, or <code class="literal">-1</code>
  **/
-void
-gdata_youtube_group_get_uploaded (GDataYouTubeGroup *self, GTimeVal *uploaded)
+gint64
+gdata_youtube_group_get_uploaded (GDataYouTubeGroup *self)
 {
-	g_return_if_fail (GDATA_IS_YOUTUBE_GROUP (self));
-	g_return_if_fail (uploaded != NULL);
-	*uploaded = self->priv->uploaded;
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_GROUP (self), -1);
+	return self->priv->uploaded;
 }
 
 /**
diff --git a/gdata/services/youtube/gdata-youtube-group.h b/gdata/services/youtube/gdata-youtube-group.h
index 828b252..99c8583 100644
--- a/gdata/services/youtube/gdata-youtube-group.h
+++ b/gdata/services/youtube/gdata-youtube-group.h
@@ -65,7 +65,7 @@ GType gdata_youtube_group_get_type (void) G_GNUC_CONST;
 guint gdata_youtube_group_get_duration (GDataYouTubeGroup *self) G_GNUC_PURE;
 gboolean gdata_youtube_group_is_private (GDataYouTubeGroup *self) G_GNUC_PURE;
 void gdata_youtube_group_set_is_private (GDataYouTubeGroup *self, gboolean is_private);
-void gdata_youtube_group_get_uploaded (GDataYouTubeGroup *self, GTimeVal *uploaded);
+gint64 gdata_youtube_group_get_uploaded (GDataYouTubeGroup *self);
 const gchar *gdata_youtube_group_get_video_id (GDataYouTubeGroup *self) G_GNUC_PURE;
 const gchar *gdata_youtube_group_get_aspect_ratio (GDataYouTubeGroup *self) G_GNUC_PURE;
 void gdata_youtube_group_set_aspect_ratio (GDataYouTubeGroup *self, const gchar *aspect_ratio);
diff --git a/gdata/services/youtube/gdata-youtube-video.c b/gdata/services/youtube/gdata-youtube-video.c
index 75a9721..d3cb1a3 100644
--- a/gdata/services/youtube/gdata-youtube-video.c
+++ b/gdata/services/youtube/gdata-youtube-video.c
@@ -33,7 +33,7 @@
  * 	<programlisting>
  * 	GDataYouTubeVideo *video;
  * 	const gchar *video_id, *title, *player_uri, *description, *video_uri = NULL;
- * 	GTimeVal updated, published;
+ * 	gint64 updated, published;
  * 	GDataMediaContent *content;
  * 	GList *thumbnails;
  *
@@ -43,8 +43,8 @@
  * 	title = gdata_entry_get_title (GDATA_ENTRY (video)); /<!-- -->* e.g. "Korpiklaani Vodka (official video 2009)" *<!-- -->/
  * 	player_uri = gdata_youtube_video_get_player_uri (video); /<!-- -->* e.g. "http://www.youtube.com/watch?v=ZTUVgYoeN_b"; *<!-- -->/
  * 	description = gdata_youtube_video_get_description (video); /<!-- -->* e.g. "Vodka is the first single from the album..." *<!-- -->/
- * 	gdata_entry_get_published (GDATA_ENTRY (video), &published); /<!-- -->* Date and time the video was originally published *<!-- -->/
- * 	gdata_entry_get_updated (GDATA_ENTRY (video), &updated); /<!-- -->* When the video was most recently updated by the author *<!-- -->/
+ * 	published = gdata_entry_get_published (GDATA_ENTRY (video)); /<!-- -->* Date and time the video was originally published *<!-- -->/
+ * 	updated = gdata_entry_get_updated (GDATA_ENTRY (video)); /<!-- -->* When the video was most recently updated by the author *<!-- -->/
  *
  * 	/<!-- -->* Retrieve a specific encoding of the video in GDataMediaContent format *<!-- -->/
  * 	content = gdata_youtube_video_look_up_content (video, "video/3gpp");
@@ -109,7 +109,7 @@ struct _GDataYouTubeVideoPrivate {
 
 	/* Other properties */
 	GDataYouTubeControl *youtube_control;
-	GTimeVal recorded;
+	gint64 recorded;
 };
 
 enum {
@@ -365,9 +365,9 @@ gdata_youtube_video_class_init (GDataYouTubeVideoClass *klass)
 	 * url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:uploaded";>online documentation</ulink>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_UPLOADED,
-	                                 g_param_spec_boxed ("uploaded",
+	                                 g_param_spec_int64 ("uploaded",
 	                                                     "Uploaded", "Specifies the time the video was originally uploaded to YouTube.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -424,9 +424,9 @@ gdata_youtube_video_class_init (GDataYouTubeVideoClass *klass)
 	 * Since: 0.3.0
 	 **/
 	g_object_class_install_property (gobject_class, PROP_RECORDED,
-	                                 g_param_spec_boxed ("recorded",
+	                                 g_param_spec_int64 ("recorded",
 	                                                     "Recorded", "Specifies the time the video was originally recorded.",
-	                                                     GDATA_TYPE_G_TIME_VAL,
+	                                                     -1, G_MAXINT64, -1,
 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -459,6 +459,7 @@ static void
 gdata_youtube_video_init (GDataYouTubeVideo *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_YOUTUBE_VIDEO, GDataYouTubeVideoPrivate);
+	self->priv->recorded = -1;
 	self->priv->access_controls = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
 
 	/* The video's title is duplicated between atom:title and media:group/media:title, so listen for change notifications on atom:title
@@ -562,11 +563,9 @@ gdata_youtube_video_get_property (GObject *object, guint property_id, GValue *va
 		case PROP_IS_PRIVATE:
 			g_value_set_boolean (value, gdata_youtube_group_is_private (GDATA_YOUTUBE_GROUP (priv->media_group)));
 			break;
-		case PROP_UPLOADED: {
-			GTimeVal uploaded;
-			gdata_youtube_group_get_uploaded (GDATA_YOUTUBE_GROUP (priv->media_group), &uploaded);
-			g_value_set_boxed (value, &(uploaded));
-			break; }
+		case PROP_UPLOADED:
+			g_value_set_int64 (value, gdata_youtube_group_get_uploaded (GDATA_YOUTUBE_GROUP (priv->media_group)));
+			break;
 		case PROP_VIDEO_ID:
 			g_value_set_string (value, gdata_youtube_group_get_video_id (GDATA_YOUTUBE_GROUP (priv->media_group)));
 			break;
@@ -577,7 +576,7 @@ gdata_youtube_video_get_property (GObject *object, guint property_id, GValue *va
 			g_value_set_object (value, gdata_youtube_control_get_state (priv->youtube_control));
 			break;
 		case PROP_RECORDED:
-			g_value_set_boxed (value, &(priv->recorded));
+			g_value_set_int64 (value, priv->recorded);
 			break;
 		case PROP_ASPECT_RATIO:
 			g_value_set_string (value, gdata_youtube_group_get_aspect_ratio (GDATA_YOUTUBE_GROUP (priv->media_group)));
@@ -614,7 +613,7 @@ gdata_youtube_video_set_property (GObject *object, guint property_id, const GVal
 			gdata_youtube_video_set_is_draft (self, g_value_get_boolean (value));
 			break;
 		case PROP_RECORDED:
-			gdata_youtube_video_set_recorded (self, g_value_get_boxed (value));
+			gdata_youtube_video_set_recorded (self, g_value_get_int64 (value));
 			break;
 		case PROP_ASPECT_RATIO:
 			gdata_youtube_video_set_aspect_ratio (self, g_value_get_string (value));
@@ -694,17 +693,17 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		} else if (xmlStrcmp (node->name, (xmlChar*) "recorded") == 0) {
 			/* yt:recorded */
 			xmlChar *recorded;
-			GTimeVal recorded_timeval;
+			gint64 recorded_int64;
 
 			recorded = xmlNodeListGetString (doc, node->children, TRUE);
-			if (gdata_parser_time_val_from_date ((gchar*) recorded, &recorded_timeval) == FALSE) {
+			if (gdata_parser_int64_from_date ((gchar*) recorded, &recorded_int64) == FALSE) {
 				/* Error */
 				gdata_parser_error_not_iso8601_format (node, (gchar*) recorded, error);
 				xmlFree (recorded);
 				return FALSE;
 			}
 			xmlFree (recorded);
-			gdata_youtube_video_set_recorded (self, &recorded_timeval);
+			gdata_youtube_video_set_recorded (self, recorded_int64);
 		} else {
 			return GDATA_PARSABLE_CLASS (gdata_youtube_video_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
@@ -806,8 +805,8 @@ get_xml (GDataParsable *parsable, GString *xml_string)
 	if (priv->location != NULL)
 		gdata_parser_string_append_escaped (xml_string, "<yt:location>", priv->location, "</yt:location>");
 
-	if (priv->recorded.tv_sec != 0 || priv->recorded.tv_usec != 0) {
-		gchar *recorded = gdata_parser_date_from_time_val (&(priv->recorded));
+	if (priv->recorded != -1) {
+		gchar *recorded = gdata_parser_date_from_int64 (priv->recorded);
 		g_string_append_printf (xml_string, "<yt:recorded>%s</yt:recorded>", recorded);
 		g_free (recorded);
 	}
@@ -1250,17 +1249,16 @@ gdata_youtube_video_set_is_private (GDataYouTubeVideo *self, gboolean is_private
 /**
  * gdata_youtube_video_get_uploaded:
  * @self: a #GDataYouTubeVideo
- * @uploaded: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataYouTubeVideo:uploaded property and puts it in @uploaded. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataYouTubeVideo:uploaded property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the video was uploaded, or <code class="literal">-1</code>
  **/
-void
-gdata_youtube_video_get_uploaded (GDataYouTubeVideo *self, GTimeVal *uploaded)
+gint64
+gdata_youtube_video_get_uploaded (GDataYouTubeVideo *self)
 {
-	g_return_if_fail (GDATA_IS_YOUTUBE_VIDEO (self));
-	g_return_if_fail (uploaded != NULL);
-	gdata_youtube_group_get_uploaded (GDATA_YOUTUBE_GROUP (self->priv->media_group), uploaded);
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_VIDEO (self), -1);
+	return gdata_youtube_group_get_uploaded (GDATA_YOUTUBE_GROUP (self->priv->media_group));
 }
 
 /**
@@ -1329,42 +1327,39 @@ gdata_youtube_video_get_state (GDataYouTubeVideo *self)
 /**
  * gdata_youtube_video_get_recorded:
  * @self: a #GDataYouTubeVideo
- * @recorded: (out caller-allocates): a #GTimeVal
  *
- * Gets the #GDataYouTubeVideo:recorded property and puts it in @recorded. If the property is unset,
- * both fields in the #GTimeVal will be set to <code class="literal">0</code>.
+ * Gets the #GDataYouTubeVideo:recorded property. If the property is unset, <code class="literal">-1</code> will be returned.
+ *
+ * Return value: the UNIX timestamp for the time the video was recorded, or <code class="literal">-1</code>
  *
  * Since: 0.3.0
  **/
-void
-gdata_youtube_video_get_recorded (GDataYouTubeVideo *self, GTimeVal *recorded)
+gint64
+gdata_youtube_video_get_recorded (GDataYouTubeVideo *self)
 {
-	g_return_if_fail (GDATA_IS_YOUTUBE_VIDEO (self));
-	g_return_if_fail (recorded != NULL);
-	*recorded = self->priv->recorded;
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_VIDEO (self), -1);
+	return self->priv->recorded;
 }
 
 /**
  * gdata_youtube_video_set_recorded:
  * @self: a #GDataYouTubeVideo
- * @recorded: (allow-none): the video's new recorded time, or %NULL
+ * @recorded: the video's new recorded time, or <code class="literal">-1</code>
  *
  * Sets the #GDataYouTubeVideo:recorded property to the new recorded time, @recorded.
  *
- * Set @recorded to %NULL to unset the video's recorded time.
+ * Set @recorded to <code class="literal">-1</code> to unset the video's recorded time.
  *
  * Since: 0.3.0
  **/
 void
-gdata_youtube_video_set_recorded (GDataYouTubeVideo *self, const GTimeVal *recorded)
+gdata_youtube_video_set_recorded (GDataYouTubeVideo *self, gint64 recorded)
 {
 	g_return_if_fail (GDATA_IS_YOUTUBE_VIDEO (self));
-	if (recorded == NULL) {
-		self->priv->recorded.tv_sec = 0;
-		self->priv->recorded.tv_usec = 0;
-	} else {
-		self->priv->recorded = *recorded;
-	}
+	g_return_if_fail (recorded >= -1);
+
+	self->priv->recorded = recorded;
+	g_object_notify (G_OBJECT (self), "recorded");
 }
 
 /**
diff --git a/gdata/services/youtube/gdata-youtube-video.h b/gdata/services/youtube/gdata-youtube-video.h
index 6c87330..cb29a55 100644
--- a/gdata/services/youtube/gdata-youtube-video.h
+++ b/gdata/services/youtube/gdata-youtube-video.h
@@ -170,13 +170,13 @@ GList *gdata_youtube_video_get_thumbnails (GDataYouTubeVideo *self) G_GNUC_PURE;
 guint gdata_youtube_video_get_duration (GDataYouTubeVideo *self) G_GNUC_PURE;
 gboolean gdata_youtube_video_is_private (GDataYouTubeVideo *self) G_GNUC_PURE;
 void gdata_youtube_video_set_is_private (GDataYouTubeVideo *self, gboolean is_private);
-void gdata_youtube_video_get_uploaded (GDataYouTubeVideo *self, GTimeVal *uploaded);
+gint64 gdata_youtube_video_get_uploaded (GDataYouTubeVideo *self);
 const gchar *gdata_youtube_video_get_video_id (GDataYouTubeVideo *self) G_GNUC_PURE;
 gboolean gdata_youtube_video_is_draft (GDataYouTubeVideo *self) G_GNUC_PURE;
 void gdata_youtube_video_set_is_draft (GDataYouTubeVideo *self, gboolean is_draft);
 GDataYouTubeState *gdata_youtube_video_get_state (GDataYouTubeVideo *self) G_GNUC_PURE;
-void gdata_youtube_video_get_recorded (GDataYouTubeVideo *self, GTimeVal *recorded);
-void gdata_youtube_video_set_recorded (GDataYouTubeVideo *self, const GTimeVal *recorded);
+gint64 gdata_youtube_video_get_recorded (GDataYouTubeVideo *self);
+void gdata_youtube_video_set_recorded (GDataYouTubeVideo *self, gint64 recorded);
 const gchar *gdata_youtube_video_get_aspect_ratio (GDataYouTubeVideo *self) G_GNUC_PURE;
 void gdata_youtube_video_set_aspect_ratio (GDataYouTubeVideo *self, const gchar *aspect_ratio);
 
diff --git a/gdata/tests/calendar.c b/gdata/tests/calendar.c
index dc4f9c1..d3cf72a 100644
--- a/gdata/tests/calendar.c
+++ b/gdata/tests/calendar.c
@@ -249,7 +249,7 @@ test_insert_simple (gconstpointer service)
 	g_object_unref (who);
 	g_time_val_from_iso8601 ("2009-04-17T15:00:00.000Z", &start_time);
 	g_time_val_from_iso8601 ("2009-04-17T17:00:00.000Z", &end_time);
-	when = gdata_gd_when_new (&start_time, &end_time, FALSE);
+	when = gdata_gd_when_new (start_time.tv_sec, end_time.tv_sec, FALSE);
 	gdata_calendar_event_add_time (event, when);
 	g_object_unref (when);
 
@@ -296,7 +296,7 @@ test_xml_dates (void)
 	GDataCalendarEvent *event;
 	GList *times, *i;
 	GDataGDWhen *when;
-	GTimeVal time_val;
+	gint64 _time;
 	gchar *xml;
 	GError *error = NULL;
 
@@ -323,12 +323,10 @@ test_xml_dates (void)
 	when = GDATA_GD_WHEN (i->data);
 	g_assert (i->next != NULL);
 	g_assert (gdata_gd_when_is_date (when) == TRUE);
-	gdata_gd_when_get_start_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 1239926400);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
-	gdata_gd_when_get_end_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 0);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
+	_time = gdata_gd_when_get_start_time (when);
+	g_assert_cmpint (_time, ==, 1239926400);
+	_time = gdata_gd_when_get_end_time (when);
+	g_assert_cmpint (_time, ==, -1);
 	g_assert (gdata_gd_when_get_value_string (when) == NULL);
 	g_assert (gdata_gd_when_get_reminders (when) == NULL);
 
@@ -337,12 +335,10 @@ test_xml_dates (void)
 	when = GDATA_GD_WHEN (i->data);
 	g_assert (i->next != NULL);
 	g_assert (gdata_gd_when_is_date (when) == FALSE);
-	gdata_gd_when_get_start_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 1239926400 + 54000);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
-	gdata_gd_when_get_end_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 0);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
+	_time = gdata_gd_when_get_start_time (when);
+	g_assert_cmpint (_time, ==, 1239926400 + 54000);
+	_time = gdata_gd_when_get_end_time (when);
+	g_assert_cmpint (_time, ==, -1);
 	g_assert (gdata_gd_when_get_value_string (when) == NULL);
 	g_assert (gdata_gd_when_get_reminders (when) == NULL);
 
@@ -351,12 +347,10 @@ test_xml_dates (void)
 	when = GDATA_GD_WHEN (i->data);
 	g_assert (i->next == NULL);
 	g_assert (gdata_gd_when_is_date (when) == TRUE);
-	gdata_gd_when_get_start_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 1239926400 + 864000);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
-	gdata_gd_when_get_end_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 1241568000);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
+	_time = gdata_gd_when_get_start_time (when);
+	g_assert_cmpint (_time, ==, 1239926400 + 864000);
+	_time = gdata_gd_when_get_end_time (when);
+	g_assert_cmpint (_time, ==, 1241568000);
 	g_assert (gdata_gd_when_get_value_string (when) == NULL);
 	g_assert (gdata_gd_when_get_reminders (when) == NULL);
 
@@ -449,7 +443,8 @@ test_xml_recurrence (void)
 static void
 test_query_uri (void)
 {
-	GTimeVal time_val, time_val2;
+	gint64 _time;
+	GTimeVal time_val;
 	gchar *query_uri;
 	GDataCalendarQuery *query = gdata_calendar_query_new ("q");
 
@@ -460,16 +455,14 @@ test_query_uri (void)
 	g_assert_cmpstr (gdata_calendar_query_get_order_by (query), ==, "starttime");
 
 	g_time_val_from_iso8601 ("2009-04-17T15:00:00.000Z", &time_val);
-	gdata_calendar_query_set_recurrence_expansion_start (query, &time_val);
-	gdata_calendar_query_get_recurrence_expansion_start (query, &time_val2);
-	g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
-	g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+	gdata_calendar_query_set_recurrence_expansion_start (query, time_val.tv_sec);
+	_time = gdata_calendar_query_get_recurrence_expansion_start (query);
+	g_assert_cmpint (_time, ==, time_val.tv_sec);
 
 	g_time_val_from_iso8601 ("2010-04-17T15:00:00.000Z", &time_val);
-	gdata_calendar_query_set_recurrence_expansion_end (query, &time_val);
-	gdata_calendar_query_get_recurrence_expansion_end (query, &time_val2);
-	g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
-	g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+	gdata_calendar_query_set_recurrence_expansion_end (query, time_val.tv_sec);
+	_time = gdata_calendar_query_get_recurrence_expansion_end (query);
+	g_assert_cmpint (_time, ==, time_val.tv_sec);
 
 	gdata_calendar_query_set_single_events (query, TRUE);
 	g_assert (gdata_calendar_query_get_single_events (query) == TRUE);
@@ -478,16 +471,14 @@ test_query_uri (void)
 	g_assert_cmpstr (gdata_calendar_query_get_sort_order (query), ==, "descending");
 
 	g_time_val_from_iso8601 ("2009-04-17T15:00:00.000Z", &time_val);
-	gdata_calendar_query_set_start_min (query, &time_val);
-	gdata_calendar_query_get_start_min (query, &time_val2);
-	g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
-	g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+	gdata_calendar_query_set_start_min (query, time_val.tv_sec);
+	_time = gdata_calendar_query_get_start_min (query);
+	g_assert_cmpint (_time, ==, time_val.tv_sec);
 
 	g_time_val_from_iso8601 ("2010-04-17T15:00:00.000Z", &time_val);
-	gdata_calendar_query_set_start_max (query, &time_val);
-	gdata_calendar_query_get_start_max (query, &time_val2);
-	g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
-	g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+	gdata_calendar_query_set_start_max (query, time_val.tv_sec);
+	_time = gdata_calendar_query_get_start_max (query);
+	g_assert_cmpint (_time, ==, time_val.tv_sec);
 
 	gdata_calendar_query_set_timezone (query, "America/Los Angeles");
 	g_assert_cmpstr (gdata_calendar_query_get_timezone (query), ==, "America/Los_Angeles");
@@ -532,12 +523,12 @@ test_query_etag (void)
 
 	CHECK_ETAG (gdata_calendar_query_set_future_events (query, FALSE))
 	CHECK_ETAG (gdata_calendar_query_set_order_by (query, "shizzle"))
-	CHECK_ETAG (gdata_calendar_query_set_recurrence_expansion_start (query, NULL))
-	CHECK_ETAG (gdata_calendar_query_set_recurrence_expansion_end (query, NULL))
+	CHECK_ETAG (gdata_calendar_query_set_recurrence_expansion_start (query, -1))
+	CHECK_ETAG (gdata_calendar_query_set_recurrence_expansion_end (query, -1))
 	CHECK_ETAG (gdata_calendar_query_set_single_events (query, FALSE))
 	CHECK_ETAG (gdata_calendar_query_set_sort_order (query, "shizzle"))
-	CHECK_ETAG (gdata_calendar_query_set_start_min (query, NULL))
-	CHECK_ETAG (gdata_calendar_query_set_start_max (query, NULL))
+	CHECK_ETAG (gdata_calendar_query_set_start_min (query, -1))
+	CHECK_ETAG (gdata_calendar_query_set_start_max (query, -1))
 	CHECK_ETAG (gdata_calendar_query_set_timezone (query, "about now"))
 
 #undef CHECK_ETAG
@@ -575,7 +566,7 @@ test_acls_insert_rule (gconstpointer service)
 	GDataCategory *category;
 	GList *categories;
 	gchar *xml;
-	GTimeVal edited;
+	gint64 edited;
 	GError *error = NULL;
 
 	calendar = get_calendar (service, &error);
@@ -615,8 +606,8 @@ test_acls_insert_rule (gconstpointer service)
 	gdata_access_rule_get_scope (new_rule, &scope_type, &scope_value);
 	g_assert_cmpstr (scope_type, ==, GDATA_ACCESS_SCOPE_USER);
 	g_assert_cmpstr (scope_value, ==, "darcy gmail com");
-	gdata_access_rule_get_edited (new_rule, &edited);
-	g_assert_cmpuint (edited.tv_sec, >, 0);
+	edited = gdata_access_rule_get_edited (new_rule);
+	g_assert_cmpuint (edited, >, 0);
 
 	/* Check it only has the one category and that it's correct */
 	categories = gdata_entry_get_categories (GDATA_ENTRY (new_rule));
@@ -641,7 +632,7 @@ test_acls_update_rule (gconstpointer service)
 	GDataAccessRule *rule = NULL, *new_rule;
 	const gchar *scope_type, *scope_value;
 	GList *rules;
-	GTimeVal edited;
+	gint64 edited;
 	GError *error = NULL;
 
 	calendar = get_calendar (service, &error);
@@ -681,8 +672,8 @@ test_acls_update_rule (gconstpointer service)
 	gdata_access_rule_get_scope (new_rule, &scope_type, &scope_value);
 	g_assert_cmpstr (scope_type, ==, GDATA_ACCESS_SCOPE_USER);
 	g_assert_cmpstr (scope_value, ==, "darcy gmail com");
-	gdata_access_rule_get_edited (new_rule, &edited);
-	g_assert_cmpuint (edited.tv_sec, >, 0);
+	edited = gdata_access_rule_get_edited (new_rule);
+	g_assert_cmpuint (edited, >, 0);
 
 	g_object_unref (new_rule);
 	g_object_unref (calendar);
diff --git a/gdata/tests/contacts.c b/gdata/tests/contacts.c
index 1635260..8b7c21f 100644
--- a/gdata/tests/contacts.c
+++ b/gdata/tests/contacts.c
@@ -167,12 +167,13 @@ test_insert_simple (gconstpointer service)
 	GList *list;
 	GDate date, *date2;
 	GHashTable *properties;
-	GTimeVal *edited, creation_time;
+	GTimeVal current_time;
+	gint64 edited, creation_time;
 	gboolean deleted, has_photo, birthday_has_year;
 	GError *error = NULL;
 
 	contact = gdata_contacts_contact_new (NULL);
-	g_get_current_time (&creation_time);
+	g_get_current_time (&current_time);
 
 	/* Check the kind is present and correct */
 	g_assert (GDATA_IS_CONTACTS_CONTACT (contact));
@@ -298,8 +299,7 @@ test_insert_simple (gconstpointer service)
 	              "subject", &subject,
 	              NULL);
 
-	g_assert_cmpint (edited->tv_sec, ==, creation_time.tv_sec);
-	/*g_assert_cmpint (edited->tv_usec, ==, creation_time.tv_usec); --- testing to the nearest microsecond is too precise, and always fails */
+	g_assert_cmpint (edited, ==, current_time.tv_sec);
 	g_assert (deleted == FALSE);
 	g_assert (has_photo == FALSE);
 	g_assert (name2 == name);
@@ -400,8 +400,8 @@ test_insert_simple (gconstpointer service)
 	g_clear_error (&error);
 
 	/* Check its edited date */
-	gdata_contacts_contact_get_edited (new_contact, &creation_time);
-	g_assert_cmpint (creation_time.tv_sec, >=, edited->tv_sec);
+	creation_time = gdata_contacts_contact_get_edited (new_contact);
+	g_assert_cmpint (creation_time, >=, edited);
 
 	/* Various properties */
 	g_assert_cmpstr (gdata_contacts_contact_get_nickname (new_contact), ==, "Big J");
@@ -573,7 +573,6 @@ test_insert_simple (gconstpointer service)
 	gdata_contacts_contact_remove_all_hobbies (new_contact);
 	g_assert (gdata_contacts_contact_get_hobbies (new_contact) == NULL);
 
-	g_free (edited);
 	g_object_unref (contact);
 	g_object_unref (new_contact);
 }
diff --git a/gdata/tests/general.c b/gdata/tests/general.c
index a478ba8..678f470 100644
--- a/gdata/tests/general.c
+++ b/gdata/tests/general.c
@@ -26,7 +26,7 @@
 static void
 test_entry_get_xml (void)
 {
-	GTimeVal updated, published, updated2, published2, *updated3, *published3;
+	gint64 updated, published, updated2, published2, updated3, published3;
 	GDataEntry *entry, *entry2;
 	GDataCategory *category;
 	GDataLink *_link; /* stupid unistd.h */
@@ -154,15 +154,13 @@ test_entry_get_xml (void)
 	g_assert_cmpstr (gdata_entry_get_content (entry), ==, gdata_entry_get_content (entry2));
 	g_assert_cmpstr (gdata_entry_get_content_uri (entry), ==, gdata_entry_get_content_uri (entry2)); /* should both be NULL */
 
-	gdata_entry_get_updated (entry, &updated);
-	gdata_entry_get_updated (entry2, &updated2);
-	g_assert_cmpuint (updated.tv_sec, ==, updated2.tv_sec);
-	g_assert_cmpuint (updated.tv_usec, ==, updated2.tv_usec);
+	updated = gdata_entry_get_updated (entry);
+	updated2 = gdata_entry_get_updated (entry2);
+	g_assert_cmpuint (updated, ==, updated2);
 
-	gdata_entry_get_published (entry, &published);
-	gdata_entry_get_published (entry2, &published2);
-	g_assert_cmpuint (published.tv_sec, ==, published2.tv_sec);
-	g_assert_cmpuint (published.tv_usec, ==, published2.tv_usec);
+	published = gdata_entry_get_published (entry);
+	published2 = gdata_entry_get_published (entry2);
+	g_assert_cmpuint (published, ==, published2);
 
 	/* Check links */
 	_link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
@@ -256,10 +254,8 @@ test_entry_get_xml (void)
 	g_assert_cmpstr (summary, ==, gdata_entry_get_summary (entry));
 	g_assert_cmpstr (id, ==, gdata_entry_get_id (entry));
 	g_assert_cmpstr (etag, ==, gdata_entry_get_etag (entry));
-	g_assert_cmpint (updated3->tv_sec, ==, updated.tv_sec);
-	g_assert_cmpint (updated3->tv_usec, ==, updated.tv_usec);
-	g_assert_cmpint (published3->tv_sec, ==, published.tv_sec);
-	g_assert_cmpint (published3->tv_usec, ==, published.tv_usec);
+	g_assert_cmpint (updated3, ==, updated);
+	g_assert_cmpint (published3, ==, published);
 	g_assert_cmpstr (content, ==, gdata_entry_get_content (entry));
 	g_assert_cmpstr (content_uri, ==, gdata_entry_get_content_uri (entry));
 	g_assert (is_inserted == FALSE);
@@ -269,8 +265,6 @@ test_entry_get_xml (void)
 	g_free (summary);
 	g_free (id);
 	g_free (etag);
-	g_free (updated3);
-	g_free (published3);
 	g_free (content);
 	g_free (content_uri);
 	g_free (rights);
@@ -304,8 +298,8 @@ test_entry_parse_xml (void)
 	entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY,
 		"<entry xmlns='http://www.w3.org/2005/Atom' xmlns:ns='http://example.com/'>"
 			"<title type='text'>Testing unhandled XML</title>"
-			"<updated>2009-01-25T14:07:37.880860Z</updated>"
-			"<published>2009-01-23T14:06:37.880860Z</published>"
+			"<updated>2009-01-25T14:07:37Z</updated>"
+			"<published>2009-01-23T14:06:37Z</published>"
 			"<content type='text'>Here we test unhandled XML elements.</content>"
 			"<foobar>Test!</foobar>"
 			"<barfoo shizzle='zing'/>"
@@ -321,8 +315,8 @@ test_entry_parse_xml (void)
 			 "<?xml version='1.0' encoding='UTF-8'?>"
 			 "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' xmlns:ns='http://example.com/'>"
 				"<title type='text'>Testing unhandled XML</title>"
-				"<updated>2009-01-25T14:07:37.880860Z</updated>"
-				"<published>2009-01-23T14:06:37.880860Z</published>"
+				"<updated>2009-01-25T14:07:37Z</updated>"
+				"<published>2009-01-23T14:06:37Z</published>"
 				"<content type='text'>Here we test unhandled XML elements.</content>"
 				"<foobar>Test!</foobar>"
 				"<barfoo shizzle=\"zing\"/>"
@@ -371,7 +365,7 @@ test_feed_parse_xml (void)
 	GDataLink *_link; /* stupid unistd.h */
 	GList *list;
 	gchar *title, *subtitle, *id, *etag, *logo, *icon, *rights;
-	GTimeVal *updated, updated2;
+	gint64 updated, updated2;
 	GDataGenerator *generator;
 	guint items_per_page, start_index, total_results;
 	GError *error = NULL;
@@ -442,8 +436,7 @@ test_feed_parse_xml (void)
 	g_assert_cmpstr (id, ==, "http://example.com/id";);
 	g_assert_cmpstr (etag, ==, "W/\"D08FQn8-eil7ImA9WxZbFEw.\"");
 
-	g_assert_cmpint (updated->tv_sec, ==, 1235570857);
-	g_assert_cmpint (updated->tv_usec, ==, 880860);
+	g_assert_cmpint (updated, ==, 1235570857);
 
 	g_assert_cmpstr (logo, ==, "http://example.com/logo.png";);
 	g_assert_cmpstr (icon, ==, "http://example.com/icon.png";);
@@ -462,7 +455,6 @@ test_feed_parse_xml (void)
 	g_free (subtitle);
 	g_free (id);
 	g_free (etag);
-	g_free (updated);
 	g_free (logo);
 	g_free (icon);
 	g_free (rights);
@@ -520,9 +512,8 @@ test_feed_parse_xml (void)
 	g_assert_cmpstr (gdata_feed_get_id (feed), ==, "http://example.com/id";);
 	g_assert_cmpstr (gdata_feed_get_etag (feed), ==, "W/\"D08FQn8-eil7ImA9WxZbFEw.\"");
 
-	gdata_feed_get_updated (feed, &updated2);
-	g_assert_cmpint (updated2.tv_sec, ==, 1235570857);
-	g_assert_cmpint (updated2.tv_usec, ==, 880860);
+	updated2 = gdata_feed_get_updated (feed);
+	g_assert_cmpint (updated2, ==, 1235570857);
 
 	g_assert_cmpstr (gdata_feed_get_logo (feed), ==, "http://example.com/logo.png";);
 	g_assert_cmpstr (gdata_feed_get_icon (feed), ==, "http://example.com/icon.png";);
@@ -699,10 +690,10 @@ test_query_etag (void)
 	CHECK_ETAG (gdata_query_set_q (query, "q"))
 	CHECK_ETAG (gdata_query_set_categories (query, "shizzle,foobar"))
 	CHECK_ETAG (gdata_query_set_author (query, "John Smith"))
-	CHECK_ETAG (gdata_query_set_updated_min (query, NULL))
-	CHECK_ETAG (gdata_query_set_updated_max (query, NULL))
-	CHECK_ETAG (gdata_query_set_published_min (query, NULL))
-	CHECK_ETAG (gdata_query_set_published_max (query, NULL))
+	CHECK_ETAG (gdata_query_set_updated_min (query, -1))
+	CHECK_ETAG (gdata_query_set_updated_max (query, -1))
+	CHECK_ETAG (gdata_query_set_published_min (query, -1))
+	CHECK_ETAG (gdata_query_set_published_max (query, -1))
 	CHECK_ETAG (gdata_query_set_start_index (query, 5))
 	CHECK_ETAG (gdata_query_set_is_strict (query, TRUE))
 	CHECK_ETAG (gdata_query_set_max_results (query, 1000))
@@ -767,7 +758,7 @@ test_access_rule_get_xml (void)
 {
 	GDataAccessRule *rule, *rule2;
 	gchar *xml, *role, *scope_type3, *scope_value3;
-	GTimeVal edited, *edited2;
+	gint64 edited, edited2;
 	const gchar *scope_type, *scope_value, *scope_type2, *scope_value2;
 	GError *error = NULL;
 
@@ -784,8 +775,8 @@ test_access_rule_get_xml (void)
 	gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
 	g_assert_cmpstr (scope_type, ==, "A scope type");
 	g_assert_cmpstr (scope_value, ==, "A scope value");
-	gdata_access_rule_get_edited (rule, &edited);
-	g_assert_cmpuint (edited.tv_sec, >, 0); /* current time */
+	edited = gdata_access_rule_get_edited (rule);
+	g_assert_cmpuint (edited, >, 0); /* current time */
 
 	/* Set the properties more conventionally */
 	gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE);
@@ -817,9 +808,8 @@ test_access_rule_get_xml (void)
 	gdata_access_rule_get_scope (rule2, &scope_type2, &scope_value2);
 	g_assert_cmpstr (scope_type, ==, scope_type2);
 	g_assert_cmpstr (scope_value, ==, scope_value2);
-	gdata_access_rule_get_edited (rule2, &edited);
-	g_assert_cmpuint (edited.tv_sec, ==, 0); /* unspecified in XML */
-	g_assert_cmpuint (edited.tv_usec, ==, 0);
+	edited = gdata_access_rule_get_edited (rule2);
+	g_assert_cmpuint (edited, ==, -1); /* unspecified in XML */
 
 	/* Check properties a different way */
 	g_object_get (G_OBJECT (rule2),
@@ -832,10 +822,8 @@ test_access_rule_get_xml (void)
 	g_assert_cmpstr (role, ==, gdata_access_rule_get_role (rule));
 	g_assert_cmpstr (scope_type, ==, scope_type3);
 	g_assert_cmpstr (scope_value, ==, scope_value3);
-	g_assert_cmpuint (edited2->tv_sec, ==, 0);
-	g_assert_cmpuint (edited2->tv_usec, ==, 0);
+	g_assert_cmpuint (edited2, ==, -1);
 
-	g_free (edited2);
 	g_free (role);
 	g_free (scope_type3);
 	g_free (scope_value3);
@@ -2003,7 +1991,7 @@ test_gd_reminder (void)
 {
 	GDataGDReminder *reminder, *reminder2;
 	gchar *xml;
-	GTimeVal time_val;
+	gint64 _time;
 	GError *error = NULL;
 
 	reminder = GDATA_GD_REMINDER (gdata_parsable_new_from_xml (GDATA_TYPE_GD_REMINDER,
@@ -2038,7 +2026,7 @@ test_gd_reminder (void)
 	g_assert_cmpint (gdata_gd_reminder_get_relative_time (reminder), ==, 15 * 60);
 
 	/* Compare to another reminder */
-	reminder2 = gdata_gd_reminder_new (NULL, NULL, 15 * 60);
+	reminder2 = gdata_gd_reminder_new (NULL, -1, 15 * 60);
 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (reminder), GDATA_COMPARABLE (reminder2)), ==, 0);
 	g_object_unref (reminder2);
 	g_object_unref (reminder);
@@ -2066,12 +2054,11 @@ test_gd_reminder (void)
 	/* Check the properties */
 	g_assert_cmpstr (gdata_gd_reminder_get_method (reminder), ==, GDATA_GD_REMINDER_ALERT);
 	g_assert (gdata_gd_reminder_is_absolute_time (reminder) == TRUE);
-	gdata_gd_reminder_get_absolute_time (reminder, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 1118105700);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
+	_time = gdata_gd_reminder_get_absolute_time (reminder);
+	g_assert_cmpint (_time, ==, 1118105700);
 
 	/* Compare to another reminder */
-	reminder2 = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, &time_val, -1);
+	reminder2 = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, _time, -1);
 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (reminder), GDATA_COMPARABLE (reminder2)), ==, 0);
 	g_object_unref (reminder2);
 
@@ -2091,7 +2078,7 @@ test_gd_reminder_escaping (void)
 	GDataGDReminder *reminder;
 	gchar *xml;
 
-	reminder = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT "?foo&bar", NULL, 15);
+	reminder = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT "?foo&bar", -1, 15);
 
 	/* Check the outputted XML is escaped properly */
 	xml = gdata_parsable_get_xml (GDATA_PARSABLE (reminder));
@@ -2110,7 +2097,7 @@ test_gd_when (void)
 	GDataGDReminder *reminder;
 	gchar *xml;
 	GList *reminders;
-	GTimeVal time_val, time_val2;
+	gint64 _time, _time2;
 	GError *error = NULL;
 
 	when = GDATA_GD_WHEN (gdata_parsable_new_from_xml (GDATA_TYPE_GD_WHEN,
@@ -2121,23 +2108,21 @@ test_gd_when (void)
 	g_clear_error (&error);
 
 	/* Check the properties */
-	gdata_gd_when_get_start_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 1118106000);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
-	gdata_gd_when_get_end_time (when, &time_val2);
-	g_assert_cmpint (time_val2.tv_sec, ==, 1118109600);
-	g_assert_cmpint (time_val2.tv_usec, ==, 0);
+	_time = gdata_gd_when_get_start_time (when);
+	g_assert_cmpint (_time, ==, 1118106000);
+	_time2 = gdata_gd_when_get_end_time (when);
+	g_assert_cmpint (_time2, ==, 1118109600);
 	g_assert (gdata_gd_when_is_date (when) == FALSE);
 	g_assert (gdata_gd_when_get_value_string (when) == NULL);
 	g_assert (gdata_gd_when_get_reminders (when) == NULL);
 
 	/* Compare it against another identical time */
-	when2 = gdata_gd_when_new (&time_val, &time_val2, FALSE);
+	when2 = gdata_gd_when_new (_time, _time2, FALSE);
 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when), GDATA_COMPARABLE (when2)), ==, 0);
 
 	/* â?¦and a different one */
-	time_val2.tv_usec = 100;
-	gdata_gd_when_set_end_time (when2, &time_val2);
+	_time2 = 100;
+	gdata_gd_when_set_end_time (when2, _time2);
 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when), GDATA_COMPARABLE (when2)), !=, 0);
 	g_object_unref (when2);
 
@@ -2161,12 +2146,10 @@ test_gd_when (void)
 	g_clear_error (&error);
 
 	/* Check the properties */
-	gdata_gd_when_get_start_time (when, &time_val);
-	g_assert_cmpint (time_val.tv_sec, ==, 1118016000);
-	g_assert_cmpint (time_val.tv_usec, ==, 0);
-	gdata_gd_when_get_end_time (when, &time_val2);
-	g_assert_cmpint (time_val2.tv_sec, ==, 1118188800);
-	g_assert_cmpint (time_val2.tv_usec, ==, 0);
+	_time = gdata_gd_when_get_start_time (when);
+	g_assert_cmpint (_time, ==, 1118016000);
+	_time2 = gdata_gd_when_get_end_time (when);
+	g_assert_cmpint (_time2, ==, 1118188800);
 	g_assert (gdata_gd_when_is_date (when) == TRUE);
 	g_assert_cmpstr (gdata_gd_when_get_value_string (when), ==, "This weekend");
 
@@ -2178,7 +2161,7 @@ test_gd_when (void)
 	g_assert_cmpint (gdata_gd_reminder_get_relative_time (GDATA_GD_REMINDER (reminders->data)), ==, 15);
 
 	/* Add another reminder */
-	reminder = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, &time_val, -1);
+	reminder = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, _time, -1);
 	gdata_gd_when_add_reminder (when, reminder);
 	g_object_unref (reminder);
 
@@ -2204,7 +2187,7 @@ test_gd_when_escaping (void)
 	GTimeVal start_time;
 
 	g_time_val_from_iso8601 ("2005-06-07T01:00:00Z", &start_time);
-	when = gdata_gd_when_new (&start_time, NULL, FALSE);
+	when = gdata_gd_when_new (start_time.tv_sec, -1, FALSE);
 	gdata_gd_when_set_value_string (when, "Value string & stuff!");
 
 	/* Check the outputted XML is escaped properly */
diff --git a/gdata/tests/picasaweb.c b/gdata/tests/picasaweb.c
index 608090f..cfd4080 100644
--- a/gdata/tests/picasaweb.c
+++ b/gdata/tests/picasaweb.c
@@ -33,7 +33,7 @@
 
 #define PW_USERNAME "libgdata picasaweb gmail com"
 /* the following two properties will change if a new album is added */
-#define NUM_ALBUMS 3
+#define NUM_ALBUMS 5
 #define TEST_ALBUM_INDEX 2
 
 static void
@@ -212,7 +212,7 @@ test_upload_async (gconstpointer service)
 	g_assert (g_regex_match (regex, xml, 0, &match_info) == TRUE);
 	parsed_time_str = g_match_info_fetch (match_info, 1);
 	delta = g_ascii_strtoull (parsed_time_str, NULL, 10) - (((guint64) timeval.tv_sec) * 1000 + ((guint64) timeval.tv_usec) / 1000);
-	g_assert_cmpuint (abs (delta), <, 100);
+	g_assert_cmpuint (abs (delta), <, 1000);
 
 	g_free (parsed_time_str);
 	g_free (xml);
@@ -586,7 +586,7 @@ test_upload_simple (gconstpointer service)
 	g_assert (g_regex_match (regex, xml, 0, &match_info) == TRUE);
 	parsed_time_str = g_match_info_fetch (match_info, 1);
 	delta = g_ascii_strtoull (parsed_time_str, NULL, 10) - (((guint64) timeval.tv_sec) * 1000 + ((guint64) timeval.tv_usec) / 1000);
-	g_assert_cmpuint (abs (delta), <, 100);
+	g_assert_cmpuint (abs (delta), <, 1000);
 
 	g_free (parsed_time_str);
 	g_free (xml);
@@ -633,9 +633,6 @@ test_photo (gconstpointer service)
 	GList *list;
 	GDataMediaContent *content;
 	GDataMediaThumbnail *thumbnail;
-	GTimeVal _time;
-	gchar *str;
-	gchar *timestamp;
 	const gchar * const *tags;
 	gdouble latitude;
 	gdouble longitude;
@@ -661,10 +658,7 @@ test_photo (gconstpointer service)
 	photo_entry = GDATA_ENTRY (g_list_nth_data (files, 0));
 	photo = GDATA_PICASAWEB_FILE (photo_entry);
 
-	gdata_picasaweb_file_get_edited (photo, &_time);
-	str = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (str, ==, "2010-05-13T20:45:13.603000Z");
-	g_free (str);
+	g_assert_cmpint (gdata_picasaweb_file_get_edited (photo), ==, 1273783513);
 
 	/* tests */
 
@@ -677,11 +671,7 @@ test_photo (gconstpointer service)
 	g_assert_cmpuint (gdata_picasaweb_file_get_size (photo), ==, 1124730);
 	/* TODO: file wasn't uploaded with client assigned; g_assert_cmpstr (gdata_picasaweb_file_get_client (photo), ==, ??); */
 	/* TODO: file wasn't uploaded with checksum assigned; g_assert_cmpstr (gdata_picasaweb_file_get_checksum (photo), ==, ??); */
-
-	gdata_picasaweb_file_get_timestamp (photo, &_time);
-	timestamp = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (timestamp, ==, "2008-12-06T18:32:10Z");
-
+	g_assert_cmpint (gdata_picasaweb_file_get_timestamp (photo), ==, 1228588330000);
 	g_assert_cmpstr (gdata_picasaweb_file_get_video_status (photo), ==, NULL);
 	/* TODO: not a good test of video status; want to upload a video for it */
 	g_assert_cmpuint (gdata_picasaweb_file_is_commenting_enabled (photo), ==, TRUE);
@@ -755,8 +745,6 @@ test_photo (gconstpointer service)
 	g_assert_cmpuint (gdata_media_thumbnail_get_width (thumbnail), ==, 288);
 	g_assert_cmpuint (gdata_media_thumbnail_get_height (thumbnail), ==, 216);
 	g_assert_cmpint (gdata_media_thumbnail_get_time (thumbnail), ==, -1); /* PicasaWeb doesn't set anything better */
-
-	g_free (timestamp);
 }
 
 static void
@@ -770,8 +758,6 @@ test_photo_feed_entry (gconstpointer service)
 	GList *albums;
 	GList *files;
 	GDataEntry *photo_entry;
-	gchar *str;
-	GTimeVal _time;
 
 	album_feed = gdata_picasaweb_service_query_all_albums (GDATA_PICASAWEB_SERVICE (service), NULL, NULL, NULL, NULL, NULL, &error);
 	g_assert_no_error (error);
@@ -799,17 +785,8 @@ test_photo_feed_entry (gconstpointer service)
 	g_assert_cmpstr (gdata_picasaweb_file_get_id (GDATA_PICASAWEB_FILE (photo_entry)), ==, "5328890138794566386");
 	g_assert_cmpstr (gdata_entry_get_id (photo_entry), ==, "http://picasaweb.google.com/data/entry/user/libgdata.picasaweb/albumid/5328889949261497249/photoid/5328890138794566386";);
 	g_assert_cmpstr (gdata_entry_get_etag (photo_entry), !=, NULL);
-
-	gdata_entry_get_updated (photo_entry, &_time);
-	str = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (str, ==, "2010-05-13T20:45:13.603000Z");
-	g_free (str);
-
-	gdata_entry_get_published (photo_entry, &_time);
-	str = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (str, ==, "2009-04-26T06:55:20Z");
-	g_free (str);
-
+	g_assert_cmpint (gdata_entry_get_updated (photo_entry), ==, 1273783513);
+	g_assert_cmpint (gdata_entry_get_published (photo_entry), ==, 1240728920);
 	g_assert (gdata_entry_get_content (photo_entry) == NULL);
 	g_assert_cmpstr (gdata_entry_get_content_uri (photo_entry), ==,
 			 "http://lh3.ggpht.com/_1kdcGyvOb8c/SfQFWPnuovI/AAAAAAAAAB0/MI0L4Sd11Eg/100_0269.jpg";);
@@ -880,8 +857,7 @@ test_album (gconstpointer service)
 	GDataFeed *album_feed;
 	GDataPicasaWebAlbum *album;
 	GList *albums, *contents, *thumbnails;
-	GTimeVal _time;
-	gchar *str, *original_rights;
+	gchar *original_rights;
 	gdouble latitude, longitude, original_latitude, original_longitude;
 	GDataMediaContent *content;
 	GDataMediaThumbnail *thumbnail;
@@ -902,20 +878,10 @@ test_album (gconstpointer service)
 	/* Check album-specific API */
 	g_assert_cmpstr (gdata_picasaweb_album_get_user (album), ==, "libgdata.picasaweb");
 	g_assert_cmpstr (gdata_picasaweb_album_get_nickname (album), ==, "libgdata.picasaweb");
-
-	gdata_picasaweb_album_get_edited (album, &_time);
-	str = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (str, ==, "2009-04-26T06:57:03.474000Z");
-	g_free (str);
-
+	g_assert_cmpint (gdata_picasaweb_album_get_edited (album), ==, 1240729023);
 	g_assert_cmpint (gdata_picasaweb_album_get_visibility (album), ==, GDATA_PICASAWEB_PUBLIC);
 	g_assert_cmpstr (gdata_picasaweb_album_get_location (album), ==, "Venice");
-
-	gdata_picasaweb_album_get_timestamp (album, &_time);
-	str = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (str, ==, "2009-04-26T07:00:00Z");
-	g_free (str);
-
+	g_assert_cmpint (gdata_picasaweb_album_get_timestamp (album), ==, 1240729200000);
 	g_assert_cmpuint (gdata_picasaweb_album_get_num_photos (album), ==, 1);
 	g_assert_cmpuint (gdata_picasaweb_album_get_num_photos_remaining (album), >, 0); /* about 999 remaining, testing weakly to avoid having to update regularly */
 	g_assert_cmpuint (gdata_picasaweb_album_get_bytes_used (album), ==, 1124730);
@@ -1005,8 +971,7 @@ test_album_feed_entry (gconstpointer service)
 	GError *error = NULL;
 	GDataEntry *entry;
 	GList *albums;
-	gchar *str, *xml;
-	GTimeVal _time;
+	gchar *xml;
 
 	album_feed = gdata_picasaweb_service_query_all_albums (GDATA_PICASAWEB_SERVICE (service), NULL, NULL, NULL, NULL, NULL, &error);
 	g_assert_no_error (error);
@@ -1028,16 +993,8 @@ test_album_feed_entry (gconstpointer service)
 	g_assert_cmpstr (gdata_entry_get_id (entry), ==, "http://picasaweb.google.com/data/entry/user/libgdata.picasaweb/albumid/5328889949261497249";);
 	g_assert_cmpstr (gdata_entry_get_etag (entry), !=, NULL);
 	g_assert_cmpstr (gdata_entry_get_rights (entry), ==, "public");
-
-	gdata_entry_get_updated (entry, &_time);
-	str = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (str, ==, "2009-04-26T06:57:03.474000Z");
-	g_free (str);
-
-	gdata_entry_get_published (entry, &_time);
-	str = g_time_val_to_iso8601 (&_time);
-	g_assert_cmpstr (str, ==, "2009-04-26T07:00:00Z");
-	g_free (str);
+	g_assert_cmpint (gdata_entry_get_updated (entry), ==, 1240729023);
+	g_assert_cmpint (gdata_entry_get_published (entry), ==, 1240729200);
 
 	xml = gdata_parsable_get_xml (GDATA_PARSABLE (entry));
 	g_assert_cmpstr (xml, !=, NULL);
@@ -1076,7 +1033,6 @@ test_insert_album (gconstpointer service)
 	GDataPicasaWebAlbum *album;
 	GDataPicasaWebAlbum *inserted_album;
 	GTimeVal timestamp;
-	gchar *timestr;
 	GError *error;
 
 	GDataFeed *album_feed;
@@ -1094,7 +1050,7 @@ test_insert_album (gconstpointer service)
 	gdata_picasaweb_album_set_location (album, "Winnipeg, MN");
 
 	g_time_val_from_iso8601 ("2002-10-14T09:58:59.643554Z", &timestamp);
-	gdata_picasaweb_album_set_timestamp (album, &timestamp);
+	gdata_picasaweb_album_set_timestamp (album, timestamp.tv_sec * 1000);
 
 	inserted_album = gdata_picasaweb_service_insert_album (GDATA_PICASAWEB_SERVICE (service), album, NULL, &error);
 	g_assert_no_error (error);
@@ -1104,11 +1060,7 @@ test_insert_album (gconstpointer service)
 	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (inserted_album)), ==, "Thanksgiving photos");
 	g_assert_cmpstr (gdata_entry_get_summary (GDATA_ENTRY (inserted_album)), ==, "Family photos of the feast!");
 	g_assert_cmpstr (gdata_picasaweb_album_get_location (inserted_album), ==, "Winnipeg, MN");
-
-	gdata_picasaweb_album_get_timestamp (inserted_album, &timestamp);
-	timestr = g_time_val_to_iso8601 (&timestamp);
-	g_assert_cmpstr (timestr, ==, "2002-10-14T09:58:59Z");
-	g_free (timestr);
+	g_assert_cmpint (gdata_picasaweb_album_get_timestamp (inserted_album), ==, 1034589539000);
 
 	/* Test that album is actually on server */
 	album_feed = gdata_picasaweb_service_query_all_albums (GDATA_PICASAWEB_SERVICE (service), NULL, NULL, NULL, NULL, NULL, &error);
@@ -1319,7 +1271,7 @@ test_album_new (void)
 	g_assert (g_regex_match (regex, xml, 0, &match_info) == TRUE);
 	parsed_time_str = g_match_info_fetch (match_info, 1);
 	delta = g_ascii_strtoull (parsed_time_str, NULL, 10) - (((guint64) timeval.tv_sec) * 1000 + ((guint64) timeval.tv_usec) / 1000);
-	g_assert_cmpuint (abs (delta), <, 100);
+	g_assert_cmpuint (abs (delta), <, 1000);
 
 	g_free (parsed_time_str);
 	g_free (xml);
diff --git a/gdata/tests/youtube.c b/gdata/tests/youtube.c
index b2d2ae3..d86a852 100644
--- a/gdata/tests/youtube.c
+++ b/gdata/tests/youtube.c
@@ -375,7 +375,7 @@ static void
 test_parsing_yt_recorded (void)
 {
 	GDataYouTubeVideo *video;
-	GTimeVal recorded;
+	gint64 recorded;
 	gchar *xml;
 	GError *error = NULL;
 
@@ -408,13 +408,12 @@ test_parsing_yt_recorded (void)
 	g_clear_error (&error);
 
 	/* Test the recorded date */
-	gdata_youtube_video_get_recorded (video, &recorded);
-	g_assert_cmpint (recorded.tv_sec, ==, 1059868800);
-	g_assert_cmpint (recorded.tv_usec, ==, 0);
+	recorded = gdata_youtube_video_get_recorded (video);
+	g_assert_cmpint (recorded, ==, 1059868800);
 
 	/* Update the state and see if the XML's written out OK */
-	recorded.tv_sec = 1128229200;
-	gdata_youtube_video_set_recorded (video, &recorded);
+	recorded = 1128229200;
+	gdata_youtube_video_set_recorded (video, recorded);
 
 	/* Check the XML */
 	xml = gdata_parsable_get_xml (GDATA_PARSABLE (video));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]