{"thread":{"id":"48836","subject":"[RFC PATCH] Add 'human' date format","startedAt":"2018-07-07T19:39:05Z","lastAt":"2018-11-27T04:10:15Z","messageCount":14,"participants":["Linus Torvalds","Andrei Rybak","Junio C Hamano","Ævar Arnfjörð Bjarmason","Stephen P. Smith"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"351851","messageId":"alpine.LFD.2.21.999.1807071238410.18818@i7.lan","threadId":"48836","inReplyTo":null,"subject":"[RFC PATCH] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-07T19:38:59Z","receivedAt":"2018-07-07T19:39:05Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\n\nThis adds --date=human, which skips the timezone if it matches the\ncurrent time-zone, and doesn't print the whole date if that matches (ie\nskip printing year for dates that are \"this year\", but also skip the\nwhole date itself if it's in the last few days and we can just say what\nweekday it was).\n\nFor really recent dates (within the last hour), use the relative date\nstamp.\n\nAlso add 'auto' date mode, which defaults to human if we're using the\npager.  So you can do\n\n\tgit config --add log.date auto\n\nand your \"git log\" commands will show the human-legible format unless\nyou're scripting things.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n\nOk, I tried something like this long long ago, but that was a fairly nasty \npatch that just defaulted to \"--date=relative\" for recent dates, and then \ndid the usual default for anything else.\n\nBut the issue kept bugging me, and this is a slightly more sane model (?). \nIt keeps the notion of \"let's use --date=relative for very recent dates\", \nbut for anything that is more than an hour old, it just uses a simplified \ndate.\n\nFor example, for time stamps that are \"today\", just show the time. And if \nthe year or the time zone matches the current year or timezone, skip them.  \nAnd don't bother showing seconds, because humans won't care.\n\nThe end result is a slightly simplified view.\n\nSo for example, the date for this commit right now looks like\n\n    Date:   Sat Jul 7 12:21:26 2018 -0700\n\nto me, but with \"--date=human\", right now it just says\n\n    Date:   12:21\n\n(and maybe for a US locale, I should make it do the AM/PM thing).\n\nThis is marked RFC because\n\n (a) maybe I'm the only one who has ever wanted the simplified dates\n\n (b) the simplification rules themselves might be worthy of discussion.\n\nFor example, I also simplified the \"a couple of days ago\" case, so that it \nshows\n\n    Date:   Fri 19:45\n\nfor one of my kernel commits that happened yesterday. The date didn't \nmatch _exactly_, but it's the same month, and just a few days ago, so it \njust shows the weekday. Is that easier to read? Maybe. I kind of like it.\n\n\n builtin/blame.c |   1 +\n cache.h         |   1 +\n date.c          | 139 +++++++++++++++++++++++++++++++++++++-----------\n 3 files changed, 110 insertions(+), 31 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 5a0388aae..27c64b1c8 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -917,6 +917,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t */\n \t\tblame_date_width = utf8_strwidth(_(\"4 years, 11 months ago\")) + 1; /* add the null */\n \t\tbreak;\n+\tcase DATE_HUMAN:\n \tcase DATE_NORMAL:\n \t\tblame_date_width = sizeof(\"Thu Oct 19 16:00:04 2006 -0700\");\n \t\tbreak;\ndiff --git a/cache.h b/cache.h\nindex d49092d94..8a6810ee6 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1428,6 +1428,7 @@ extern struct object *peel_to_type(const char *name, int namelen,\n struct date_mode {\n \tenum date_mode_type {\n \t\tDATE_NORMAL = 0,\n+\t\tDATE_HUMAN,\n \t\tDATE_RELATIVE,\n \t\tDATE_SHORT,\n \t\tDATE_ISO8601,\ndiff --git a/date.c b/date.c\nindex 49f943e25..9809ac334 100644\n--- a/date.c\n+++ b/date.c\n@@ -77,22 +77,16 @@ static struct tm *time_to_tm_local(timestamp_t time)\n }\n \n /*\n- * What value of \"tz\" was in effect back then at \"time\" in the\n- * local timezone?\n+ * Fill in the localtime 'struct tm' for the supplied time,\n+ * and return the local tz.\n  */\n-static int local_tzoffset(timestamp_t time)\n+static int local_time_tzoffset(time_t t, struct tm *tm)\n {\n-\ttime_t t, t_local;\n-\tstruct tm tm;\n+\ttime_t t_local;\n \tint offset, eastwest;\n \n-\tif (date_overflows(time))\n-\t\tdie(\"Timestamp too large for this system: %\"PRItime, time);\n-\n-\tt = (time_t)time;\n-\tlocaltime_r(&t, &tm);\n-\tt_local = tm_to_time_t(&tm);\n-\n+\tlocaltime_r(&t, tm);\n+\tt_local = tm_to_time_t(tm);\n \tif (t_local == -1)\n \t\treturn 0; /* error; just use +0000 */\n \tif (t_local < t) {\n@@ -107,6 +101,20 @@ static int local_tzoffset(timestamp_t time)\n \treturn offset * eastwest;\n }\n \n+/*\n+ * What value of \"tz\" was in effect back then at \"time\" in the\n+ * local timezone?\n+ */\n+static int local_tzoffset(timestamp_t time)\n+{\n+\tstruct tm tm;\n+\n+\tif (date_overflows(time))\n+\t\tdie(\"Timestamp too large for this system: %\"PRItime, time);\n+\n+\treturn local_time_tzoffset((time_t)time, &tm);\n+}\n+\n void show_date_relative(timestamp_t time, int tz,\n \t\t\t       const struct timeval *now,\n \t\t\t       struct strbuf *timebuf)\n@@ -191,27 +199,94 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)\n \treturn &mode;\n }\n \n+static void show_date_normal(struct strbuf *buf, struct tm *tm, int tz, struct tm *human_tm, int human_tz, int local)\n+{\n+\tstruct {\n+\t\tunsigned int\tyear:1,\n+\t\t\t\tdate:1,\n+\t\t\t\twday:1,\n+\t\t\t\tseconds:1,\n+\t\t\t\ttz:1;\n+\t} hide = { 0 };\n+\n+\thide.tz = local || tz == human_tz;\n+\thide.year = tm->tm_year == human_tm->tm_year;\n+\tif (hide.year) {\n+\t\tif (tm->tm_mon == human_tm->tm_mon) {\n+\t\t\tif (tm->tm_mday > human_tm->tm_mday) {\n+\t\t\t\t/* Crazy future time */\n+\t\t\t\thide.year = 0;\n+\t\t\t} else if (tm->tm_mday == human_tm->tm_mday) {\n+\t\t\t\thide.date = hide.wday = 1;\n+\t\t\t} else if (tm->tm_mday + 5 > human_tm->tm_mday) {\n+\t\t\t\t/* Leave just weekday if it was a few days ago */\n+\t\t\t\thide.date = 1;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Always hide seconds for human-readable */\n+\thide.seconds = human_tm->tm_year > 0;\n+\n+\tif (!hide.wday)\n+\t\tstrbuf_addf(buf, \"%.3s \", weekday_names[tm->tm_wday]);\n+\tif (!hide.date)\n+\t\tstrbuf_addf(buf, \"%.3s %d \", month_names[tm->tm_mon], tm->tm_mday);\n+\n+\t/* Always show time. Do we want AM/PM depending on locale? */\n+\tstrbuf_addf(buf, \"%02d:%02d\", tm->tm_hour, tm->tm_min);\n+\tif (!hide.seconds)\n+\t\tstrbuf_addf(buf, \":%02d\", tm->tm_sec);\n+\n+\tif (!hide.year)\n+\t\tstrbuf_addf(buf, \" %d\", tm->tm_year + 1900);\n+\n+\tif (!hide.tz)\n+\t\tstrbuf_addf(buf, \" %+05d\", tz);\n+}\n+\n const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n {\n+\tint type = mode->type;\n+\tint local = mode->local;\n \tstruct tm *tm;\n+\tstruct tm human_tm = { 0 };\n+\tint human_tz = -1;\n \tstatic struct strbuf timebuf = STRBUF_INIT;\n \n-\tif (mode->type == DATE_UNIX) {\n+\tif (type == DATE_UNIX) {\n \t\tstrbuf_reset(&timebuf);\n \t\tstrbuf_addf(&timebuf, \"%\"PRItime, time);\n \t\treturn timebuf.buf;\n \t}\n \n-\tif (mode->local)\n+\tif (type == DATE_HUMAN) {\n+\t\tstruct timeval now;\n+\n+\t\tgettimeofday(&now, NULL);\n+\n+\t\t/* Fill in the data for \"current time\" in human_tz and human_tm */\n+\t\thuman_tz = local_time_tzoffset(now.tv_sec, &human_tm);\n+\n+\t\t/* Special case: if it's less than an hour ago, use relative time */\n+\t\tif (time - now.tv_sec < 60 * 60)\n+\t\t\ttype = DATE_RELATIVE;\n+\n+\t\t/* Don't print timezone if it matches */\n+\t\tif (tz == human_tz)\n+\t\t\tlocal = 1;\n+\t}\n+\n+\tif (local)\n \t\ttz = local_tzoffset(time);\n \n-\tif (mode->type == DATE_RAW) {\n+\tif (type == DATE_RAW) {\n \t\tstrbuf_reset(&timebuf);\n \t\tstrbuf_addf(&timebuf, \"%\"PRItime\" %+05d\", time, tz);\n \t\treturn timebuf.buf;\n \t}\n \n-\tif (mode->type == DATE_RELATIVE) {\n+\tif (type == DATE_RELATIVE) {\n \t\tstruct timeval now;\n \n \t\tstrbuf_reset(&timebuf);\n@@ -220,7 +295,7 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n \t\treturn timebuf.buf;\n \t}\n \n-\tif (mode->local)\n+\tif (local)\n \t\ttm = time_to_tm_local(time);\n \telse\n \t\ttm = time_to_tm(time, tz);\n@@ -230,17 +305,17 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n \t}\n \n \tstrbuf_reset(&timebuf);\n-\tif (mode->type == DATE_SHORT)\n+\tif (type == DATE_SHORT)\n \t\tstrbuf_addf(&timebuf, \"%04d-%02d-%02d\", tm->tm_year + 1900,\n \t\t\t\ttm->tm_mon + 1, tm->tm_mday);\n-\telse if (mode->type == DATE_ISO8601)\n+\telse if (type == DATE_ISO8601)\n \t\tstrbuf_addf(&timebuf, \"%04d-%02d-%02d %02d:%02d:%02d %+05d\",\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\ttz);\n-\telse if (mode->type == DATE_ISO8601_STRICT) {\n+\telse if (type == 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@@ -249,23 +324,16 @@ const char *show_date(timestamp_t time, int tz, const struct 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\tsign, tz / 100, tz % 100);\n-\t} else if (mode->type == DATE_RFC2822)\n+\t} else if (type == 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 \t\t\ttm->tm_hour, tm->tm_min, tm->tm_sec, tz);\n-\telse if (mode->type == DATE_STRFTIME)\n+\telse if (type == DATE_STRFTIME)\n \t\tstrbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,\n-\t\t\t\t!mode->local);\n+\t\t\t\t!local);\n \telse\n-\t\tstrbuf_addf(&timebuf, \"%.3s %.3s %d %02d:%02d:%02d %d%c%+05d\",\n-\t\t\t\tweekday_names[tm->tm_wday],\n-\t\t\t\tmonth_names[tm->tm_mon],\n-\t\t\t\ttm->tm_mday,\n-\t\t\t\ttm->tm_hour, tm->tm_min, tm->tm_sec,\n-\t\t\t\ttm->tm_year + 1900,\n-\t\t\t\tmode->local ? 0 : ' ',\n-\t\t\t\ttz);\n+\t\tshow_date_normal(&timebuf, tm, tz, &human_tm, human_tz, local);\n \treturn timebuf.buf;\n }\n \n@@ -802,6 +870,11 @@ int parse_date(const char *date, struct strbuf *result)\n \treturn 0;\n }\n \n+static int auto_date_style(void)\n+{\n+\treturn (isatty(1) || pager_in_use()) ? DATE_HUMAN : DATE_NORMAL;\n+}\n+\n static enum date_mode_type parse_date_type(const char *format, const char **end)\n {\n \tif (skip_prefix(format, \"relative\", end))\n@@ -819,6 +892,10 @@ static enum date_mode_type parse_date_type(const char *format, const char **end)\n \t\treturn DATE_SHORT;\n \tif (skip_prefix(format, \"default\", end))\n \t\treturn DATE_NORMAL;\n+\tif (skip_prefix(format, \"human\", end))\n+\t\treturn DATE_HUMAN;\n+\tif (skip_prefix(format, \"auto\", end))\n+\t\treturn auto_date_style();\n \tif (skip_prefix(format, \"raw\", end))\n \t\treturn DATE_RAW;\n \tif (skip_prefix(format, \"unix\", end))\n-- \n2.18.0.131.gc3213e20f.dirty\n\n"},{"id":"351852","messageId":"CA+55aFyh4=Udhfn+L__9MiCbjqSLTWBGaAvDOPg5EJWs-DjjPQ@mail.gmail.com","threadId":"48836","inReplyTo":"alpine.LFD.2.21.999.1807071238410.18818@i7.lan","subject":"Re: [RFC PATCH] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-07T19:58:32Z","receivedAt":"2018-07-07T19:58:47Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Sat, Jul 7, 2018 at 12:39 PM Linus Torvalds\n<torvalds@linux-foundation.org> wrote:\n> to me, but with \"--date=human\", right now it just says\n>\n>     Date:   12:21\n\nSide note: this is probably my least favorite of the formats.\n\nI'm playing with making all \"today\" dates just use the relative\nformat, and then the \"a couple of days ago\" dates would then have the\n\n>     Date:   Fri 19:45\n\nformat.\n\nBut since it's _explicitly_ about a \"human legible\" format, I think\nthe format could be a bit fluid, and things like that might be tweaked\nlater. Anybody who would script this would be crazy.\n\nI'm more looking for \"no, that's just stupid\" comments, or \"no, you're\nnot the only one who has wanted this\" kinds of replies.\n\n                  Linus\n"},{"id":"351853","messageId":"CA+55aFy=rUvt8kV==Zxvc02zaTQpd=Zc0p6dMN=vHvvoYE4bYw@mail.gmail.com","threadId":"48836","inReplyTo":"CA+55aFyh4=Udhfn+L__9MiCbjqSLTWBGaAvDOPg5EJWs-DjjPQ@mail.gmail.com","subject":"Re: [RFC PATCH] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-07T20:12:33Z","receivedAt":"2018-07-07T20:12:48Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Sat, Jul 7, 2018 at 12:58 PM Linus Torvalds\n<torvalds@linux-foundation.org> wrote:\n>\n> I'm playing with making all \"today\" dates just use the relative\n> format.\n\nHere's the incremental patch for that if people want to compare the output.\n\nWith this, you never get the \"just time\" case, because that will turn\ninto \"2 hours ago\" or similar. But you will get \"Fri 19:45\" for\nsomething that happened yesterday.\n\nSo examples from my kernel logs look something like this:\n\n  2 hours ago\n  Fri 19:45\n  Fri 10:44 +1000\n  Fri Jun 22 15:46\n  Tue Jun 19 15:41 -0600\n  Thu Jun 15 12:57 2017 +0300\n\ndepending on how long ago they were and whether they were in the same\ntimezone etc.\n\n              Linus\n\n\n date.c | 16 ++++++++++------\n 1 file changed, 10 insertions(+), 6 deletions(-)\n\ndiff --git a/date.c b/date.c\nindex 9809ac334..de0b03cf4 100644\n--- a/date.c\n+++ b/date.c\n@@ -199,7 +199,7 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)\n \treturn &mode;\n }\n \n-static void show_date_normal(struct strbuf *buf, struct tm *tm, int tz, struct tm *human_tm, int human_tz, int local)\n+static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm, int tz, struct tm *human_tm, int human_tz, int local)\n {\n \tstruct {\n \t\tunsigned int\tyear:1,\n@@ -225,6 +225,14 @@ static void show_date_normal(struct strbuf *buf, struct tm *tm, int tz, struct t\n \t\t}\n \t}\n \n+\t/* Show \"today\" times as just relative times */\n+\tif (hide.wday) {\n+\t\tstruct timeval now;\n+\t\tgettimeofday(&now, NULL);\n+\t\tshow_date_relative(time, tz, &now, buf);\n+\t\treturn;\n+\t}\n+\n \t/* Always hide seconds for human-readable */\n \thide.seconds = human_tm->tm_year > 0;\n \n@@ -268,10 +276,6 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n \t\t/* Fill in the data for \"current time\" in human_tz and human_tm */\n \t\thuman_tz = local_time_tzoffset(now.tv_sec, &human_tm);\n \n-\t\t/* Special case: if it's less than an hour ago, use relative time */\n-\t\tif (time - now.tv_sec < 60 * 60)\n-\t\t\ttype = DATE_RELATIVE;\n-\n \t\t/* Don't print timezone if it matches */\n \t\tif (tz == human_tz)\n \t\t\tlocal = 1;\n@@ -333,7 +337,7 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n \t\tstrbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,\n \t\t\t\t!local);\n \telse\n-\t\tshow_date_normal(&timebuf, tm, tz, &human_tm, human_tz, local);\n+\t\tshow_date_normal(&timebuf, time, tm, tz, &human_tm, human_tz, local);\n \treturn timebuf.buf;\n }\n \n"},{"id":"351858","messageId":"alpine.LFD.2.21.999.1807071502260.18818@i7.lan","threadId":"48836","inReplyTo":"alpine.LFD.2.21.999.1807071238410.18818@i7.lan","subject":"[RFC PATCH v2] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-07T22:02:35Z","receivedAt":"2018-07-07T22:02:42Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\n\nThis adds --date=human, which skips the timezone if it matches the\ncurrent time-zone, and doesn't print the whole date if that matches (ie\nskip printing year for dates that are \"this year\", but also skip the\nwhole date itself if it's in the last few days and we can just say what\nweekday it was).\n\nFor really recent dates (same day), use the relative date stamp, while\nfor old dates (year doesn't match), don't bother with time and timezone.\n\nAlso add 'auto' date mode, which defaults to human if we're using the\npager.  So you can do\n\n\tgit config --add log.date auto\n\nand your \"git log\" commands will show the human-legible format unless\nyou're scripting things.\n\nNote that this time format still shows the timezone for recent enough\nevents (but not so recent that they show up as relative dates).  You can\ncombine it with the \"-local\" suffix to never show timezones for an even\nmore simplified view.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n\nSlightly updated version after playing with this more. \n\nThis tries to make the length somewhat more consistent (and shorter), \nwhich came about when looking at this in \"git blame\" output. \n\nOnce you're talking \"last year\" patches, you don't tend to care about time \nof day or timezone. So the longest date is basically \"Thu Oct 19 16:00\", \nbecause if you show the year (four characters), you don't show the time \n(five characters). And the timezone (five characters) is only shown if not \nshowing the date (5-6 characters).\n\nAlso, because the relative time is now handled entirely inside the \nshow_date_normal() function, I could undo some of the changes to \nshow_date() that were updating date->mode and date->local. So the patch \nhas actually shrunk a bit, I think.\n\n builtin/blame.c |   4 ++\n cache.h         |   1 +\n date.c          | 130 ++++++++++++++++++++++++++++++++++++++++--------\n 3 files changed, 115 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 5a0388aae..7b6235321 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -917,6 +917,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t */\n \t\tblame_date_width = utf8_strwidth(_(\"4 years, 11 months ago\")) + 1; /* add the null */\n \t\tbreak;\n+\tcase DATE_HUMAN:\n+\t\t/* If the year is shown, no time is shown */\n+\t\tblame_date_width = sizeof(\"Thu Oct 19 16:00\");\n+\t\tbreak;\n \tcase DATE_NORMAL:\n \t\tblame_date_width = sizeof(\"Thu Oct 19 16:00:04 2006 -0700\");\n \t\tbreak;\ndiff --git a/cache.h b/cache.h\nindex d49092d94..8a6810ee6 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1428,6 +1428,7 @@ extern struct object *peel_to_type(const char *name, int namelen,\n struct date_mode {\n \tenum date_mode_type {\n \t\tDATE_NORMAL = 0,\n+\t\tDATE_HUMAN,\n \t\tDATE_RELATIVE,\n \t\tDATE_SHORT,\n \t\tDATE_ISO8601,\ndiff --git a/date.c b/date.c\nindex 49f943e25..4486c028a 100644\n--- a/date.c\n+++ b/date.c\n@@ -77,22 +77,16 @@ static struct tm *time_to_tm_local(timestamp_t time)\n }\n \n /*\n- * What value of \"tz\" was in effect back then at \"time\" in the\n- * local timezone?\n+ * Fill in the localtime 'struct tm' for the supplied time,\n+ * and return the local tz.\n  */\n-static int local_tzoffset(timestamp_t time)\n+static int local_time_tzoffset(time_t t, struct tm *tm)\n {\n-\ttime_t t, t_local;\n-\tstruct tm tm;\n+\ttime_t t_local;\n \tint offset, eastwest;\n \n-\tif (date_overflows(time))\n-\t\tdie(\"Timestamp too large for this system: %\"PRItime, time);\n-\n-\tt = (time_t)time;\n-\tlocaltime_r(&t, &tm);\n-\tt_local = tm_to_time_t(&tm);\n-\n+\tlocaltime_r(&t, tm);\n+\tt_local = tm_to_time_t(tm);\n \tif (t_local == -1)\n \t\treturn 0; /* error; just use +0000 */\n \tif (t_local < t) {\n@@ -107,6 +101,20 @@ static int local_tzoffset(timestamp_t time)\n \treturn offset * eastwest;\n }\n \n+/*\n+ * What value of \"tz\" was in effect back then at \"time\" in the\n+ * local timezone?\n+ */\n+static int local_tzoffset(timestamp_t time)\n+{\n+\tstruct tm tm;\n+\n+\tif (date_overflows(time))\n+\t\tdie(\"Timestamp too large for this system: %\"PRItime, time);\n+\n+\treturn local_time_tzoffset((time_t)time, &tm);\n+}\n+\n void show_date_relative(timestamp_t time, int tz,\n \t\t\t       const struct timeval *now,\n \t\t\t       struct strbuf *timebuf)\n@@ -191,9 +199,80 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)\n \treturn &mode;\n }\n \n+static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm, int tz, struct tm *human_tm, int human_tz, int local)\n+{\n+\tstruct {\n+\t\tunsigned int\tyear:1,\n+\t\t\t\tdate:1,\n+\t\t\t\twday:1,\n+\t\t\t\ttime:1,\n+\t\t\t\tseconds:1,\n+\t\t\t\ttz:1;\n+\t} hide = { 0 };\n+\n+\thide.tz = local || tz == human_tz;\n+\thide.year = tm->tm_year == human_tm->tm_year;\n+\tif (hide.year) {\n+\t\tif (tm->tm_mon == human_tm->tm_mon) {\n+\t\t\tif (tm->tm_mday > human_tm->tm_mday) {\n+\t\t\t\t/* Future date: think timezones */\n+\t\t\t} else if (tm->tm_mday == human_tm->tm_mday) {\n+\t\t\t\thide.date = hide.wday = 1;\n+\t\t\t} else if (tm->tm_mday + 5 > human_tm->tm_mday) {\n+\t\t\t\t/* Leave just weekday if it was a few days ago */\n+\t\t\t\thide.date = 1;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Show \"today\" times as just relative times */\n+\tif (hide.wday) {\n+\t\tstruct timeval now;\n+\t\tgettimeofday(&now, NULL);\n+\t\tshow_date_relative(time, tz, &now, buf);\n+\t\treturn;\n+\t}\n+\n+\t/*\n+\t * Always hide seconds for human-readable.\n+\t * Hide timezone if showing date.\n+\t * Hide weekday and time if showing year.\n+\t *\n+\t * The logic here is two-fold:\n+\t *  (a) only show details when recent enough to matter\n+\t *  (b) keep the maximum length \"similar\", and in check\n+\t */\n+\tif (human_tm->tm_year) {\n+\t\thide.seconds = 1;\n+\t\thide.tz |= !hide.date;\n+\t\thide.wday = hide.time = !hide.year;\n+\t}\n+\n+\tif (!hide.wday)\n+\t\tstrbuf_addf(buf, \"%.3s \", weekday_names[tm->tm_wday]);\n+\tif (!hide.date)\n+\t\tstrbuf_addf(buf, \"%.3s %d \", month_names[tm->tm_mon], tm->tm_mday);\n+\n+\t/* Do we want AM/PM depending on locale? */\n+\tif (!hide.time) {\n+\t\tstrbuf_addf(buf, \"%02d:%02d\", tm->tm_hour, tm->tm_min);\n+\t\tif (!hide.seconds)\n+\t\t\tstrbuf_addf(buf, \":%02d\", tm->tm_sec);\n+\t} else\n+\t\tstrbuf_rtrim(buf);\n+\n+\tif (!hide.year)\n+\t\tstrbuf_addf(buf, \" %d\", tm->tm_year + 1900);\n+\n+\tif (!hide.tz)\n+\t\tstrbuf_addf(buf, \" %+05d\", tz);\n+}\n+\n const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n {\n \tstruct tm *tm;\n+\tstruct tm human_tm = { 0 };\n+\tint human_tz = -1;\n \tstatic struct strbuf timebuf = STRBUF_INIT;\n \n \tif (mode->type == DATE_UNIX) {\n@@ -202,6 +281,15 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n \t\treturn timebuf.buf;\n \t}\n \n+\tif (mode->type == DATE_HUMAN) {\n+\t\tstruct timeval now;\n+\n+\t\tgettimeofday(&now, NULL);\n+\n+\t\t/* Fill in the data for \"current time\" in human_tz and human_tm */\n+\t\thuman_tz = local_time_tzoffset(now.tv_sec, &human_tm);\n+\t}\n+\n \tif (mode->local)\n \t\ttz = local_tzoffset(time);\n \n@@ -258,14 +346,7 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n \t\tstrbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,\n \t\t\t\t!mode->local);\n \telse\n-\t\tstrbuf_addf(&timebuf, \"%.3s %.3s %d %02d:%02d:%02d %d%c%+05d\",\n-\t\t\t\tweekday_names[tm->tm_wday],\n-\t\t\t\tmonth_names[tm->tm_mon],\n-\t\t\t\ttm->tm_mday,\n-\t\t\t\ttm->tm_hour, tm->tm_min, tm->tm_sec,\n-\t\t\t\ttm->tm_year + 1900,\n-\t\t\t\tmode->local ? 0 : ' ',\n-\t\t\t\ttz);\n+\t\tshow_date_normal(&timebuf, time, tm, tz, &human_tm, human_tz, mode->local);\n \treturn timebuf.buf;\n }\n \n@@ -802,6 +883,11 @@ int parse_date(const char *date, struct strbuf *result)\n \treturn 0;\n }\n \n+static int auto_date_style(void)\n+{\n+\treturn (isatty(1) || pager_in_use()) ? DATE_HUMAN : DATE_NORMAL;\n+}\n+\n static enum date_mode_type parse_date_type(const char *format, const char **end)\n {\n \tif (skip_prefix(format, \"relative\", end))\n@@ -819,6 +905,10 @@ static enum date_mode_type parse_date_type(const char *format, const char **end)\n \t\treturn DATE_SHORT;\n \tif (skip_prefix(format, \"default\", end))\n \t\treturn DATE_NORMAL;\n+\tif (skip_prefix(format, \"human\", end))\n+\t\treturn DATE_HUMAN;\n+\tif (skip_prefix(format, \"auto\", end))\n+\t\treturn auto_date_style();\n \tif (skip_prefix(format, \"raw\", end))\n \t\treturn DATE_RAW;\n \tif (skip_prefix(format, \"unix\", end))\n-- \n2.18.0.132.g95eda3d86\n\n"},{"id":"352294","messageId":"CACayv=ifE5BQVtxXCVEhS3uO7iz1z+ZPrF3J_n=e-uoYOpwNtA@mail.gmail.com","threadId":"48836","inReplyTo":"alpine.LFD.2.21.999.1807071502260.18818@i7.lan","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Andrei Rybak","fromEmail":"rybak.a.v@gmail.com","sentAt":"2018-07-11T20:34:19Z","receivedAt":"2018-07-11T20:34:38Z","isPatch":true,"sender":{"key":"rybak.a.v@gmail.com","avatar":"https://avatars.githubusercontent.com/u/624072?v=4"},"body":"On 2018-07-08 00:02, Linus Torvalds wrote:\n> diff --git a/date.c b/date.c\n> index 49f943e25..4486c028a 100644\n> --- a/date.c\n> +++ b/date.c\n> @@ -77,22 +77,16 @@ static struct tm *time_to_tm_local(timestamp_t time)\n>  }\n>\n>  /*\n> - * What value of \"tz\" was in effect back then at \"time\" in the\n> - * local timezone?\n> + * Fill in the localtime 'struct tm' for the supplied time,\n> + * and return the local tz.\n>   */\n> -static int local_tzoffset(timestamp_t time)\n> +static int local_time_tzoffset(time_t t, struct tm *tm)\n>  {\n> -     time_t t, t_local;\n> -     struct tm tm;\n> +     time_t t_local;\n>       int offset, eastwest;\n>\n> -     if (date_overflows(time))\n> -             die(\"Timestamp too large for this system: %\"PRItime, time);\n> -\n> -     t = (time_t)time;\n> -     localtime_r(&t, &tm);\n> -     t_local = tm_to_time_t(&tm);\n> -\n> +     localtime_r(&t, tm);\n> +     t_local = tm_to_time_t(tm);\n>       if (t_local == -1)\n>               return 0; /* error; just use +0000 */\n>       if (t_local < t) {\n> @@ -107,6 +101,20 @@ static int local_tzoffset(timestamp_t time)\n>       return offset * eastwest;\n>  }\n>\n\n[...]\n\n> +\n>  const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n>  {\n>       struct tm *tm;\n> +     struct tm human_tm = { 0 };\n> +     int human_tz = -1;\n\nIs -1 an OK initial value for timezone if local_time_tzoffset returns\nnegative values as well? It looks like it doesn't matter for from functional\n\n>       static struct strbuf timebuf = STRBUF_INIT;\n>\n>       if (mode->type == DATE_UNIX) {\n> @@ -202,6 +281,15 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)\n>               return timebuf.buf;\n>       }\n>\n> +     if (mode->type == DATE_HUMAN) {\n> +             struct timeval now;\n> +\n> +             gettimeofday(&now, NULL);\n> +\n> +             /* Fill in the data for \"current time\" in human_tz and human_tm */\n> +             human_tz = local_time_tzoffset(now.tv_sec, &human_tm);\n> +     }\n> +\n>       if (mode->local)\n>               tz = local_tzoffset(time);\n>\n\n--\nBest regards, Andrei Rybak\n"},{"id":"352295","messageId":"CACayv=jM0Q4x=U+4=_YqJHto_ZdZAz8r89xALOcW5a+n9w=LeA@mail.gmail.com","threadId":"48836","inReplyTo":"CACayv=ifE5BQVtxXCVEhS3uO7iz1z+ZPrF3J_n=e-uoYOpwNtA@mail.gmail.com","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Andrei Rybak","fromEmail":"rybak.a.v@gmail.com","sentAt":"2018-07-11T20:38:23Z","receivedAt":"2018-07-11T20:38:42Z","isPatch":true,"sender":{"key":"rybak.a.v@gmail.com","avatar":"https://avatars.githubusercontent.com/u/624072?v=4"},"body":"On Wed, 11 Jul 2018 at 22:34, Andrei Rybak <rybak.a.v@gmail.com> wrote:\n>\n> Is -1 an OK initial value for timezone if local_time_tzoffset returns\n> negative values as well? It looks like it doesn't matter for from functional\n>\n\nmeant to say: \"It looks like it doesn't matter from the functional\npoint of view\".\n"},{"id":"352296","messageId":"CA+55aFym5aSudSHiVA=VmvoY=WFytUqficLQCE4Sd_urjwKqPw@mail.gmail.com","threadId":"48836","inReplyTo":"CACayv=ifE5BQVtxXCVEhS3uO7iz1z+ZPrF3J_n=e-uoYOpwNtA@mail.gmail.com","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-11T20:49:24Z","receivedAt":"2018-07-11T20:49:37Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Jul 11, 2018 at 1:34 PM Andrei Rybak <rybak.a.v@gmail.com> wrote:\n>\n> > +     int human_tz = -1;\n>\n> Is -1 an OK initial value for timezone if local_time_tzoffset returns\n> negative values as well? It looks like it doesn't matter for from functional\n\nThe value was intentionally picked to *not* be a valid timezone value,\nso that the comparison of \"human_tz == tz\" would always fail if\nDATE_HUMAN is not selected.\n\nBut it could be anything else invalid, of course. It could be MAX_INT\nor something like that.\n\nBy picking something that isn't possibly a real timezone value, late\ncode can do things like\n\n        hide.tz = local || tz == human_tz;\n\nwithout worrying about whther it's really DATE_HUMAN or not.\n\nThe clearing of \"human_tm\" is done for a similar reason: the code does\n\n        hide.year = tm->tm_year == human_tm->tm_year;\n\n(and then later just checks \"if (human_tm->tm_year)\") knowing that a\nnon-zero tm_year will only ever happen for human_tz (and that 1900 is\nnot a valid git date, even though I guess in theory you could do it).\n\n               Linus\n"},{"id":"352298","messageId":"xmqqtvp51ok0.fsf@gitster-ct.c.googlers.com","threadId":"48836","inReplyTo":"CACayv=jM0Q4x=U+4=_YqJHto_ZdZAz8r89xALOcW5a+n9w=LeA@mail.gmail.com","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-07-11T20:54:07Z","receivedAt":"2018-07-11T20:54:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andrei Rybak <rybak.a.v@gmail.com> writes:\n\n> On Wed, 11 Jul 2018 at 22:34, Andrei Rybak <rybak.a.v@gmail.com> wrote:\n>>\n>> Is -1 an OK initial value for timezone if local_time_tzoffset returns\n>> negative values as well? It looks like it doesn't matter for from functional\n>>\n>\n> meant to say: \"It looks like it doesn't matter from the functional\n> point of view\".\n\nAs long as we do not show data in a timezone that is exactly one\nminute ahead (or is it behind???) of UTC, it does not cause an issue\nin practice.\n"},{"id":"352300","messageId":"CA+55aFx8-hni4WoDpc6jkNo03GJr1jVbRr5-Pz35X=yaq+hEqQ@mail.gmail.com","threadId":"48836","inReplyTo":"CA+55aFym5aSudSHiVA=VmvoY=WFytUqficLQCE4Sd_urjwKqPw@mail.gmail.com","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-11T21:23:47Z","receivedAt":"2018-07-11T21:24:01Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"[ Trying to come up with crazy special cases ]\n\nOn Wed, Jul 11, 2018 at 1:49 PM Linus Torvalds\n<torvalds@linux-foundation.org> wrote:\n>\n> But it could be anything else invalid, of course. It could be MAX_INT\n> or something like that.\n\nThat might be better. A timezone of -1 isn't actually a valid\ntimezone, but I guess you could create a commit by hand that had\n\"-0001\" as the timezone.\n\nYou can't do that with something like MAX_INT, without fsck\ncomplaining - since it has to be exactly four digits.\n\n> The clearing of \"human_tm\" is done for a similar reason: the code does\n>\n>         hide.year = tm->tm_year == human_tm->tm_year;\n>\n> (and then later just checks \"if (human_tm->tm_year)\") knowing that a\n> non-zero tm_year will only ever happen for human_tz (and that 1900 is\n> not a valid git date, even though I guess in theory you could do it).\n\nActually, the 1900 should be safe, because 'timestamp_t' is unsigned.\nSo a valid timestamp really can't be before 1970.\n\nOf course, you can probably try to mess with it by giving values that\ndon't actually fit, because sometimes we do convert mindlessly from\n'timestamp_t' to 'time_t'. In particular, if you use the\n\"default-local\" time, it will use that\n\n  static struct tm *time_to_tm_local(timestamp_t time)\n  {\n        time_t t = time;\n        return localtime(&t);\n  }\n\nand not check the range of the timestamp.\n\nBut other proper time stamp functions will actually do range checking\nwith \"date_overflow()\", so in general that whole assumption of \"a real\ngit date cannot be in the year 1900\" is valid.\n\n              Linus\n"},{"id":"352301","messageId":"87h8l5cvp3.fsf@evledraar.gmail.com","threadId":"48836","inReplyTo":"alpine.LFD.2.21.999.1807071502260.18818@i7.lan","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-07-11T21:24:24Z","receivedAt":"2018-07-11T21:24:34Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Sat, Jul 07 2018, Linus Torvalds wrote:\n\nI really like where this is going in general. Having a \"human\" format\nwould be great.\n\n> For really recent dates (same day), use the relative date stamp, while\n> for old dates (year doesn't match), don't bother with time and timezone.\n> [...]\n> Once you're talking \"last year\" patches, you don't tend to care about time\n> of day or timezone. So the longest date is basically \"Thu Oct 19 16:00\",\n> because if you show the year (four characters), you don't show the time\n> (five characters). And the timezone (five characters) is only shown if not\n> showing the date (5-6 characters).\n\nJust chiming in on this part, I think it's a worthwile trade-off to\nalways keep it relatively short, but I'd like to challenge the \"you\ndon't tend to care about time [for really old commits]\".\n\nI think that's true for the likes of linux.git & git.git, but a lot of\nusers of git say work in some corporate setting entirely or mostly in\nthe same timezone.\n\nIn that case, knowing if some commit whose sole message was \"fix\"[1] was\nmade at 3am or in the afternoon, even if it's really old, is really\nuseful information, even years later.\n\nMaybe something like v2 could be a human-lossy and v1 human-short (or\nbetter names...). I.e. (AFAICT) v1 didn't lose any information, just\nsmartly abbreviated it, but v2 does.\n\n1. Because let's face it, bothering to write good commit messages like\n   git.git is the exception.\n"},{"id":"352306","messageId":"CA+55aFw2srtqU2B60wWo9h38pTTwT4zCDHZDwb+WMpMAbc0wOg@mail.gmail.com","threadId":"48836","inReplyTo":"87h8l5cvp3.fsf@evledraar.gmail.com","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-11T21:49:32Z","receivedAt":"2018-07-11T21:49:45Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Jul 11, 2018 at 2:24 PM Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n>\n> I think that's true for the likes of linux.git & git.git, but a lot of\n> users of git say work in some corporate setting entirely or mostly in\n> the same timezone.\n>\n> In that case, knowing if some commit whose sole message was \"fix\"[1] was\n> made at 3am or in the afternoon, even if it's really old, is really\n> useful information, even years later.\n\nHeh.\n\nMaybe. But if  you care about that kind of information, would you\nactually want to use the \"human\" date? Wouldn't you want to use the\nstrftime thing instead, which gets you whatever field you care about,\nand gets it consistently regardless of how old the data is?\n\nThat said, I do acknowledge that the \"human\" format may be a bit\ninflexible and ad-hoc. Of course some more generic way that allowed\narbitrary rules might be better for some uses.\n\nI'll just explain the cases that made me zero in on what that last patch did:\n\n (a) I do like the \"relative\" date for recent stuff.\n\nQuite often, I look at how recent the commits are, for example, and\nthen I really like seeing \"2 hours ago\" rather than a time with a\ntimezone (which is a lot harder for me to mentally parse)\n\nThis was the primary impetus for my original \"auto\" patch many years\nago, that was (rightly) not merged. It really boiled down to just\n\"default or relative, depending on how recent it was\".\n\n (b) I noticed that I was distracted by dates that were *too* terse.\n\nMy first patch had _just_ the time when it was today and the same\ntimezone (but older than two hours, so the original relative logic\ndidn't trigger).\n\nThat initially sounded great to me, which is why it was that first time.\n\nBut after _using_ it for a while, I actually found that it didn't have\nenough context for me (visually) to really trigger my date parsing at\nall.\n\nSo \"five hours ago\" actually parsed better than just \"9:48\" to me. I\ndidn't think it would do that, but it did. Which was why I changed the\n\"relative\" time to trigger every time if it was the exact same date\n(and in the past) - just to avoid the really terse model.\n\n (c) when I played around with other commands than just \"git log\", I\nalso noticed that a consistent length mattered.,\n\nAgain, my first version was more along the lines of \"if it's long ago,\njust use the full format, exactly like the default date\". It wasn't\n*quite* that, because it would always skip the seconds, but it was\nclose.\n\nAnd with \"git log\", that worked fine, because dates were fairly\nuniformly increasing, so the date format would slowly get longer, and\nthat was fine.\n\nBut then when I played with \"git blame -C --date=human\", I noticed\nthat not only did the human date actually make sense there too, it\nactually made it easier for me to read - and that in particular, the\n\"extra\" info was just annoying.\n\nSo now I find that shortened \"only show the date\" format to be really\ngood _particularly_ for \"git blame\". You can see very clearly whether\nit's something recent or something old.\n\nMaybe my use of \"git blame\" is unusual, but I don't think so. I tend\nto do \"git blame -C\" when I'm looking for a bug, and then seeing\nsomething like this:\n\n        ...\n          Apr 16 2005       437)\n          Apr 16 2005       438)\n          Jan 14 2016       439)\n          Apr 16 2005       440)\n          Apr 16 2005       441)\n          Apr 16 2005       442)\n          Thu Jun 14 15:26  443)\n          Thu Jun 14 15:26  444)\n          Thu Jun 14 15:26  445)\n          Thu Jun 14 15:26  446)\n          Thu Jun 14 15:26  447)\n          Thu Jun 14 15:26  448)\n          Thu Jun 14 15:26  449)\n          Thu Jun 14 15:26  450)\n          Apr 16 2005       451)\n          Jul 30 2012       452)\n          Jul 30 2012       453)\n          Feb 13 2012       454)\n          Apr 16 2005       455)\n          Apr 16 2005       456)\n        ....\n\nin that date field (yeah. that happens to be \"kernel/fork.c\" in the\ncurrent kernel - I just edited out all the other stuff than time and\nline number) is actually very visually easy to see what parts are old,\nand which ones are recent, because it changes the format pretty\nclearly and unambiguously, without changing the size of that field\n_dramatically_.\n\n(Sure, the size changes, but it's not a radical difference, it's a\nfairly small variation, and the variation only highlights the\ndifferent time range, without making it compltely unbalanced).\n\nAnyway, enough excuses. I'l just trying to explain some of the things\nthat I noticed simply _while_ making some of the decisions I made.\n\nAre they the \"right\" decisions? I don't know. But I've been running with that\n\n        git config --add log.date auto\n\nin my kernel repo since I posted the patches, and so far I'm still liking it.\n\n                 Linus\n"},{"id":"353532","messageId":"xmqqtvoowbgi.fsf@gitster-ct.c.googlers.com","threadId":"48836","inReplyTo":"alpine.LFD.2.21.999.1807071502260.18818@i7.lan","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-07-24T21:49:49Z","receivedAt":"2018-07-24T21:49:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> From: Linus Torvalds <torvalds@linux-foundation.org>\n>\n> This adds --date=human, which skips the timezone if it matches the\n> current time-zone, and doesn't print the whole date if that matches (ie\n> skip printing year for dates that are \"this year\", but also skip the\n> whole date itself if it's in the last few days and we can just say what\n> weekday it was).\n\nThe behavior of the code does not quite match my intuition, though.\n\n    $ date ;# to show that I am in -0700 zone\n    Tue Jul 24 14:42:09 PDT 2018\n    $ git show -s pk/rebase-in-c | head -n 3\n    commit d18b5221ba98fe8254c3f9922ba31b21d7c954af\n    Author: Pratik Karki <predatoramigo@gmail.com>\n    Date:   Sun Jul 8 23:46:04 2018 +0545\n    $ git show --date=human -s pk/rebase-in-c | head -n 3\n    commit d18b5221ba98fe8254c3f9922ba31b21d7c954af\n    Author: Pratik Karki <predatoramigo@gmail.com>\n    Date:   Sun Jul 8 23:46\n\nIt is sensible to omit the seconds; I do not really care about that\nlevel of precision for an event that happened two weeks ago in a\ndifferent continent.\n\nBut lack of TZ does not give me enough hint about which content it\nhappened.  The fact that this was done late at night on weekend is\nindeed interesting, and I may not care what time it locally was for\nme, so perhaps this is an intended behaviour.\n\n"},{"id":"353546","messageId":"CA+55aFyXRyBvpq5Yvjg8=m6fdMRO4fdpDjW=bD4Kryo-goSDJA@mail.gmail.com","threadId":"48836","inReplyTo":"xmqqtvoowbgi.fsf@gitster-ct.c.googlers.com","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2018-07-24T22:58:50Z","receivedAt":"2018-07-24T22:59:04Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Tue, Jul 24, 2018 at 2:49 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> But lack of TZ does not give me enough hint about which content it\n> happened.  The fact that this was done late at night on weekend is\n> indeed interesting, and I may not care what time it locally was for\n> me, so perhaps this is an intended behaviour.\n\nI'm not sure you could call it \"intended\". The TZ hiding did change as\nI was playing with this.\n\nThe first version of the patch only hid the timezone if it matched the\ncurrent one.\n\nBecause, as you say, the time zone can be interesting not so much\nbecause you care about *when* the commit happened, but you care about\n*where* the commit happened. And that can be true even if the commit\nis very old.\n\nSo the timezone data in some sense isn't necessarily about the date at all.\n\nWhen I used it a bit more (I still have the \"--date=auto\" as my\ndefault for the kernel), I decided I really don't much care about the\ntimezone. In any _individual_ case, the timezone looks fine, but when\nyou look at many different dates, it looks really odd how it sometimes\nshows, and sometimes does not, particularly for old dates when it\nreally doesn't matter for the *time* reason.\n\nSo I decided that it's better to not show the timezone at all when you\nshow a real date.\n\nBut honestly, I don't claim to have a really strong argument. It's\njust a choice. Nothing says it's the absolute right choice.\n\nI pointed out that you can use \"--date=human-local\" to get an even\ndenser representation that gives you the human date without ever\nhaving a TZ. But we don't have the reverse of \"-local\", which would\nexplicitly show the timezones.\n\nAgain, I think this is really because the timezone is about something\nother than just the time. I think the \"do we care *where* it was done\nor not?\" question in many ways is entirely independent of the time\nquestion.\n\nSo right now the patch says\n\n                hide.tz |= !hide.date;\n\nwhich ends up being good for the \"times are roughly the same size\"\n(which I decided was a good thing - again, I don't really have a\nhugely strong argument for it, it was a matter of me playing with\noptions).\n\nBut it would make equally much sense to say\n\n                hide.tz |= hide.time;\n\nand just say that the timezone is hidden if it matches the current\none, or if the commit is just so old that we don't show the time at\nall.\n\nOR you could just say \"timezone is always interesting, because you\nwant to know _where_ it was done regardless of _when_ it was done\",\nand just not hide the timezone at all.\n\nI think all are \"technically valid\" choices to make. The one I made\nwas just a random personal preference, not necessarily the right one.\n\nCould we extend on the \"decorations\" (like the \"-local\" thing)?\nAbsolutely.  I'm not sure it's worth doing, but it would certainly\nsolve the \"different people have different preferences\" issue.\n\nI think that *if* we want to extend on the decorations, that would\nprobably still be a separate patch from the basic patch.\n\n               Linus\n"},{"id":"364116","messageId":"5263255.SQOp2klSmx@thunderbird","threadId":"48836","inReplyTo":"alpine.LFD.2.21.999.1807071502260.18818@i7.lan","subject":"Re: [RFC PATCH v2] Add 'human' date format","fromName":"Stephen P. Smith","fromEmail":"ischis2@cox.net","sentAt":"2018-11-27T04:10:10Z","receivedAt":"2018-11-27T04:10:15Z","isPatch":true,"sender":{"key":"ishchis2@gmail.com","avatar":null},"body":"On Saturday, July 7, 2018 3:02:35 PM MST Linus Torvalds wrote:\n> From: Linus Torvalds <torvalds@linux-foundation.org>\n> \n> This adds --date=human, which skips the timezone if it matches the\n> current time-zone, and doesn't print the whole date if that matches (ie\n> skip printing year for dates that are \"this year\", but also skip the\n> whole date itself if it's in the last few days and we can just say what\n> weekday it was).\n\nIn the \"What's cooking....\" email response [1] there was some \nconcern about what to call this format.\n\nWhile the format is more useful to humans by dropping inferred information, \nthere is nothing that makes it actually human.  Additionally, what \none human considers a good format another may not like.  \n\nIn part of the V2 patch email[2], Linus notes that the patch reports \nrelative dates based on information inferred from the date \non the machine running the git command at the time the \ncommand is executed.   \n\nIf relative wasn't already taken that would be a reasonable \nchoice instead of human.\n\nTherefore keeping 'human' and documenting how the patch formats \nthe date to suppress future \"infinite\" tweaks to the format seems \nlike a a reasonable way to approach your concerns. [1]\n\nI will start working the Doc's and test updates.   \n\nOn Wednesday, November 21, 2018 6:06:13 PM MST Junio C Hamano wrote:\n> Command line completion;\n\nI'm not quite sure what you want for this item.   Could you please describe?\n\nsps\n\n[1] https://public-inbox.org/git/xmqq8t1l6hve.fsf@gitster-ct.c.googlers.com/\n[2] https://public-inbox.org/git/alpine.LFD.2.21.999.1807071502260.18818@i7.lan/\n\n\n"}]}