Reputation: 31666
Formatting a time interval in seconds as minutes:seconds
using MacOS ootb /bin/date
works as expected using the "+%M:%S"
format:
# convert 200 seconds to 03:20
date -j -f "%s" 200 "+%M:%S"
# OUTPUT: 03:20
# convert 3595 seconds to 59:55
date -j -f "%s" 3595 "+%M:%S"
# OUTPUT: 59:55
However when the parsed value is more than one hour (3600+ seconds) the format string "+%H:%M:%S"
(and the equivalent "+%T"
) appears to have an off-by-one error:
date -j -f "%s" 3600 "+%H:%M:%S"
# ACTUAL OUTPUT: 02:00:00
# EXPECTED OUTPUT: 01:00:00
The manpage for date
mentions that Parsing is done using strptime(3)
which in turn points to strftime
which says:
%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3)).
According to the above I would expect 3600 to be parsed and formatted as 01:00:00
and NOT as 02:00:00
.
Is there something wrong with the arguments I am passing or is this an implementation bug?
Upvotes: 0
Views: 68
Reputation: 125718
The basic problem is that date
doesn't deal with time intervals, it deals with absolute time+dates. When you use date -j -f "%s" 200
, it doesn't interpret the "200" as meaning an interval of 200 seconds, it means 200 seconds after midnight, January 1 1970, UTC. So if I run that on my Mac, I get this:
$ date -j -f "%s" 200
Wed Dec 31 16:03:20 PST 1969
...because I'm in the US Pacific time zone. I'm currently on Pacific Daylight time, but at 200 seconds after midnight, January 1 1970, UTC, this area would've been on Pacific Standard time, so it uses that to display the time & date.
You're seeing essentially the same thing, but since your area is one hour ahead of UTC (or was on January 1, 1970), you get an hour added instead of 8 subtracted. You don't notice this unless you display the hours, but it'll happen even if the time "interval" is less than 3600:
$ date -j -f "%s" 200 "+%H:%M:%S"
16:03:20
(In your time zone, you'll presumably see "01:03:20".) You can get even weirder results in a time zone with a non-hour offset:
$ TZ=Canada/Newfoundland date -j -f "%s" 200 "+%H:%M:%S"
20:33:20
You can mostly work around this by telling date
to output in UTC, either with -u
or TZ=UTC
:
$ date -ju -f "%s" 3600 "+%H:%M:%S"
01:00:00
$ TZ=UTC date -j -f "%s" 3600 "+%H:%M:%S"
01:00:00
But at least in my opinion, this is still just a hack; the fundamental problem is that you're mixing up intervals with absolute times, and I'm not convinced this won't cause other problems as well.
Upvotes: 2