7

I've found strange behaviour of date program in Ubuntu 18.04.

So, I consider date should work with --date option and correctly process +N minutes:

date --date "2019-01-01 13:43:32 +1 minutes" "+%Y-%m-%d %H:%M:%S"

But, in Ubuntu 16.04 I will get:

2019-01-01 13:44:32

And in 18.04:

2019-01-01 12:44:32

The solution is add +1 hours as well, but, wait a minute, why I'm getting minus one hour when I do plus one minute?

Victor Perov
  • 255
  • 2
  • 9
  • 2
    No problem here. Did you set `TZ` in your shell? Test with `echo $TZ`. Also look at `timedatectl` output. – Thomas Feb 04 '19 at 20:04
  • 1
    I also see 12:44:32 with timezone set to UTC, on RHEL 7. Something strange is going on here. – Michael Hampton Feb 04 '19 at 20:59
  • `echo $TZ` does not return anything, means it's not set. `timedatectl` shows the next: Local time: Tue 2019-02-05 09:42:12 GMT Universal time: Tue 2019-02-05 09:42:12 UTC RTC time: Tue 2019-02-05 09:42:12 Time zone: Europe/London (GMT, +0000) System clock synchronized: yes systemd-timesyncd.service active: yes RTC in local TZ: no – Victor Perov Feb 05 '19 at 09:41
  • I see it even with timezone set: one of my machines running 18.04 is a desktop so it is set to `America/New_York` instead of UTC. It says the result of the command in the question is `... 07:44:32` but it should really be `... 08:44:32`. – Moshe Katz Feb 08 '19 at 14:18

1 Answers1

8

The problem here is that date is treating the +1 part as the timezone, and not as an extra minute. The extra minute is coming only from the word minutes which is parsed as "add one minute" because it is unclear.

You can see this if you try the following commands:

  • Your original command, which is interpreted as if it says "at time zone UTC +1".

    $ date --date "2019-01-01 13:43:32 +1 minutes" "+%Y-%m-%d %H:%M:%S"
    2019-01-01 12:44:32
    
  • Change to +2 and notice that the hour is reduced by one but the minute stays the same. This is interpreted as "at time zone UTC +2".

    $ date --date "2019-01-01 13:43:32 +2 minutes" "+%Y-%m-%d %H:%M:%S"
    2019-01-01 11:44:32
    
  • Observe that just using +1 (without minutes) gives the behavior of only changing the hour, not the minute.

    $ date --date "2019-01-01 13:43:32 +1" "+%Y-%m-%d %H:%M:%S"
    2019-01-01 12:43:32
    
  • Observe that the word minutes is interpreted as adding a single minute.

    $ date --date "2019-01-01 13:43:32 minutes" "+%Y-%m-%d %H:%M:%S"
    2019-01-01 13:44:32
    

Here is some of the relevant documentation:

  • From the info date command output, section 21.1.6 Options for ‘date’:

    ... For example, ‘--date="2004-02-27 14:19:13.489392193 +0530"’
    specifies the instant of time that is 489,392,193 nanoseconds after
    February 27, 2004 at 2:19:13 PM in a time zone that is 5 hours and
    30 minutes east of UTC. ...
    

    Note the use of +530 to describe the time zone.

  • From the info date command output, section 28.7 Relative items in date strings:

    ... The unit of time may be preceded by a multiplier, given as an
    optionally signed number.  Unsigned numbers are taken as positively
    signed.  No number at all implies 1 for a multiplier.  Following a
    relative item by the string ‘ago’ is equivalent to preceding the unit by
    a multiplier with value -1. ...
    

    Note the text: "No number at all implies 1 for a multiplier".


So how can you get around this?

One option is to reverse the order of the string elements:

$ date --date "+1 minutes 2019-01-01 13:43:32" "+%Y-%m-%d %H:%M:%S"
2019-01-01 13:44:32

Another option (the option I'd prefer) is to explicitly specify the time zone:

$ date --date "2019-01-01 13:43:32 UTC +1 minutes" "+%Y-%m-%d %H:%M:%S"
2019-01-01 13:44:32

(Note that you can also use +0 or Z as alternatives to UTC in the string above.)


Also note that if you are using date version 8.26 or newer (as Ubuntu 18.04 is; 16.04 is using 8.25), you can add the --debug flag for date to tell you how it parsed the input text:

$ date --date "2019-01-01 13:43:32 +1 minutes" --debug "+%Y-%m-%d %H:%M:%S"
date: parsed date part: (Y-M-D) 2019-01-01
date: parsed time part: 13:43:32 UTC+01
date: parsed relative part: +1 minutes
date: input timezone: parsed date/time string (+01)
date: using specified time as starting value: '13:43:32'
date: starting date/time: '(Y-M-D) 2019-01-01 13:43:32 TZ=+01'
date: '(Y-M-D) 2019-01-01 13:43:32 TZ=+01' = 1546346612 epoch-seconds
date: after time adjustment (+0 hours, +1 minutes, +0 seconds, +0 ns),
date:     new time = 1546346672 epoch-seconds
date: timezone: system default
date: final: 1546346672.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-01 12:44:32 (UTC)
date: final: (Y-M-D) 2019-01-01 12:44:32 (UTC+00)
2019-01-01 12:44:32

vs.

$ date --date "+1 minutes 2019-01-01 13:43:32" --debug "+%Y-%m-%d %H:%M:%S"
date: parsed relative part: +1 minutes
date: parsed date part: (Y-M-D) 2019-01-01
date: parsed time part: 13:43:32
date: input timezone: system default
date: using specified time as starting value: '13:43:32'
date: starting date/time: '(Y-M-D) 2019-01-01 13:43:32'
date: '(Y-M-D) 2019-01-01 13:43:32' = 1546350212 epoch-seconds
date: after time adjustment (+0 hours, +1 minutes, +0 seconds, +0 ns),
date:     new time = 1546350272 epoch-seconds
date: timezone: system default
date: final: 1546350272.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-01 13:44:32 (UTC)
date: final: (Y-M-D) 2019-01-01 13:44:32 (UTC+00)
2019-01-01 13:44:32

Final note: I have no idea why you get a different output on 16.04. On my 16.04 machines I get the same result as my 18.04 machines. I also looked through the git history of GNU coreutils, and I don't see any commits that would have obviously caused such a change.

Moshe Katz
  • 3,053
  • 3
  • 26
  • 41
  • Thanks for such wide answer! Based on your answer, I think that 16.04 gives me different value, because it has different time zone (it has UTC +2) – Victor Perov Feb 12 '19 at 12:27