Subject: bug#26101: Counterproductive calculation order in date

From: Assaf Gordon <[email-masked]>
Date: Wed, 15 Mar 2017 14:47:56 -0400

Hello, 

> On Mar 15, 2017, at 11:53, Pádraig Brady <[email-masked]> wrote:
> 
> Yes that's an awkward gotcha (I'm not sure is related to the OP's issue).
> I outlined a solution at http://bugs.gnu.org/18159#8
> I didn't document in "coreutils gotchas" as it's covered in "coreutils FAQ",
> though it might deserve a discussion there.

If mentioning date adjustment in the 'gotcha' page,
perhaps the following examples will be useful (short but sufficient to illustrate the problems). All examples work in EDT timezone (= "America/New_York" or -05:00).
"--debug" should be useful to understand these cases.

A year is not always 365 days (2016 was a leap year with 366 days):

  $ date -d '2016-03-01 - 1 year' +%F
  2015-03-01
  $ date -d '2016-03-01 - 365 days' +%F
  2015-03-02

Month calculations are tricky at the end of the month:

  $ date -d '2017-09-30 - 1 month' +%F
  2017-08-30
  $ date -d '2017-10-31 - 1 month' +%F
  2017-10-01

Explanation:
what happens is that after the month is adjusted from 2017-10-31 to 2017-09-31,
the invalid date 2017-09-31 is adjusted by the number of invalid days (1 day after
the last valid day 2017-09-30 becomes 2017-10-01).

A month is not always 30 days (which is obvious, but more tricky
with February):

   $ date -d '2017-03-30 - 1 month' +%F
   2017-03-02
   $ date -d '2017-03-30 - 30 days' +%F
   2017-02-28

A day is not always 24 hours (Nov 6th 2016 was end of DST in US east-coast timezone):

   $ date -d '2016-11-06 + 1 day' +%F
   2016-11-07
   $ date -d '2016-11-06 + 24 hours' +%F
   2016-11-06

Daylight saving adjustment matter *not only* on the actual
day of the switch, but also if the adjusted period crosses
the date of the switch:

   $ date -d '2016-11-01 + 10 days' +%F
   2016-11-11
   $ date -d '2016-11-01 + 240 hours' +%F
   2016-11-10

   $ date -d '2016-06-01 EDT + 6 months' +%F
   2016-11-30

regards,
 - assaf