[libgdata] tasks: Re-add ISO 8601 formatting workaround for Tasks service



commit d10155034b0fa2e43e2889e55157798ce073f807
Author: Philip Withnall <withnall endlessm com>
Date:   Thu Apr 20 11:50:09 2017 +0100

    tasks: Re-add ISO 8601 formatting workaround for Tasks service
    
    This partially reverts commit 684f95e8845be4f9efc434ea6456bee99b2303ac
    for the Tasks service only, since it is the only service which currently
    requires a formatting workaround for ISO 8601 date timezones.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=780067
    
    Signed-off-by: Philip Withnall <withnall endlessm com>

 gdata/gdata-parser.c                        |   31 ++++++++++++++++
 gdata/gdata-parser.h                        |    1 +
 gdata/services/tasks/gdata-tasks-query.c    |   10 +++---
 gdata/services/tasks/gdata-tasks-task.c     |   49 +++++++++++++++++++++++---
 gdata/services/tasks/gdata-tasks-tasklist.c |   50 +++++++++++++++++++++++++++
 gdata/tests/tasks.c                         |   34 +++++++++---------
 6 files changed, 148 insertions(+), 27 deletions(-)
---
diff --git a/gdata/gdata-parser.c b/gdata/gdata-parser.c
index a43c2ec..ef10a47 100644
--- a/gdata/gdata-parser.c
+++ b/gdata/gdata-parser.c
@@ -248,6 +248,37 @@ gdata_parser_int64_to_iso8601 (gint64 _time)
        return g_time_val_to_iso8601 (&time_val);
 }
 
