From 5fcf3fac690da346c1ee00ed0c1e6d831668f5a6 Mon Sep 17 00:00:00 2001
From: Tuomas Ahola <taahol@utu.fi>
Date: Sun, 16 Mar 2025 23:53:16 +0200
Subject: [PATCH] approxidate: overwrite mday for now, today and yesterday

In c27cc94fad (approxidate: handle pending number for
"specials", 2018-11-02) "Jan 5 yesterday" was given as
an example of an approxidate string where "the number
shouldn't be respected at all".  Likewise, "tea today"
shouldn't respect the usual tea-time logic of going
backwards in time; instead "today" should be able to
override the mday change possibly caused by "tea".

Add a new format "today" as an alias of "now", and make
it and "yesterday" overwrite mday.  Make date_time() use
the new method for deferred mday adjustment, and add tests
to cover the changes.

Signed-off-by: Tuomas Ahola <taahol@utu.fi>
---
 date.c          | 21 ++++++++++++---------
 t/t0006-date.sh |  4 ++++
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/date.c b/date.c
index 3ba4cb9c13..1f070399ca 100644
--- a/date.c
+++ b/date.c
@@ -1127,45 +1127,47 @@ static void pending_number(struct tm *tm, int *num)
 static void date_now(struct tm *tm, struct tm *now, int *num)
 {
 	*num = 0;
+	tm->tm_mday = -1;
 	update_tm(tm, now, 0);
 }
 
 static void date_yesterday(struct tm *tm, struct tm *now, int *num)
 {
 	*num = 0;
+	tm->tm_mday = -1;
 	update_tm(tm, now, 24*60*60);
 }
 
-static void date_time(struct tm *tm, struct tm *now, int hour)
+static void date_time(struct tm *tm, int 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.
+	 * or e.g. "noon today", that logic is overridden.
 	 */
 	if (tm->tm_mday < 0 && tm->tm_hour < hour)
-		update_tm(tm, now, 24*60*60);
+		tm->tm_mday = -2; /* eventually handled by update_tm() */
 	tm->tm_hour = hour;
 	tm->tm_min = 0;
 	tm->tm_sec = 0;
 }
 
-static void date_midnight(struct tm *tm, struct tm *now, int *num)
+static void date_midnight(struct tm *tm, struct tm *now UNUSED, int *num)
 {
 	pending_number(tm, num);
-	date_time(tm, now, 0);
+	date_time(tm, 0);
 }
 
-static void date_noon(struct tm *tm, struct tm *now, int *num)
+static void date_noon(struct tm *tm, struct tm *now UNUSED, int *num)
 {
 	pending_number(tm, num);
-	date_time(tm, now, 12);
+	date_time(tm, 12);
 }
 
-static void date_tea(struct tm *tm, struct tm *now, int *num)
+static void date_tea(struct tm *tm, struct tm *now UNUSED, int *num)
 {
 	pending_number(tm, num);
-	date_time(tm, now, 17);
+	date_time(tm, 17);
 }
 
 static void date_pm(struct tm *tm, struct tm *now UNUSED, int *num)
@@ -1215,6 +1217,7 @@ static const struct special {
 	{ "AM", date_am },
 	{ "never", date_never },
 	{ "now", date_now },
+	{ "today", date_now },
 	{ NULL }
 };
 
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index c69a2fa745..e58c0c595b 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -186,7 +186,11 @@ 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 'noon today' '2009-08-30 12:00:00' success '-12'
+check_approxidate 'noon today' '2009-09-01 12:00:00' success '+36'
 check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
+check_approxidate 'noon yesterday' '2009-08-29 12:00:00' success '-12'
+check_approxidate 'tea last saturday' '2009-08-29 17: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'
-- 
GitLab