John W.C. Smith John W.C. Smith - 14 days ago 7
Bash Question

shell date "-n hours" differs with "n hours ago" in some situation

in shell, when I print this

date -d "2016-11-23 13:05 -1 hours " "+%Y-%m-%d %H:00:00"


I get
2016-11-23 23:00:00.
Strange!

when I print this

date -d "2016-11-23 13:05 1 hours ago" "+%Y-%m-%d %H:00:00"


I get
2016-11-23 12:00:00
.

Why they are different? What I think is that they are both
2016-11-23 12:00:00
.

Answer

This is because the negative number is treated as an offset to your timezone, not to the 13:05. In my timezone, MET (one hour east of GMT), this is what I get:

$ date -d "2016-11-23 13:05 -1 hours "  "+%Y-%m-%d %H:00:00"
2016-11-23 16:00:00
$ TZ=GMT date -d "2016-11-23 13:05 -1 hours "  "+%Y-%m-%d %H:00:00"
2016-11-23 15:00:00
$ TZ=GMT-1 date -d "2016-11-23 13:05 -1 hours "  "+%Y-%m-%d %H:00:00"
2016-11-23 16:00:00
$ TZ=GMT-1 date -d "2016-11-23 13:05 -2 hours "  "+%Y-%m-%d %H:00:00"
2016-11-23 17:00:00

The timezone offset is usually specified as a four digit number, as in

Sun, 29  Feb 2004  16:21:42 -0800

but apparently date(1) is happy with a -1 as well.

From the man page:

DATE STRING

The --date=STRING is a mostly free format human readable date string such as "Sun, 29 Feb 2004 16:21:42 -0800" or "2004-02-29 16:21:42" or even "next Thursday". A date string may contain items indicating calendar date, time of day, time zone, day of week, relative time, relative date, and numbers. An empty string indicates the beginning of the day. The date string format is more complex than is easily documented here but is fully described in the info documentation.