If I subtract a time amount from the current date, GNU date works intuitively:
date '+%F %R'; date '+%F %R' --date='- 1 hour'
2021-04-19 15:35
2021-04-19 14:35
However, when I use a date as operand, the result is unexpected:
$ date '+%F %R' --date='2000/1/2 03:04:05 - 1 hour'
2000-01-02 06:04
$ date '+%F %R' --date='2000/1/2 03:04:05 + 1 hour ago'
2000-01-02 02:04
How is date
intepreting the $date - 1 hour
expression?
In short: The date you give with --date
is taken in local time, unless you specify a time zone, and something like +/- NNN
is taken as one. Only anything after that, even if it's just hour
is taken as the relative modifier. So - 1 hour
doesn't mean to subtract one hour from the given time, but to specify that the time is in the time zone UTC-01, and then to add one hour to it.
What I think should work for what you're trying, would be to either explicitly give the timezone before the offset, or put the offset first so it can't be confused with a timezone.
Here, using the Central European Summer Time timezone (CEST), and today's date, with %Z
added to the output to show the timezone. (You could also use %z
to output the numeric timezone, or +0200
here.)
$ date +'%F %T %Z' -d '2021-04-19 12:00:00 CEST + 5 hours'
2021-04-19 17:00:00 CEST
$ date +'%F %T %Z' -d '+ 5 hours 2021-04-19 12:00:00'
2021-04-19 17:00:00 CEST
Though of course for a January date like in the question, a summer-time time zone like CEST would not be a valid one. But rearranging the two still works, the time you give is just taken as the local time at that time.
$ date +'%F %T %Z' -d '+ 5 hours 2021-01-01 12:00:00'
2021-01-01 17:00:00 CET
(And for 2021-10-31 02:30:00
I get CET, even though that time also exists in CEST...)
(See older revisions of this answer for more examples on how it interprets various inputs.)
As per @muru's answer on another question, we can also use the --debug
option to have the program actually tell us what it did. Note the second and third lines:
$ date --debug +'%F %T %Z' -d '2021-04-19 12:00:00 - 1 hour' date: parsed date part: (Y-M-D) 2021-04-19 date: parsed time part: 12:00:00 TZ=-01:00 date: parsed relative part: +1 hour(s) date: input timezone: -01:00 (set from parsed date/time string) date: using specified time as starting value: '12:00:00' date: starting date/time: '(Y-M-D) 2021-04-19 12:00:00 TZ=-01:00' date: '(Y-M-D) 2021-04-19 12:00:00 TZ=-01:00' = 1618837200 epoch-seconds date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns), date: new time = 1618840800 epoch-seconds date: output timezone: +01:00 (set from TZ="Europe/Berlin" environment value) date: final: 1618840800.000000000 (epoch-seconds) date: final: (Y-M-D) 2021-04-19 14:00:00 (UTC0) date: final: (Y-M-D) 2021-04-19 16:00:00 (output timezone TZ=+01:00) 2021-04-19 16:00:00 CEST
The man page says:
The date string format is more complex than is easily documented here [...]
Which indeed seems quite apt. The more comprehensive documentation is in the info pages, or online: https://www.gnu.org/software/coreutils/manual/html_node/Date-input-formats.html
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments