From 26e0e1d25a588861bf16f574f9b98c63d3c0aeea Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Mon, 19 Aug 2019 22:35:47 +0200
Subject: [PATCH] time/ISO8601: allow omitting the "Z" suffix

And allow "Z" suffix after date.
---
 NEWS                 | 3 ++-
 src/time/ISO8601.cxx | 5 ++++-
 test/TestISO8601.cxx | 6 ++++++
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 2ff1398df..f7c47a7c4 100644
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,8 @@ ver 0.22 (not yet released)
   - "findadd"/"searchadd"/"searchaddpl" support the "sort" and
     "window" parameters
   - add command "readpicture" to download embedded pictures
-  - relax the ISO 8601 parser: allow omitting the time of day
+  - relax the ISO 8601 parser: allow omitting the time of day and the "Z"
+    suffix
 * tags
   - new tags "Grouping" (for ID3 "TIT1") and "Work"
 * input
diff --git a/src/time/ISO8601.cxx b/src/time/ISO8601.cxx
index 4811813fb..f08938e4e 100644
--- a/src/time/ISO8601.cxx
+++ b/src/time/ISO8601.cxx
@@ -83,7 +83,7 @@ ParseISO8601(const char *s)
 	/* parse the time of day */
 	if (*s == 'T') {
 		++s;
-		end = strptime(s, "%TZ", &tm);
+		end = strptime(s, "%T", &tm);
 		if (end == nullptr)
 			throw std::runtime_error("Failed to parse time of day");
 
@@ -93,6 +93,9 @@ ParseISO8601(const char *s)
 
 	auto tp = TimeGm(tm);
 
+	if (*s == 'Z')
+		++s;
+
 	if (*s != 0)
 		throw std::runtime_error("Garbage at end of time stamp");
 
diff --git a/test/TestISO8601.cxx b/test/TestISO8601.cxx
index d5e8dd2dc..6fdc11dc8 100644
--- a/test/TestISO8601.cxx
+++ b/test/TestISO8601.cxx
@@ -51,6 +51,12 @@ static constexpr struct {
 	{ "2019-02-04", 1549238400, std::chrono::hours(24) },
 	{ "2018-12-31", 1546214400, std::chrono::hours(24) },
 	{ "2019-01-01", 1546300800, std::chrono::hours(24) },
+
+	/* date with time zone */
+	{ "2019-02-04Z", 1549238400, std::chrono::hours(24) },
+
+	/* without time zone */
+	{ "2019-02-04T16:46:41", 1549298801, std::chrono::seconds(1) },
 };
 
 TEST(ISO8601, Parse)