Subject: Re: bug#17161: date: confusing: "TIME -/+NUM" treated as time zone

From: Assaf Gordon <[email-masked]>
Date: Fri, 19 Oct 2018 21:13:55 -0600

severity 17161 wishlist
retitle 17161 date: confusing: "TIME -/+NUM" treated as time zone
stop

(triaging old bugs)

Hello,

On 02/04/14 05:27 AM, Eric Blake wrote:
> On 04/02/2014 02:17 AM, Marc R.J. Brevoort wrote:
>>
>> The more days I subtract, the more hours are added. If this were a time
>> zone issue, the amount of hours added would be constant but the
>> resulting date would not.
> 
> Thanks for persisting.  I was able to reproduce using coreutils.git, and
> I can explain what's happening.  Date is parsing this as:
> 
> "(2014-03-11 12:34:56 -3) (days)"
[...]
> It does indeed seem awkward that date is not parsing this as:
> 
> "(2014-03-11 12:34:56) (-3 days)"
> 
> but fixing that will require tweaks to the getdate.y parser in gnulib.
> I've reopened the bug to track the issue with awkward precedence in the
> parser.

In the mean time, date gained the "--debug" option that makes
diagnosing these issues somewhat easier.

Due to the way the date parser works, the following
rules apply:

1.
Time (HH:MM:SS) followed by a plus/minus character
and a number - ALWAYS parsed as time zone.
The unit that followed (e.g. "days" / "minutes")
are then taken to be of value 1 (e.g. 1 day, 1 minute).

Examples:

   ## This is "Timezone=3, plus one day"
   $ date --debug -d "2014-03-11 12:34:56 +3 days"
   date: parsed date part: (Y-M-D) 2014-03-11
   date: parsed time part: 12:34:56 UTC+03
   date: parsed relative part: +1 day(s)
   date: input timezone: parsed date/time string (+03)
   [...]
   Wed Mar 12 03:34:56 MDT 2014

   ## This is "Timezone=-10, plus one month"
   $ date --debug -d "2014-03-11 12:34:56 -10 months"
   date: parsed date part: (Y-M-D) 2014-03-11
   date: parsed time part: 12:34:56 UTC-10
   date: parsed relative part: +1 month(s)
   date: input timezone: parsed date/time string (-10)
   [...]
   Fri Apr 11 16:34:56 MDT 2014

2.
Time (HH:MM:SS) followed by a number without plus/minus sign,
The number applies to the units.

   ## This is "time, plus 7 seconds"
   $ date --debug -d "2014-03-11 12:34:56 7 seconds"
   date: parsed date part: (Y-M-D) 2014-03-11
   date: parsed time part: 12:34:56
   date: parsed relative part: +7 seconds
   [...]
   Tue Mar 11 12:35:03 MDT 2014

3.
To subtract units (e.g. three days) without using a minus character
(i.e. forcing rule #2 instead of triggering rule #1), use the word "ago":

   ## This is "time - 7 seconds"
   $ date --debug -d "2014-03-11 12:34:56 7 seconds ago"
   date: parsed date part: (Y-M-D) 2014-03-11
   date: parsed time part: 12:34:56
   date: parsed relative part: -7 seconds
   [...]
   Tue Mar 11 12:34:49 MDT 2014

   ## This is 3 days subtraction
   $ date --debug -d "2014-03-11 12:34:56 3 days ago"
   date: parsed date part: (Y-M-D) 2014-03-11
   date: parsed time part: 12:34:56
   date: parsed relative part: -3 day(s)
   [...]
   Sat Mar  8 12:34:56 MST 2014

Or use Eric's suggestion of putting the "-3 days"
before the date.

4.
Combining a time zone and a unit value is valid,
e.g.

   ## Timezone = -10, 9 days subtraction
   $ date --debug -d "2014-03-11 12:34:56 -10 -9 days"
   date: parsed date part: (Y-M-D) 2014-03-11
   date: parsed time part: 12:34:56 UTC-10
   date: parsed relative part: -9 day(s)
   date: input timezone: parsed date/time string (-10)
   [...]
   Sun Mar  2 15:34:56 MST 2014

----

As Eric wrote above, modifying the parser could be done in gnulib.
Not so much a technical problem, but very likely to be backward-
incompatible in a way that will break many many existing scripts.

As such, I'm marking this as "wishlist", but keeping it open -
discussion is welcomed to continue by replying to this thread.

regards,
  - assaf