Subject: Re: [PATCH v2 2/3] approxidate: make "specials" respect fixed day-of-month

From: Junio C Hamano <[email-masked]>
Date: Wed, 13 May 2026 01:52:11 +0900

Tuomas Ahola <[email-masked]> writes:

> The special approxidate time formats, "noon" and "tea", wrap
> to the previous day if the current time is before 12 or 5 pm,
> respectively.  That holds even when an actual date is supplied;
> therefore, "10 May at tea" and "last Friday at noon" can cause
> the date to be set to a seemingly wrong day:
>
> 	now -> 2026-05-12 11:00:00 +0000
> 	10 May at tea -> 2026-05-09 17:00:00 +0000
> 	last Friday at noon -> 2026-05-07 12:00:00 +0000

It would help readers to say that Friday of that week was May 8th to
make it easier for them to see why this is a wrong answer.

> 	One year ago yesterday at tea-time -> 2025-05-10 17:00:00 +0000
>
> The last example is from Linus Torvalds who remarked in 2006
> that the answer was "just silly and not even correct." [1]

It may be just me, but it was hard for me to guess if you are
justifying how these answers are correct, or you are presenting
examples of wrong output.  Perhaps starting the paragraph with cases
where the "wrap to the previous" gets right to set the stage may
make it easier to understand?  Let's see...

    The ... 'noon' and 'tea', wrap to the ... before 12 or 5 pm,
    respectively.  So for example if it is 11am on 2026-05-12, then

	now  -> 2026-05-12 11:00:00 +0000
	noon -> 2026-05-11 11:00:00 +0000
	tea  -> 2026-05-11 17:00:00 +0000

    which would work well when you ask for "git log --since=tea",
    for example.

    That hold even when ... seemingly wrong day:

> As "last Friday at noon" is mentioned in the documentation
> (date-formats.adoc) it would be nice if it worked correctly.
> Let's fix the glitch with a simple patch.
>
> Check whether we already have a specified (non-negative) mday
> and make date_time() stick to it.  Add a suitable time offset
> to the relevant test.
>
> While we are at it, add "today" as an alias of "now", so that
> "today at noon" will do the right thing, too, and assert that
> with a new test.
>
> Links:
>   1. https://lore.kernel.org/git/[email-masked]/
>
> Signed-off-by: Tuomas Ahola <[email-masked]>
> ---
>  date.c          | 8 +++++++-
>  t/t0006-date.sh | 4 ++++
>  2 files changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/date.c b/date.c
> index 17a95077cf..e48cc2a4d7 100644
> --- a/date.c
> +++ b/date.c
> @@ -1132,7 +1132,12 @@ static void date_yesterday(struct tm *tm, struct tm *now, int *num)
>  
>  static void date_time(struct tm *tm, struct tm *now, int hour)
>  {
> -	if (tm->tm_hour < hour)
> +	/*
> +	 * By default, "tea" and "noon" refer to last such time in the
> +	 * past, be it today or yesterday.  With a specified mday,
> +	 * that logic is overridden.
> +	 */

Again, this may be just me, but I happen to find the version of
comment in Peff's review on the earlier iteration of this series
much easier to understand.

> +	if (tm->tm_mday < 0 && tm->tm_hour < hour)
>  		update_tm(tm, now, 24*60*60);
>  	tm->tm_hour = hour;
>  	tm->tm_min = 0;
> @@ -1204,6 +1209,7 @@ static const struct special {
>  	{ "AM", date_am },
>  	{ "never", date_never },
>  	{ "now", date_now },
> +	{ "today", date_now },

Hmph, this may not work very well for "git log --since=today", which
you may want to stop immediately when the traversal reaches a patch
written before the most recent midnight, instead of stopping without
giving anything back.

>  	{ NULL }
>  };
>  
> diff --git a/t/t0006-date.sh b/t/t0006-date.sh
> index 5d66267672..e01d093514 100755
> --- a/t/t0006-date.sh
> +++ b/t/t0006-date.sh
> @@ -186,8 +186,12 @@ check_approxidate '6pm yesterday' '2009-08-29 18:00:00'
>  check_approxidate '3:00' '2009-08-30 03:00:00'
>  check_approxidate '15:00' '2009-08-30 15:00:00'
>  check_approxidate 'noon today' '2009-08-30 12:00:00'
> +check_approxidate 'today at noon' '2009-08-30 12:00:00' success -12
>  check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
> +check_approxidate 'last Friday at noon' '2009-08-28 12:00:00'
> +check_approxidate 'last Friday at noon' '2009-08-28 12:00:00' success -12
>  check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00'
> +check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00' success -12
>  check_approxidate '10am noon' '2009-08-29 12:00:00'
>  check_approxidate 'January 5th yesterday' '2009-01-29 19:20:00'
>  check_approxidate 'January 5th yesterday' '2008-12-31 19:20:00' success +48