+gchar *
+gdata_parser_int64_to_iso8601_numeric_timezone (gint64 _time)
+{
+       GTimeVal time_val;
+       gchar *iso8601;
+       gchar **date_time_components;
+       gchar *retval;
+
+       time_val.tv_sec = _time;
+       time_val.tv_usec = 0;
+
+       iso8601 = g_time_val_to_iso8601 (&time_val);
+
+       /* FIXME: Work around for Google's incorrect ISO 8601 implementation.
+        * They appear to not like dates in the format ‘2014-08-09T21:07:05Z’
+        * which specify a timezone using ‘Z’ and no microseconds. This varies
+        * between services.
+        *
+        * See: https://bugzilla.gnome.org/show_bug.cgi?id=732809
+        * https://bugzilla.gnome.org/show_bug.cgi?id=780067
+        * https://code.google.com/a/google.com/p/apps-api-issues/issues/detail?id=3595
+        * http://stackoverflow.com/a/17630320/2931197 */
+       date_time_components = g_strsplit (iso8601, "Z", 2);
+       retval = g_strjoinv (".000001+00:00", date_time_components);
+       g_strfreev (date_time_components);
+
+       g_free (iso8601);
+
+       return retval;
+}
+
 gboolean
 gdata_parser_int64_from_iso8601 (const gchar *date, gint64 *_time)
 {
diff --git a/gdata/gdata-parser.h b/gdata/gdata-parser.h
index bc7a15a..6f0303f 100644
--- a/gdata/gdata-parser.h
+++ b/gdata/gdata-parser.h
@@ -46,6 +46,7 @@ gdata_parser_error_from_json_error (JsonReader *reader,
 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;
+gchar *gdata_parser_int64_to_iso8601_numeric_timezone (gint64 _time) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 gboolean gdata_parser_int64_from_iso8601 (const gchar *date, gint64 *_time);
 
 /*
diff --git a/gdata/services/tasks/gdata-tasks-query.c b/gdata/services/tasks/gdata-tasks-query.c
index 627dc86..80ff702 100644
--- a/gdata/services/tasks/gdata-tasks-query.c
+++ b/gdata/services/tasks/gdata-tasks-query.c
@@ -288,7 +288,7 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 
                APPEND_SEP
                g_string_append (query_uri, "updatedMin=");
-               updated_min = gdata_parser_int64_to_iso8601 (gdata_query_get_updated_min (GDATA_QUERY 
(self)));
+               updated_min = gdata_parser_int64_to_iso8601_numeric_timezone (gdata_query_get_updated_min 
(GDATA_QUERY (self)));
                g_string_append (query_uri, updated_min);
                g_free (updated_min);
        }
@@ -298,7 +298,7 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 
                APPEND_SEP
                g_string_append (query_uri, "completedMin=");
-               completed_min = gdata_parser_int64_to_iso8601 (priv->completed_min);
+               completed_min = gdata_parser_int64_to_iso8601_numeric_timezone (priv->completed_min);
                g_string_append (query_uri, completed_min);
                g_free (completed_min);
        }
@@ -308,7 +308,7 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 
                APPEND_SEP
                g_string_append (query_uri, "completedMax=");
-               completed_max = gdata_parser_int64_to_iso8601 (priv->completed_max);
+               completed_max = gdata_parser_int64_to_iso8601_numeric_timezone (priv->completed_max);
                g_string_append (query_uri, completed_max);
                g_free (completed_max);
        }
@@ -318,7 +318,7 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 
                APPEND_SEP
                g_string_append (query_uri, "dueMin=");
-               due_min = gdata_parser_int64_to_iso8601 (priv->due_min);
+               due_min = gdata_parser_int64_to_iso8601_numeric_timezone (priv->due_min);
                g_string_append (query_uri, due_min);
                g_free (due_min);
        }
@@ -328,7 +328,7 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
 
                APPEND_SEP
                g_string_append (query_uri, "dueMax=");
-               due_max = gdata_parser_int64_to_iso8601 (priv->due_max);
+               due_max = gdata_parser_int64_to_iso8601_numeric_timezone (priv->due_max);
                g_string_append (query_uri, due_max);
                g_free (due_max);
        }
diff --git a/gdata/services/tasks/gdata-tasks-task.c b/gdata/services/tasks/gdata-tasks-task.c
index 00490b8..568c828 100644
--- a/gdata/services/tasks/gdata-tasks-task.c
+++ b/gdata/services/tasks/gdata-tasks-task.c
@@ -333,11 +333,50 @@ get_json (GDataParsable *parsable, JsonBuilder *builder)
 {
        gchar *due;
        gchar *completed;
-
+       GList *i;
+       GDataLink *_link;
+       GDataEntry *entry = GDATA_ENTRY (parsable);
        GDataTasksTaskPrivate *priv = GDATA_TASKS_TASK (parsable)->priv;
 
-       /* Chain up to the parent class */
-       GDATA_PARSABLE_CLASS (gdata_tasks_task_parent_class)->get_json (parsable, builder);
+       /* Add all the general JSON. We can’t chain up to #GDataEntry here
+        * because Google Tasks uses a different date format. */
+       json_builder_set_member_name (builder, "title");
+       json_builder_add_string_value (builder, gdata_entry_get_title (entry));
+
+       if (gdata_entry_get_id (entry)) {
+               json_builder_set_member_name (builder, "id");
+               json_builder_add_string_value (builder, gdata_entry_get_id (entry));
+       }
+
+       if (gdata_entry_get_updated (entry) != -1) {
+               gchar *updated = gdata_parser_int64_to_iso8601_numeric_timezone (gdata_entry_get_updated 
(entry));
+               json_builder_set_member_name (builder, "updated");
+               json_builder_add_string_value (builder, updated);
+               g_free (updated);
+       }
+
+       /* If we have a "kind" category, add that. */
+       for (i = gdata_entry_get_categories (entry); i != NULL; i = i->next) {
+               GDataCategory *category = GDATA_CATEGORY (i->data);
+
+               if (g_strcmp0 (gdata_category_get_scheme (category), "http://schemas.google.com/g/2005#kind";) 
== 0) {
+                       json_builder_set_member_name (builder, "kind");
+                       json_builder_add_string_value (builder, gdata_category_get_term (category));
+               }
+       }
+
+       /* Add the ETag, if available. */
+       if (gdata_entry_get_etag (entry) != NULL) {
+               json_builder_set_member_name (builder, "etag");
+               json_builder_add_string_value (builder, gdata_entry_get_etag (entry));
+       }
+
+       /* Add the self-link. */
+       _link = gdata_entry_look_up_link (GDATA_ENTRY (parsable), GDATA_LINK_SELF);
+       if (_link != NULL) {
+               json_builder_set_member_name (builder, "selfLink");
+               json_builder_add_string_value (builder, gdata_link_get_uri (_link));
+       }
 
        /* Add all the task specific JSON */
 
@@ -358,13 +397,13 @@ get_json (GDataParsable *parsable, JsonBuilder *builder)
                json_builder_add_string_value (builder, priv->status);
        }
        if (priv->due != -1) {
-               due = gdata_parser_int64_to_iso8601 (priv->due);
+               due = gdata_parser_int64_to_iso8601_numeric_timezone (priv->due);
                json_builder_set_member_name (builder, "due");
                json_builder_add_string_value (builder, due);
                g_free (due);
        }
        if (priv->completed != -1) {
-               completed = gdata_parser_int64_to_iso8601 (priv->completed);
+               completed = gdata_parser_int64_to_iso8601_numeric_timezone (priv->completed);
                json_builder_set_member_name (builder, "completed");
                json_builder_add_string_value (builder, completed);
                g_free (completed);
diff --git a/gdata/services/tasks/gdata-tasks-tasklist.c b/gdata/services/tasks/gdata-tasks-tasklist.c
index 1690c23..2fbc470 100644
--- a/gdata/services/tasks/gdata-tasks-tasklist.c
+++ b/gdata/services/tasks/gdata-tasks-tasklist.c
@@ -40,6 +40,7 @@
 #include "gdata-private.h"
 #include "gdata-types.h"
 
+static void get_json (GDataParsable *parsable, JsonBuilder *builder);
 static const gchar *get_content_type (void);
 
 G_DEFINE_TYPE (GDataTasksTasklist, gdata_tasks_tasklist, GDATA_TYPE_ENTRY)
@@ -50,6 +51,7 @@ gdata_tasks_tasklist_class_init (GDataTasksTasklistClass *klass)
        GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
        GDataEntryClass *entry_class = GDATA_ENTRY_CLASS (klass);
 
+       parsable_class->get_json = get_json;
        parsable_class->get_content_type = get_content_type;
 
        entry_class->kind_term = "tasks#taskList";
@@ -61,6 +63,54 @@ gdata_tasks_tasklist_init (GDataTasksTasklist *self)
        /* Empty */
 }
 
+static void
+get_json (GDataParsable *parsable, JsonBuilder *builder)
+{
+       GList *i;
+       GDataLink *_link;
+       GDataEntry *entry = GDATA_ENTRY (parsable);
+
+       /* Add all the general JSON. We can’t chain up to #GDataEntry here
+        * because Google Tasks uses a different date format. */
+       json_builder_set_member_name (builder, "title");
+       json_builder_add_string_value (builder, gdata_entry_get_title (entry));
+
+       if (gdata_entry_get_id (entry)) {
+               json_builder_set_member_name (builder, "id");
+               json_builder_add_string_value (builder, gdata_entry_get_id (entry));
+       }
+
+       if (gdata_entry_get_updated (entry) != -1) {
+               gchar *updated = gdata_parser_int64_to_iso8601_numeric_timezone (gdata_entry_get_updated 
(entry));
+               json_builder_set_member_name (builder, "updated");
+               json_builder_add_string_value (builder, updated);
+               g_free (updated);
+       }
+
+       /* If we have a "kind" category, add that. */
+       for (i = gdata_entry_get_categories (entry); i != NULL; i = i->next) {
+               GDataCategory *category = GDATA_CATEGORY (i->data);
+
+               if (g_strcmp0 (gdata_category_get_scheme (category), "http://schemas.google.com/g/2005#kind";) 
== 0) {
+                       json_builder_set_member_name (builder, "kind");
+                       json_builder_add_string_value (builder, gdata_category_get_term (category));
+               }
+       }
+
+       /* Add the ETag, if available. */
+       if (gdata_entry_get_etag (entry) != NULL) {
+               json_builder_set_member_name (builder, "etag");
+               json_builder_add_string_value (builder, gdata_entry_get_etag (entry));
+       }
+
+       /* Add the self-link. */
+       _link = gdata_entry_look_up_link (GDATA_ENTRY (parsable), GDATA_LINK_SELF);
+       if (_link != NULL) {
+               json_builder_set_member_name (builder, "selfLink");
+               json_builder_add_string_value (builder, gdata_link_get_uri (_link));
+       }
+}
+
 static const gchar *
 get_content_type (void)
 {
diff --git a/gdata/tests/tasks.c b/gdata/tests/tasks.c
index 2e9a03e..7ea4fd4 100644
--- a/gdata/tests/tasks.c
+++ b/gdata/tests/tasks.c
@@ -125,11 +125,11 @@ test_query_uri (void)
                         "?updated-min=1970-01-01T01:53:09Z"
                         "&max-results=10"
                         "&maxResults=10"
-                        "&updatedMin=1970-01-01T01:53:09Z"
-                        "&completedMin=1970-01-01T01:34:38Z"
-                        "&completedMax=1970-01-01T00:20:34Z"
-                        "&dueMin=1970-01-01T00:39:05Z"
-                        "&dueMax=1970-01-01T00:57:36Z"
+                        "&updatedMin=1970-01-01T01:53:09.000001+00:00"
+                        "&completedMin=1970-01-01T01:34:38.000001+00:00"
+                        "&completedMax=1970-01-01T00:20:34.000001+00:00"
+                        "&dueMin=1970-01-01T00:39:05.000001+00:00"
+                        "&dueMax=1970-01-01T00:57:36.000001+00:00"
                         "&showCompleted=true"
                         "&showDeleted=true"
                         "&showHidden=true");
@@ -153,11 +153,11 @@ test_query_uri (void)
                         "?updated-min=1970-01-01T01:53:09Z"
                         "&max-results=10"
                         "&maxResults=10"
-                        "&updatedMin=1970-01-01T01:53:09Z"
-                        "&completedMin=1970-01-01T01:34:38Z"
-                        "&completedMax=1970-01-01T00:20:34Z"
-                        "&dueMin=1970-01-01T00:39:05Z"
-                        "&dueMax=1970-01-01T00:57:36Z"
+                        "&updatedMin=1970-01-01T01:53:09.000001+00:00"
+                        "&completedMin=1970-01-01T01:34:38.000001+00:00"
+                        "&completedMax=1970-01-01T00:20:34.000001+00:00"
+                        "&dueMin=1970-01-01T00:39:05.000001+00:00"
+                        "&dueMax=1970-01-01T00:57:36.000001+00:00"
                         "&showCompleted=false"
                         "&showDeleted=false"
                         "&showHidden=false");
