{"thread":{"id":"37446","subject":"[PATCH v2] pretty: Provide a strict ISO8601 date format","startedAt":"2014-08-29T16:58:42Z","lastAt":"2014-08-29T22:12:07Z","messageCount":7,"participants":["Beat Bolli","Junio C Hamano","Andreas Schwab","Jeff King"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"248561","messageId":"1409331522-8457-1-git-send-email-bbolli@ewanet.ch","threadId":"37446","inReplyTo":null,"subject":"[PATCH v2] pretty: Provide a strict ISO8601 date format","fromName":"Beat Bolli","fromEmail":"bbolli@ewanet.ch","sentAt":"2014-08-29T16:58:42Z","receivedAt":"2014-08-29T16:58:42Z","isPatch":true,"sender":{"key":"bbolli@ewanet.ch","avatar":"https://avatars.githubusercontent.com/u/21444?v=4"},"body":"There has been concern that Git's \"ISO\" date format does not really\nconform to the ISO 8601 standard. Thus, it cannot be parsed by\nISO 8601 compliant parsers, e.g. those of XML toolchains.\n\nThe differences between the two formats are the following:\n  - a space instead of the `T` date/time delimiter\n  - a space between time and time zone\n  - no colon between hours and minutes of the time zone\n\nThis commit adds a strict ISO 8601 date format for displaying committer\nand author dates. It uses the '%aI' and '%cI' format specifiers (note\nthe uppercase 'I') and the '--date=iso-strict' or\n'--date=iso8601-strict' date format names.\n\nSee http://thread.gmane.org/gmane.comp.version-control.git/255879 and\nhttp://thread.gmane.org/gmane.comp.version-control.git/52414/focus=52585\nfor discussion.\n\nSigned-off-by: Beat Bolli <bbolli@ewanet.ch>\n---\n\nv2:\n  - Improve commit message\n  - Fix time zone display for negative values close to zero\n\n Documentation/git-rev-list.txt     |  2 +-\n Documentation/pretty-formats.txt   |  6 ++++--\n Documentation/rev-list-options.txt | 13 +++++++++++--\n cache.h                            |  1 +\n date.c                             | 14 +++++++++++++-\n pretty.c                           |  5 ++++-\n t/t4205-log-pretty-formats.sh      |  7 +++++++\n 7 files changed, 41 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt\nindex 7a1585d..fd7f8b5 100644\n--- a/Documentation/git-rev-list.txt\n+++ b/Documentation/git-rev-list.txt\n@@ -45,7 +45,7 @@ SYNOPSIS\n \t     [ \\--regexp-ignore-case | -i ]\n \t     [ \\--extended-regexp | -E ]\n \t     [ \\--fixed-strings | -F ]\n-\t     [ \\--date=(local|relative|default|iso|rfc|short) ]\n+\t     [ \\--date=(local|relative|default|iso|iso-strict|rfc|short) ]\n \t     [ [\\--objects | \\--objects-edge] [ \\--unpacked ] ]\n \t     [ \\--pretty | \\--header ]\n \t     [ \\--bisect ]\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 85d6353..50a2c30 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -115,7 +115,8 @@ The placeholders are:\n - '%aD': author date, RFC2822 style\n - '%ar': author date, relative\n - '%at': author date, UNIX timestamp\n-- '%ai': author date, ISO 8601 format\n+- '%ai': author date, ISO 8601-like format\n+- '%aI': author date, strict ISO 8601 format\n - '%cn': committer name\n - '%cN': committer name (respecting .mailmap, see\n   linkgit:git-shortlog[1] or linkgit:git-blame[1])\n@@ -126,7 +127,8 @@ The placeholders are:\n - '%cD': committer date, RFC2822 style\n - '%cr': committer date, relative\n - '%ct': committer date, UNIX timestamp\n-- '%ci': committer date, ISO 8601 format\n+- '%ci': committer date, ISO 8601-like format\n+- '%cI': committer date, strict ISO 8601 format\n - '%d': ref names, like the --decorate option of linkgit:git-log[1]\n - '%e': encoding\n - '%s': subject\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex deb8cca..5d311b8 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -677,7 +677,7 @@ include::pretty-options.txt[]\n --relative-date::\n \tSynonym for `--date=relative`.\n \n---date=(relative|local|default|iso|rfc|short|raw)::\n+--date=(relative|local|default|iso|iso-strict|rfc|short|raw)::\n \tOnly takes effect for dates shown in human-readable format, such\n \tas when using `--pretty`. `log.date` config variable sets a default\n \tvalue for the log command's `--date` option.\n@@ -687,7 +687,16 @@ e.g. ``2 hours ago''.\n +\n `--date=local` shows timestamps in user's local time zone.\n +\n-`--date=iso` (or `--date=iso8601`) shows timestamps in ISO 8601 format.\n+`--date=iso` (or `--date=iso8601`) shows timestamps in a ISO 8601-like format.\n+The differences to the strict ISO 8601 format are:\n+\n+\t- a space instead of the `T` date/time delimiter\n+\t- a space between time and time zone\n+\t- no colon between hours and minutes of the time zone\n+\n++\n+`--date=iso-strict` (or `--date=iso8601-strict`) shows timestamps in strict\n+ISO 8601 format.\n +\n `--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822\n format, often found in email messages.\ndiff --git a/cache.h b/cache.h\nindex fcb511d..fa92aaf 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1037,6 +1037,7 @@ enum date_mode {\n \tDATE_SHORT,\n \tDATE_LOCAL,\n \tDATE_ISO8601,\n+\tDATE_ISO8601_STRICT,\n \tDATE_RFC2822,\n \tDATE_RAW\n };\ndiff --git a/date.c b/date.c\nindex 782de95..5d73d9b 100644\n--- a/date.c\n+++ b/date.c\n@@ -200,7 +200,16 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)\n \t\t\t\ttm->tm_mday,\n \t\t\t\ttm->tm_hour, tm->tm_min, tm->tm_sec,\n \t\t\t\ttz);\n-\telse if (mode == DATE_RFC2822)\n+\telse if (mode == DATE_ISO8601_STRICT) {\n+\t\tchar sign = (tz >= 0) ? '+' : '-';\n+\t\ttz = abs(tz);\n+\t\tstrbuf_addf(&timebuf, \"%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d\",\n+\t\t\t\ttm->tm_year + 1900,\n+\t\t\t\ttm->tm_mon + 1,\n+\t\t\t\ttm->tm_mday,\n+\t\t\t\ttm->tm_hour, tm->tm_min, tm->tm_sec,\n+\t\t\t\tsign, tz / 100, tz % 100);\n+\t} else if (mode == DATE_RFC2822)\n \t\tstrbuf_addf(&timebuf, \"%.3s, %d %.3s %d %02d:%02d:%02d %+05d\",\n \t\t\tweekday_names[tm->tm_wday], tm->tm_mday,\n \t\t\tmonth_names[tm->tm_mon], tm->tm_year + 1900,\n@@ -751,6 +760,9 @@ enum date_mode parse_date_format(const char *format)\n \telse if (!strcmp(format, \"iso8601\") ||\n \t\t !strcmp(format, \"iso\"))\n \t\treturn DATE_ISO8601;\n+\telse if (!strcmp(format, \"iso8601-strict\") ||\n+\t\t !strcmp(format, \"iso-strict\"))\n+\t\treturn DATE_ISO8601_STRICT;\n \telse if (!strcmp(format, \"rfc2822\") ||\n \t\t !strcmp(format, \"rfc\"))\n \t\treturn DATE_RFC2822;\ndiff --git a/pretty.c b/pretty.c\nindex 3a1da6f..7dd5601 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -731,9 +731,12 @@ static size_t format_person_part(struct strbuf *sb, char part,\n \tcase 'r':\t/* date, relative */\n \t\tstrbuf_addstr(sb, show_ident_date(&s, DATE_RELATIVE));\n \t\treturn placeholder_len;\n-\tcase 'i':\t/* date, ISO 8601 */\n+\tcase 'i':\t/* date, ISO 8601-like */\n \t\tstrbuf_addstr(sb, show_ident_date(&s, DATE_ISO8601));\n \t\treturn placeholder_len;\n+\tcase 'I':\t/* date, ISO 8601 strict */\n+\t\tstrbuf_addstr(sb, show_ident_date(&s, DATE_ISO8601_STRICT));\n+\t\treturn placeholder_len;\n \t}\n \n skip:\ndiff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh\nindex 349c531..aad7a80 100755\n--- a/t/t4205-log-pretty-formats.sh\n+++ b/t/t4205-log-pretty-formats.sh\n@@ -431,6 +431,13 @@ EOF\n \ttest_cmp expected actual\n '\n \n+# ISO strict date format\n+test_expect_success 'ISO and ISO-strict date formats display the same values' '\n+\tgit log --format=%ai%n%ci | sed -e \"s/ /T/; s/ //; s/..\\$/:&/\" >expected &&\n+\tgit log --format=%aI%n%cI >actual &&\n+\ttest_cmp expected actual\n+'\n+\n # get new digests (with no abbreviations)\n head1=$(git rev-parse --verify HEAD~0) &&\n head2=$(git rev-parse --verify HEAD~1) &&\n-- \n2.1.0\n"},{"id":"248577","messageId":"xmqqwq9r5dhb.fsf@gitster.dls.corp.google.com","threadId":"37446","inReplyTo":"1409331522-8457-1-git-send-email-bbolli@ewanet.ch","subject":"Re: [PATCH v2] pretty: Provide a strict ISO8601 date format","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-08-29T18:59:12Z","receivedAt":"2014-08-29T18:59:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Beat Bolli <bbolli@ewanet.ch> writes:\n\n> Subject: Re: [PATCH v2] pretty: Provide a strict ISO8601 date format\n\n\"pretty: add --date=iso-strict, a strict ISO-8601 date format\"\n\n> The differences between the two formats are the following:\n\n\"The --date=iso format Git uses deviates from ISO-8601 in these\nways\" may make it clear which one has \"T\" and which doesn't.\n\n>   - a space instead of the `T` date/time delimiter\n>   - a space between time and time zone\n>   - no colon between hours and minutes of the time zone\n\n> This commit adds a strict ISO 8601 date format for displaying committer\n> and author dates. It uses the '%aI' and '%cI' format specifiers (note\n> the uppercase 'I') and the '--date=iso-strict' or\n> '--date=iso8601-strict' date format names.\n\n\"Add a .... author dates. Use '%aI' and '%cI' format specifiers ...\".\n\n> See http://thread.gmane.org/gmane.comp.version-control.git/255879 and\n> http://thread.gmane.org/gmane.comp.version-control.git/52414/focus=52585\n> for discussion.\n\nThanks for the pointers, especially for the older one.\n\n> +\telse if (mode == DATE_ISO8601_STRICT) {\n> +\t\tchar sign = (tz >= 0) ? '+' : '-';\n> +\t\ttz = abs(tz);\n> +\t\tstrbuf_addf(&timebuf, \"%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d\",\n> +\t\t\t\ttm->tm_year + 1900,\n> +\t\t\t\ttm->tm_mon + 1,\n> +\t\t\t\ttm->tm_mday,\n> +\t\t\t\ttm->tm_hour, tm->tm_min, tm->tm_sec,\n> +\t\t\t\tsign, tz / 100, tz % 100);\n\nOK.\n\n> +# ISO strict date format\n> +test_expect_success 'ISO and ISO-strict date formats display the same values' '\n> +\tgit log --format=%ai%n%ci | sed -e \"s/ /T/; s/ //; s/..\\$/:&/\" >expected &&\n> +\tgit log --format=%aI%n%cI >actual &&\n> +\ttest_cmp expected actual\n> +'\n\nThis is saying that as long as --date=iso-strict format is\nbug-to-bug compatible with --date=iso format it is OK.\n\nWhich is fine, especially knowing the implementation ;-)\n\n> +\n>  # get new digests (with no abbreviations)\n>  head1=$(git rev-parse --verify HEAD~0) &&\n>  head2=$(git rev-parse --verify HEAD~1) &&\n"},{"id":"248578","messageId":"xmqqppfj5d8f.fsf@gitster.dls.corp.google.com","threadId":"37446","inReplyTo":"xmqqwq9r5dhb.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2] pretty: Provide a strict ISO8601 date format","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-08-29T19:04:32Z","receivedAt":"2014-08-29T19:04:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I've queued with this fix squashed in.\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 17d30d0..f9e6481 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -2580,6 +2580,9 @@ parse_done:\n \tcase DATE_RFC2822:\n \t\tblame_date_width = sizeof(\"Thu, 19 Oct 2006 16:00:04 -0700\");\n \t\tbreak;\n+\tcase DATE_ISO8601_STRICT:\n+\t\tblame_date_width = sizeof(\"2006-10-19T16:00:04-0700\");\n+\t\tbreak;\n \tcase DATE_ISO8601:\n \t\tblame_date_width = sizeof(\"2006-10-19 16:00:04 -0700\");\n \t\tbreak;\n"},{"id":"248581","messageId":"87tx4vnl8o.fsf@igel.home","threadId":"37446","inReplyTo":"xmqqppfj5d8f.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2] pretty: Provide a strict ISO8601 date format","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2014-08-29T19:34:15Z","receivedAt":"2014-08-29T19:34:15Z","isPatch":true,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I've queued with this fix squashed in.\n>\n> diff --git a/builtin/blame.c b/builtin/blame.c\n> index 17d30d0..f9e6481 100644\n> --- a/builtin/blame.c\n> +++ b/builtin/blame.c\n> @@ -2580,6 +2580,9 @@ parse_done:\n>  \tcase DATE_RFC2822:\n>  \t\tblame_date_width = sizeof(\"Thu, 19 Oct 2006 16:00:04 -0700\");\n>  \t\tbreak;\n> +\tcase DATE_ISO8601_STRICT:\n> +\t\tblame_date_width = sizeof(\"2006-10-19T16:00:04-0700\");\n\nITYM ...-07:00\n\nAndreas.\n\n-- \nAndreas Schwab, schwab@linux-m68k.org\nGPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n\"And now for something completely different.\"\n"},{"id":"248592","messageId":"5400EA6C.3030504@ewanet.ch","threadId":"37446","inReplyTo":"xmqqwq9r5dhb.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2] pretty: Provide a strict ISO8601 date format","fromName":"Beat Bolli","fromEmail":"bbolli@ewanet.ch","sentAt":"2014-08-29T21:02:36Z","receivedAt":"2014-08-29T21:02:36Z","isPatch":true,"sender":{"key":"bbolli@ewanet.ch","avatar":"https://avatars.githubusercontent.com/u/21444?v=4"},"body":"On 29.08.14 20:59, Junio C Hamano wrote:\n>> +# ISO strict date format\n>> +test_expect_success 'ISO and ISO-strict date formats display the same values' '\n>> +\tgit log --format=%ai%n%ci | sed -e \"s/ /T/; s/ //; s/..\\$/:&/\" >expected &&\n>> +\tgit log --format=%aI%n%cI >actual &&\n>> +\ttest_cmp expected actual\n>> +'\n> \n> This is saying that as long as --date=iso-strict format is\n> bug-to-bug compatible with --date=iso format it is OK.\n> \n> Which is fine, especially knowing the implementation ;-)\n> \n\nYeah, I wasn't sure how to test this, since the commit dates change with\neach test run. Maybe it's the easy way out, but on the other hand it's\nbetter than no test at all. Check the known parts with a regex?\n\nThanks,\nBeat\n-- \nmail: echo '<bNbolOli@ewaSPnetAM.ch>' | tr -d '[A-S]'\npgp: 0x506A903A; 49D5 794A EA77 F907 764F  D89E 304B 93CF 506A 903A\ngsm: 4.7.7.6.0.7.7.9.7.1.4.e164.arpa\nicbm: 47.0452 N, 7.2715 E\n\n\"It takes love over gold, and mind over matter\" -- Dire Straits\n\n"},{"id":"248593","messageId":"5400F112.6030300@ewanet.ch","threadId":"37446","inReplyTo":"xmqqppfj5d8f.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2] pretty: Provide a strict ISO8601 date format","fromName":"Beat Bolli","fromEmail":"bbolli@ewanet.ch","sentAt":"2014-08-29T21:30:58Z","receivedAt":"2014-08-29T21:30:58Z","isPatch":true,"sender":{"key":"bbolli@ewanet.ch","avatar":"https://avatars.githubusercontent.com/u/21444?v=4"},"body":"On 29.08.14 21:04, Junio C Hamano wrote:\n> I've queued with this fix squashed in.\n\nOops, I just sent v3 with your latest fixes as well. Please ignore it.\n\n\nThanks,\nBeat\n-- \nmail: echo '<bNbolOli@ewaSPnetAM.ch>' | tr -d '[A-S]'\npgp: 0x506A903A; 49D5 794A EA77 F907 764F  D89E 304B 93CF 506A 903A\ngsm: 4.7.7.6.0.7.7.9.7.1.4.e164.arpa\nicbm: 47.0452 N, 7.2715 E\n\n\"It takes love over gold, and mind over matter\" -- Dire Straits\n\n"},{"id":"248596","messageId":"20140829221206.GB24834@peff.net","threadId":"37446","inReplyTo":"5400EA6C.3030504@ewanet.ch","subject":"Re: [PATCH v2] pretty: Provide a strict ISO8601 date format","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-08-29T22:12:07Z","receivedAt":"2014-08-29T22:12:07Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Aug 29, 2014 at 11:02:36PM +0200, Beat Bolli wrote:\n\n> On 29.08.14 20:59, Junio C Hamano wrote:\n> >> +# ISO strict date format\n> >> +test_expect_success 'ISO and ISO-strict date formats display the same values' '\n> >> +\tgit log --format=%ai%n%ci | sed -e \"s/ /T/; s/ //; s/..\\$/:&/\" >expected &&\n> >> +\tgit log --format=%aI%n%cI >actual &&\n> >> +\ttest_cmp expected actual\n> >> +'\n> > \n> > This is saying that as long as --date=iso-strict format is\n> > bug-to-bug compatible with --date=iso format it is OK.\n> > \n> > Which is fine, especially knowing the implementation ;-)\n> > \n> \n> Yeah, I wasn't sure how to test this, since the commit dates change with\n> each test run. Maybe it's the easy way out, but on the other hand it's\n> better than no test at all. Check the known parts with a regex?\n\nIf you use test_tick (or test_commit, which calls it), the timestamps\nare stable from run to run of the tests.\n\n-Peff\n"}]}