[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#26101: Counterproductive calculation order in date
From: |
Assaf Gordon |
Subject: |
bug#26101: Counterproductive calculation order in date |
Date: |
Wed, 15 Mar 2017 10:40:33 -0400 |
> On Mar 15, 2017, at 09:43, Ulf Zibis <address@hidden> wrote:
>
> Am 15.03.2017 um 13:44 schrieb Eric Blake:
>> Maybe you are confused on how date implements "subtract a month". It
>> does NOT do "subtract 28, 29, 30, or 31 days as appropriate", but rather
>> does "subtract 30 days, for lack of anything better to do".
>
> Are you really sure ???
> Here on my 8.25 version I get:
> $ date -d "-12 month" +%F
> 2016-03-15
> $ date -d "-360 day" +%F
> 2016-03-20
To give more details about the inter working of date adjustments:
Assuming the current date is 2017-03-15:
"2017-03-15 - 12 months":
Year = 2017
Month = -9 (yes, it is stored temporarily as -9)
Day = 15
Then it is normalized to:
Year = 2016
Month = 3
Day = 15
While "2017-03-15 - 360 days" =
Year = 2017
Month = 3
Day = -345 (yes, stored as -345)
then normalized to:
Year = 2016
Month = 3
Day = 20
More about the normalization:
When adjusting months (e..g "-12 months),
The value of 'day' isn't touched.
It will be (unexpectedly) modified only in cases where the
month does not have that day, e.g.:
"2017-03-30 - 1 month" becomes:
Year = 2017
Month = 2
Day = 30
then normalized to:
Year = 2017
Month = 3
Day = 2
(because "2017-02-30" means "2 days after 2017-02-28" which is "2017-03-02").
When adjusting days, it is equivalent to subtracting
the number of seconds from the current unix epoch (i.e. seconds since
1970-01-01).
Example:
Current unix time:
$ date -d '20170315' +%s
1489536000
Number of days you want to subtract, in seconds:
$ bc -l<<<'360*86400'
31104000
Resulting unix time:
$ bc -l<<<'1489536000-360*86400'
1458432000
Which is equivalent to:
$ date -d @1458432000 +%F
2016-03-20
Technical note:
date adjustment (years/months/days) is done directly on the member variables
of a 'struct tm' , which is why it ignores the number of days in months.
time adjustment (hours/minutes/seconds) is done on the unix time, AFTER
the normalized date has been converted to unix time.
> So I think my list for enhancements is still fully applicable.
I'm late-comer to the thread, so I'll verify:
You'd like to be able to do date calculations in some predictable way,
in your case to be able to change a file's timestamp.
However,
consider that adjusting by any scale (years/months/days/hours/minutes) will
have side-effects.
Adjusting by months can shift days (e.g. "2016-03-30 - 1 month" is still march).
Adjusting by days can shift hours (e.g. on Day light saving time),
Adjusting by hours can stay in the same day (e.g. "+24 hours" on a when day
light saving results in 25 "hours").
etc.
It is the edge-cases that make day adjustment tricky (e.g. "+1 month" is not
"+30 days", "+1 day" is not always "+24 hours", etc.).
If you can come up with reliable and predictable rules for date adjustment that
will not have these unexpected results - there's definitely room for
improvements.
However, there's also the existing behavior and backwards compatibility that
will need to be taken into account.
regards,
-assaf