How does coreutil’s date manage to get such weird results

coreutilsdate

I was playing around with date to try to convert expressions such as "2 hours" to a number of seconds like 7200. I thought I could perform this with invocations such as:

date -d "1970-01-01 00:00:00 + 2 hours" +"%s"

Yet, I noticed extremely strange results while so doing. (My /etc/timezone contains "Europe/Paris", hence the use of TZ to force UTC times.)

omega:~$ TZ=utc date -d "1970-01-01 00:00:00" +"%s"             
0
omega:~$ TZ=utc date -d "1970-01-01 00:00:00 + 0 minutes" +"%s"
60
omega:~$ TZ=utc date -d "1970-01-01 00:00:00 + -1 minutes" +"%s" 
3660
omega:~$ TZ=utc date -d "1970-01-01 00:00:00 + 1 minutes" +"%s" 
-3540

The first result is reasonable enough, but I'm really totally puzzled about how date might have come up with the three last results. Does anyone understand the logic between those results?

Best Answer

I think it's taking your + x as a time-zone specifier (e.g., consider 2013-04-25 19:52:36 +4 is a valid timestamp, in in a time zone 4 hours ahead of UTC).

It's then seeing the word 'minutes', and treating it as a synonym of minute, so giving you one minute later.

If you put in an explicit timezone specifier, it works:

anthony@Zia:~$ TZ=utc date -d "1970-01-01 00:00:00 UTC" +"%s"   
0
anthony@Zia:~$ TZ=utc date -d "1970-01-01 00:00:00 UTC + 0 minutes" +"%s"
0
anthony@Zia:~$ TZ=utc date -d "1970-01-01 00:00:00 UTC + -1 minutes" +"%s" 
-60
anthony@Zia:~$ TZ=utc date -d "1970-01-01 00:00:00 UTC + 1 minutes" +"%s" 
60

Note the UTC after the seconds field. You can also put in a second +0:

anthony@Zia:~$ TZ=utc date -d "1970-01-01 00:00:00 +0 + -1 minutes" +"%s"
-60

... but at least personally, that's much harder to read.

Or you can put a Z after the seconds, etc. You don't actually need the TZ environment variable to be set to UTC in the above examples.