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 ‘@1484176262 -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