diff mbox series

[v2] date: make "iso-strict" conforming for the UTC timezone

Message ID 20240313222922.11170-1-dev+git@drbeat.li (mailing list archive)
State Superseded
Headers show
Series [v2] date: make "iso-strict" conforming for the UTC timezone | expand

Commit Message

Beat Bolli March 13, 2024, 10:29 p.m. UTC
ISO 8601-1:2020-12 specifies that a zero timezone offset must be denoted
with a "Z" suffix instead of the numeric "+00:00". Add the correponding
special case to show_date() and a new test.

This changes an established output format which might be depended on by
scripts. The original patch 466fb6742d7f (pretty: provide a strict ISO
8601 date format, 2014-08-29) mentioned XML parsers as its rationale,
which generally have good parsing support, so this change should be
fine.

Reported-by: Michael Osipov <michael.osipov@innomotics.com>
Signed-off-by: Beat Bolli <dev+git@drbeat.li>
---
Changes from v1:

- added a comment why the change is fine
- removed the Link: trailer

 date.c          | 14 +++++++++-----
 t/t0006-date.sh |  1 +
 2 files changed, 10 insertions(+), 5 deletions(-)

Comments

Junio C Hamano March 13, 2024, 10:42 p.m. UTC | #1
"Beat Bolli" <bb@drbeat.li> writes:

> ISO 8601-1:2020-12 specifies that a zero timezone offset must be denoted
> with a "Z" suffix instead of the numeric "+00:00". Add the correponding
> special case to show_date() and a new test.
>
> This changes an established output format which might be depended on by
> scripts. The original patch 466fb6742d7f (pretty: provide a strict ISO
> 8601 date format, 2014-08-29) mentioned XML parsers as its rationale,
> which generally have good parsing support, so this change should be
> fine.

"fine." -> "fine for that particular usecase."

Unlike in 2005, we no longer write our features only for our own
single use case that motivated it.  I do not think it is possible
to make this change without breaking some real script, and admitting
this is a breaking change and we are knowingly doing so is probably
better in the longer term.

Saying "this should be fine" in the log will give future developers
room to consider reverting it, and while they are free to make such
a decision based on the reality at their time in the future, we
should give them a data point from our point of view: we know it may
break somebody but we are still doing so knowingly as upside to
adhere to a published standard and help those users who adhere to
the same standard is more valuable then the unfortunate script that
bended themselves to match our earlier mistake.

Thanks.
diff mbox series

Patch

diff --git a/date.c b/date.c
index 619ada5b2044..44cf2221d81f 100644
--- a/date.c
+++ b/date.c
@@ -342,14 +342,18 @@  const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
 				tm->tm_hour, tm->tm_min, tm->tm_sec,
 				tz);
 	else if (mode->type == DATE_ISO8601_STRICT) {
-		char sign = (tz >= 0) ? '+' : '-';
-		tz = abs(tz);
-		strbuf_addf(&timebuf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
+		strbuf_addf(&timebuf, "%04d-%02d-%02dT%02d:%02d:%02d",
 				tm->tm_year + 1900,
 				tm->tm_mon + 1,
 				tm->tm_mday,
-				tm->tm_hour, tm->tm_min, tm->tm_sec,
-				sign, tz / 100, tz % 100);
+				tm->tm_hour, tm->tm_min, tm->tm_sec);
+		if (tz == 0) {
+			strbuf_addch(&timebuf, 'Z');
+		} else {
+			strbuf_addch(&timebuf, tz >= 0 ? '+' : '-');
+			tz = abs(tz);
+			strbuf_addf(&timebuf, "%02d:%02d", tz / 100, tz % 100);
+		}
 	} else if (mode->type == DATE_RFC2822)
 		strbuf_addf(&timebuf, "%.3s, %d %.3s %d %02d:%02d:%02d %+05d",
 			weekday_names[tm->tm_wday], tm->tm_mday,
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index e18b1602864e..1d228a981ee9 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -46,6 +46,7 @@  check_show () {
 TIME='1466000000 +0200'
 check_show iso8601 "$TIME" '2016-06-15 16:13:20 +0200'
 check_show iso8601-strict "$TIME" '2016-06-15T16:13:20+02:00'
+check_show iso8601-strict "$(echo "$TIME" | sed 's/+0200$/+0000/')" '2016-06-15T14:13:20Z'
 check_show rfc2822 "$TIME" 'Wed, 15 Jun 2016 16:13:20 +0200'
 check_show short "$TIME" '2016-06-15'
 check_show default "$TIME" 'Wed Jun 15 16:13:20 2016 +0200'