@@ -322,8 +322,8 @@ test_task_properties (void)
                        "\"title\": \"some-other-title\","
                        "\"notes\": \"more-notes\","
                        "\"status\": \"completed\","
-                       "\"due\": \"2014-08-30T17:20:00Z\","
-                       "\"completed\": \"2014-08-30T17:20:00Z\","
+                       "\"due\": \"2014-08-30T17:20:00.000001+00:00\","
+                       "\"completed\": \"2014-08-30T17:20:00.000001+00:00\","
                        "\"deleted\": true,"
                        "\"hidden\": false"
                "}");
@@ -337,8 +337,8 @@ test_task_properties (void)
                        "\"title\": \"some-other-title\","
                        "\"notes\": \"more-notes\","
                        "\"status\": \"completed\","
-                       "\"due\": \"2014-08-30T17:20:00Z\","
-                       "\"completed\": \"2014-08-30T17:20:00Z\","
+                       "\"due\": \"2014-08-30T17:20:00.000001+00:00\","
+                       "\"completed\": \"2014-08-30T17:20:00.000001+00:00\","
                        "\"deleted\": false,"
                        "\"hidden\": false"
                "}");
@@ -501,14 +501,14 @@ test_task_parser_normal (void)
                        "\"id\": \"some-id\","
                        "\"etag\": \"some-etag\","
                        "\"title\": \"some-title \\\"with quotes\\\"\","
-                       "\"updated\": \"2014-08-30T19:40:00Z\","
+                       "\"updated\": \"2014-08-30T19:40:00.000001+00:00\","
                        "\"selfLink\": \"http://some-uri/\",";
                        "\"parent\": \"some-parent-id\","
                        "\"position\": \"some-position\","
                        "\"notes\": \"Some notes!\","
                        "\"status\": \"needsAction\","
-                       "\"due\": \"2014-08-30T20:00:00Z\","
-                       "\"completed\": \"2014-08-30T20:10:05Z\","
+                       "\"due\": \"2014-08-30T20:00:00.000001+00:00\","
+                       "\"completed\": \"2014-08-30T20:10:05.000001+00:00\","
                        "\"deleted\": false,"
                        "\"hidden\": true,"
                        /* Unhandled for the moment: */


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