Re: [RFC PATCH] Add 'human' date format

2018-07-07 Thread Linus Torvalds
On Sat, Jul 7, 2018 at 12:58 PM Linus Torvalds
 wrote:
>
> I'm playing with making all "today" dates just use the relative
> format.

Here's the incremental patch for that if people want to compare the output.

With this, you never get the "just time" case, because that will turn
into "2 hours ago" or similar. But you will get "Fri 19:45" for
something that happened yesterday.

So examples from my kernel logs look something like this:

  2 hours ago
  Fri 19:45
  Fri 10:44 +1000
  Fri Jun 22 15:46
  Tue Jun 19 15:41 -0600
  Thu Jun 15 12:57 2017 +0300

depending on how long ago they were and whether they were in the same
timezone etc.

  Linus
 date.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/date.c b/date.c
index 9809ac334..de0b03cf4 100644
--- a/date.c
+++ b/date.c
@@ -199,7 +199,7 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)
 	return &mode;
 }
 
-static void show_date_normal(struct strbuf *buf, struct tm *tm, int tz, struct tm *human_tm, int human_tz, int local)
+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)
 {
 	struct {
 		unsigned int	year:1,
@@ -225,6 +225,14 @@ static void show_date_normal(struct strbuf *buf, struct tm *tm, int tz, struct t
 		}
 	}
 
+	/* Show "today" times as just relative times */
+	if (hide.wday) {
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		show_date_relative(time, tz, &now, buf);
+		return;
+	}
+
 	/* Always hide seconds for human-readable */
 	hide.seconds = human_tm->tm_year > 0;
 
@@ -268,10 +276,6 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
 		/* Fill in the data for "current time" in human_tz and human_tm */
 		human_tz = local_time_tzoffset(now.tv_sec, &human_tm);
 
-		/* Special case: if it's less than an hour ago, use relative time */
-		if (time - now.tv_sec < 60 * 60)
-			type = DATE_RELATIVE;
-
 		/* Don't print timezone if it matches */
 		if (tz == human_tz)
 			local = 1;
@@ -333,7 +337,7 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
 		strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,
 !local);
 	else
-		show_date_normal(&timebuf, tm, tz, &human_tm, human_tz, local);
+		show_date_normal(&timebuf, time, tm, tz, &human_tm, human_tz, local);
 	return timebuf.buf;
 }
 


Re: [RFC PATCH] Add 'human' date format

2018-07-07 Thread Linus Torvalds
On Sat, Jul 7, 2018 at 12:39 PM Linus Torvalds
 wrote:
> to me, but with "--date=human", right now it just says
>
> Date:   12:21

Side note: this is probably my least favorite of the formats.

I'm playing with making all "today" dates just use the relative
format, and then the "a couple of days ago" dates would then have the

> Date:   Fri 19:45

format.

But since it's _explicitly_ about a "human legible" format, I think
the format could be a bit fluid, and things like that might be tweaked
later. Anybody who would script this would be crazy.

I'm more looking for "no, that's just stupid" comments, or "no, you're
not the only one who has wanted this" kinds of replies.

  Linus


[RFC PATCH] Add 'human' date format

2018-07-07 Thread Linus Torvalds


From: Linus Torvalds 

This adds --date=human, which skips the timezone if it matches the
current time-zone, and doesn't print the whole date if that matches (ie
skip printing year for dates that are "this year", but also skip the
whole date itself if it's in the last few days and we can just say what
weekday it was).

For really recent dates (within the last hour), use the relative date
stamp.

Also add 'auto' date mode, which defaults to human if we're using the
pager.  So you can do

git config --add log.date auto

and your "git log" commands will show the human-legible format unless
you're scripting things.

Signed-off-by: Linus Torvalds 
---

Ok, I tried something like this long long ago, but that was a fairly nasty 
patch that just defaulted to "--date=relative" for recent dates, and then 
did the usual default for anything else.

