bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#26101: Counterproductive calculation order in date


From: Eric Blake
Subject: bug#26101: Counterproductive calculation order in date
Date: Tue, 14 Mar 2017 20:21:59 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0

On 03/14/2017 07:17 PM, Ulf Zibis wrote:
> Hi,
> 
> with
>     $ date -r test
> I get:
>     Di 10. Jan 22:39:14 CET 2017
> but with
>     $ date -d "$(($(date -r test +%s)-$(date +%s))) seconds -2 months"
> I get:
>    Sa 12. Nov 22:39:14 CET 2016

Let's try this with the new --debug option of 8.26 (although I'm in a
different timezone, and not using localized strings, hopefully the
concept gets through):

$ date -r ChangeLog
Wed Jan 11 17:11:02 CST 2017
$ date --debug -d "$(($(date -r ChangeLog +%s)-$(date +%s))) seconds -2
months"
date: parsed relative part: -5363514 seconds
date: parsed relative part: -2 month(s) -5363514 seconds
date: input timezone: -06:00 (set from system default)
date: using current time as starting value: '20:02:56'
date: using current date as starting value: '(Y-M-D) 2017-03-14'
date: starting date/time: '(Y-M-D) 2017-03-14 20:02:56 TZ=-06:00'
date: warning: when adding relative months/years, it is recommended to
specify the 15th of the months
date: after date adjustment (+0 years, -2 months, +0 days),
date:     new date/time = '(Y-M-D) 2017-01-14 19:02:56 TZ=-06:00'
date: warning: daylight saving time changed after date adjustment
date: '(Y-M-D) 2017-01-14 19:02:56 TZ=-06:00' = 1484442176 epoch-seconds
date: after time adjustment (+0 hours, +0 minutes, -5363514 seconds, +0 ns),
date:     new time = 1479078662 epoch-seconds
date: output timezone: -06:00 (set from system default)
date: final: 1479078662.653491329 (epoch-seconds)
date: final: (Y-M-D) 2016-11-13 23:11:02 (UTC0)
date: final: (Y-M-D) 2016-11-13 17:11:02 (output timezone TZ=-06:00)
Sun Nov 13 17:11:02 CST 2016

> 
> I think the better result would be according to a calculation order from
> left to right:
>    Sa 10. Nov 22:39:14 CET 2016

What calculation are you trying to achieve? The inner $(()) computes the
difference between two dates: the reference file timestamp, and the
current time, resulting in a negative offset in seconds.  The outer date
computation (where I ran --debug) then sees only two relative values - a
negative seconds offset, and a negative months offset, both applied from
the current time as the starting point.

> 
> Otherwise it seems impossible to correctly change the time stamp of a
> file relative to its current value.

Wait - so you're trying to shift a file's time stamp by a fixed amount,
such as by 2 months?  Doesn't that imply that the outer date should see
the file's timestamp as one of its starting points, rather than being
left to start from the current time as its starting point?

> Example:
>     $ touch -t $(date -d "$(($(date -r test +%s)-$(date +%s))) seconds
> -2 months" +%Y%m%d%H%M.%S) test

So what's wrong with:

$ date --debug -d "Jan 1 1970 $(date -r ChangeLog +%s) seconds -2 months"
date: parsed date part: (Y-M-D) 2017-01-01
date: parsed number part: year: 1970
date: parsed relative part: +1484176262 seconds
date: parsed relative part: -2 month(s) +1484176262 seconds
date: input timezone: -06:00 (set from system default)
date: warning: using midnight as starting time: 00:00:00
date: starting date/time: '(Y-M-D) 1970-01-01 00:00:00 TZ=-06:00'
date: warning: when adding relative months/years, it is recommended to
specify the 15th of the months
date: after date adjustment (+0 years, -2 months, +0 days),
date:     new date/time = '(Y-M-D) 1969-11-01 00:00:00 TZ=-06:00'
date: '(Y-M-D) 1969-11-01 00:00:00 TZ=-06:00' = -5248800 epoch-seconds
date: after time adjustment (+0 hours, +0 minutes, +1484176262 seconds,
+0 ns),
date:     new time = 1478927462 epoch-seconds
date: output timezone: -06:00 (set from system default)
date: final: 1478927462.000000000 (epoch-seconds)
date: final: (Y-M-D) 2016-11-12 05:11:02 (UTC0)
date: final: (Y-M-D) 2016-11-11 23:11:02 (output timezone TZ=-06:00)
Fri Nov 11 23:11:02 CST 2016

which is two months prior to the timestamp?

But you may have found a real bug (or at least something we can
enhance). We document that +%s can be reversed:

$ date -r ChangeLog +%s
1484176262
$ date -r ChangeLog
Wed Jan 11 17:11:02 CST 2017
$ date -d @1484176262
Wed Jan 11 17:11:02 CST 2017

But awkwardly, we refuse to allow @seconds to be used as a starting
point for relative operations:

$ date --debug -d "@$(date -r ChangeLog +%s) -2 months"
date: parsed number of seconds part: number of seconds: 1484176262
date: error: parsing failed, stopped at ' months'
src/date: invalid date address@hidden -2 months’

Also, since you're using GNU date, you're probably using GNU touch,
which means you can use touch -d instead of touch -t to set the time of
the file, with a LOT less notational overhead, and in a reversible
manner relative to a timestamp:

$ : > foo
$ touch -d '-2 months' -r foo foo
$ ls -l foo
-rw-rw-r--. 1 eblake eblake 0 Jan 14 19:19 foo
$ touch -d '+2 months' -r foo foo
$ ls -l foo
-rw-rw-r--. 1 eblake eblake 0 Mar 14 20:19 foo

I'm leaving this open, in case someone wants to tackle the notion of
making @seconds + relative offset a valid parse. But I think your
initial use case is already feasible without any changes to the current
version of date and touch that you are using.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]