summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <withnall@endlessm.com>2017-04-20 11:50:09 +0100
committerPhilip Withnall <withnall@endlessm.com>2017-04-20 11:50:09 +0100
commitd10155034b0fa2e43e2889e55157798ce073f807 (patch)
tree4a06412a339a7e3abc8e9ec2ce5b90cbd75a5a1c
parent61659ca68638dbccf3f1dbba8927f053b301de40 (diff)
downloadlibgdata-d10155034b0fa2e43e2889e55157798ce073f807.tar.gz
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>
-rw-r--r--gdata/gdata-parser.c31
-rw-r--r--gdata/gdata-parser.h1
-rw-r--r--gdata/services/tasks/gdata-tasks-query.c10
-rw-r--r--gdata/services/tasks/gdata-tasks-task.c49
-rw-r--r--gdata/services/tasks/gdata-tasks-tasklist.c50
-rw-r--r--gdata/tests/tasks.c34
6 files changed, 148 insertions, 27 deletions
diff --git a/gdata/gdata-parser.c b/gdata/gdata-parser.c
index a43c2ecf..ef10a479 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 bc7a15a7..6f0303f7 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 627dc862..80ff7022 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 00490b89..568c8288 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 1690c232..2fbc470e 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 2e9a03ef..7ea4fd47 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: */