But the issue kept bugging me, and this is a slightly more sane model (?). 
It keeps the notion of "let's use --date=relative for very recent dates", 
but for anything that is more than an hour old, it just uses a simplified 
date.

For example, for time stamps that are "today", just show the time. And if 
the year or the time zone matches the current year or timezone, skip them.  
And don't bother showing seconds, because humans won't care.

The end result is a slightly simplified view.

So for example, the date for this commit right now looks like

Date:   Sat Jul 7 12:21:26 2018 -0700

to me, but with "--date=human", right now it just says

Date:   12:21

(and maybe for a US locale, I should make it do the AM/PM thing).

This is marked RFC because

 (a) maybe I'm the only one who has ever wanted the simplified dates

 (b) the simplification rules themselves might be worthy of discussion.

For example, I also simplified the "a couple of days ago" case, so that it 
shows

Date:   Fri 19:45

for one of my kernel commits that happened yesterday. The date didn't 
match _exactly_, but it's the same month, and just a few days ago, so it 
just shows the weekday. Is that easier to read? Maybe. I kind of like it.


 builtin/blame.c |   1 +
 cache.h |   1 +
 date.c  | 139 +---
 3 files changed, 110 insertions(+), 31 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index 5a0388aae..27c64b1c8 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -917,6 +917,7 @@ int cmd_blame(int argc, const char **argv, const char 
*prefix)
 */
blame_date_width = utf8_strwidth(_("4 years, 11 months ago")) + 
1; /* add the null */
break;
+   case DATE_HUMAN:
case DATE_NORMAL:
blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
break;
diff --git a/cache.h b/cache.h
index d49092d94..8a6810ee6 100644
--- a/cache.h
+++ b/cache.h
@@ -1428,6 +1428,7 @@ extern struct object *peel_to_type(const char *name, int 
namelen,
 struct date_mode {
enum date_mode_type {
DATE_NORMAL = 0,
+   DATE_HUMAN,
DATE_RELATIVE,
DATE_SHORT,
DATE_ISO8601,
diff --git a/date.c b/date.c
index 49f943e25..9809ac334 100644
--- a/date.c
+++ b/date.c
@@ -77,22 +77,16 @@ static struct tm *time_to_tm_local(timestamp_t time)
 }
 
 /*
- * What value of "tz" was in effect back then at "time" in the
- * local timezone?
+ * Fill in the localtime 'struct tm' for the supplied time,
+ * and return the local tz.
  */
-static int local_tzoffset(timestamp_t time)
+static int local_time_tzoffset(time_t t, struct tm *tm)
 {
-   time_t t, t_local;
-   struct tm tm;
+   time_t t_local;
int offset, eastwest;
 
-   if (date_overflows(time))
-   die("Timestamp too large for this system: %"PRItime, time);
-
-   t = (time_t)time;
-   localtime_r(&t, &tm);
-   t_local = tm_to_time_t(&tm);
-
+   localtime_r(&t, tm);
+   t_local = tm_to_time_t(tm);
if (t_local == -1)
return 0; /* error; just use + */
if (t_local < t) {
@@ -107,6 +101,20 @@ static int local_tzoffset(timestamp_t time)
return offset * eastwest;
 }
 
+/*
+ * What value of "tz" was in effect back then at "time" in the
+ * local timezone?
+ */
+static int local_tzoffset(timestamp_t time)
+{
+   struct tm tm;
+
+   if (date_overflows(time))
+   die("Timestamp too large for this system: %"PRItime, time);
+
+   return local_time_tzoffset((time_t)time, &tm);
+}
+
 void show_date_relative(timestamp_t time, int tz,
   const struct timeval *now,
   struct strbuf *timebuf)
@@ -191,27 +199,94 @@ struct date_mode *date_mode_from_type(enum date_mode_type 
type)
return &mode;
 }
 
+static void show_date_normal(struct strbuf *buf, struct tm *tm, int tz, struct 
tm *human_tm, int human_tz, int local)
+{
+   struct {
+   unsigned intyear: