On 23/11/2025 05:43, Jeffery Palm wrote:
Hi Padraig,

Thanks for the feedback.

I was able to get back to this and have a look at getting this inconsistency 
resolved, and I was able to find a change that seems to resolve this 
inconsistency.

It is still correctly parsing the timezone with AM/PM:

$ ./src/date --debug -d '2024-01-01 8:00:00PM -0500'
date: parsed date part: (Y-M-D) 2024-01-01
date: parsed time part: 08:00:00pm UTC-05
date: input timezone: parsed date/time string (-05)
date: using specified time as starting value: '20:00:00'
date: starting date/time: '(Y-M-D) 2024-01-01 20:00:00 TZ=-05'
date: '(Y-M-D) 2024-01-01 20:00:00 TZ=-05' = 1704157200 epoch-seconds
date: timezone: system default
date: final: 1704157200.000000000 (epoch-seconds)
date: final: (Y-M-D) 2024-01-02 01:00:00 (UTC)
date: final: (Y-M-D) 2024-01-01 17:00:00 (UTC-08)
date: output format: ‘%a %d %b %Y %T %Z’
Mon 01 Jan 2024 17:00:00 PST

And will now correctly prioritize time offset with a ime unit is specified, 
both with AM/PM and without:

$ ./src/date --debug -d '2024-01-01 8:00:00 -5 days'
date: parsed date part: (Y-M-D) 2024-01-01
date: parsed relative part: -5 day(s)
date: parsed time part: 08:00:00
date: input timezone: system default
date: using specified time as starting value: '08:00:00'
date: starting date/time: '(Y-M-D) 2024-01-01 08:00:00'
date: warning: when adding relative days, it is recommended to specify noon
date: after date adjustment (+0 years, +0 months, -5 days),
date:     new date/time = '(Y-M-D) 2023-12-27 08:00:00'
date: '(Y-M-D) 2023-12-27 08:00:00' = 1703692800 epoch-seconds
date: timezone: system default
date: final: 1703692800.000000000 (epoch-seconds)
date: final: (Y-M-D) 2023-12-27 16:00:00 (UTC)
date: final: (Y-M-D) 2023-12-27 08:00:00 (UTC-08)
date: output format: ‘%a %d %b %Y %T %Z’
Wed 27 Dec 2023 08:00:00 PST

$ ./src/date --debug -d '2024-01-01 8:00:00AM -5 days'
date: parsed date part: (Y-M-D) 2024-01-01
date: parsed relative part: -5 day(s)
date: parsed time part: 08:00:00
date: input timezone: system default
date: using specified time as starting value: '08:00:00'
date: starting date/time: '(Y-M-D) 2024-01-01 08:00:00'
date: warning: when adding relative days, it is recommended to specify noon
date: after date adjustment (+0 years, +0 months, -5 days),
date:     new date/time = '(Y-M-D) 2023-12-27 08:00:00'
date: '(Y-M-D) 2023-12-27 08:00:00' = 1703692800 epoch-seconds
date: timezone: system default
date: final: 1703692800.000000000 (epoch-seconds)
date: final: (Y-M-D) 2023-12-27 16:00:00 (UTC)
date: final: (Y-M-D) 2023-12-27 08:00:00 (UTC-08)
date: output format: ‘%a %d %b %Y %T %Z’
Wed 27 Dec 2023 08:00:00 PST

And the coreutils complete testsuite is passing:


Below is the full patch:

I've attached the patch for easier application if others want to test.
Also CC'd bug-gnulib as that's where the codes originates.

I see that the unadorned number is still taken as a timezone which is good
for compat (and would be good to add to tests I think):

   $ src/date --debug -d '2024-01-01 20:00 -5'
   date: parsed date part: (Y-M-D) 2024-01-01
   date: parsed time part: 20:00:00 UTC-05

cheers,
Padraig
diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y
index 6c52cd2c4c..71f8b9ae0e 100644
--- a/lib/parse-datetime.y
+++ b/lib/parse-datetime.y
@@ -573,8 +573,8 @@ debug_print_relative_time (char const *item, parser_control const *pc)
 %parse-param { parser_control *pc }
 %lex-param { parser_control *pc }

-/* This grammar has 31 shift/reduce conflicts.  */
-%expect 31
+/* This grammar has 40 shift/reduce conflicts.  */
+%expect 40

 %union
 {
@@ -681,17 +681,17 @@ iso_8601_datetime:
   ;

 time:
-    tUNUMBER tMERIDIAN
+    tUNUMBER tMERIDIAN o_zone_offset
       {
         set_hhmmss (pc, $1.value, 0, 0, 0);
         pc->meridian = $2;
       }
-  | tUNUMBER ':' tUNUMBER tMERIDIAN
+  | tUNUMBER ':' tUNUMBER tMERIDIAN o_zone_offset
       {
         set_hhmmss (pc, $1.value, $3.value, 0, 0);
         pc->meridian = $4;
       }
-  | tUNUMBER ':' tUNUMBER ':' unsigned_seconds tMERIDIAN
+  | tUNUMBER ':' tUNUMBER ':' unsigned_seconds tMERIDIAN o_zone_offset
       {
         set_hhmmss (pc, $1.value, $3.value, $5.tv_sec, $5.tv_nsec);
         pc->meridian = $6;
@@ -720,6 +720,11 @@ iso_8601_time:
 o_zone_offset:
   /* empty */
   | zone_offset
+  | relunit_snumber
+      {
+        if (! apply_relative_time (pc, $1, 1)) YYABORT;
+        debug_print_relative_time (_("relative"), pc);
+      }
   ;

 zone_offset:

Reply via email to