首页 > 解决方案 > 使用 macos ootb /bin/date 解析秒的意外输出

问题描述

minutes:seconds使用 MacOS ootb以秒为单位格式化时间间隔/bin/date可以使用以下格式按预期工作"+%M:%S"

# 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

但是,当解析的值超过一小时(3600+ 秒)时,格式字符串"+%H:%M:%S"(和等效的"+%T")似乎有一个错误:

date -j -f "%s" 3600  "+%H:%M:%S"
# ACTUAL OUTPUT: 02:00:00
# EXPECTED OUTPUT: 01:00:00

手册页date提到了Parsing is done using strptime(3)which 又指向strftimewhich 说:

%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3)).

根据上述,我希望 3600 被解析和格式化为01:00:00而不是02:00:00.

我传递的参数有问题还是这是一个实现错误?

标签: bashmacosshelldatestrftime

解决方案


基本问题是date不处理时间间隔,它处理绝对时间+日期。当您使用date -j -f "%s" 200时,它不会将“200”解释为 200 秒的间隔,它表示 UTC 时间 1970 年 1 月 1 日午夜之后的 200 秒。所以如果我在我的 Mac 上运行它,我会得到:

$ date -j -f "%s" 200
Wed Dec 31 16:03:20 PST 1969

...因为我在美国太平洋时区。我目前处于太平洋夏令时间,但在 UTC 1970 年 1 月 1 日午夜后 200 秒,该区域将处于太平洋标准时间,因此它使用它来显示时间和日期。

您看到的情况基本相同,但由于您所在的地区比 UTC 早一小时(或者是 1970 年 1 月 1 日),因此您会增加一个小时而不是减去 8 个小时。除非您显示小时数,否则您不会注意到这一点,但即使时间“间隔”小于 3600,它也会发生:

$ date -j -f "%s" 200 "+%H:%M:%S"
16:03:20

(在您的时区中,您可能会看到“01:03:20”。)在具有非小时偏移的时区中,您可能会得到更奇怪的结果:

$ TZ=Canada/Newfoundland date -j -f "%s" 200  "+%H:%M:%S"
20:33:20

您可以通过使用或告诉date以 UTC 输出来解决此问题:-uTZ=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

但至少在我看来,这仍然只是一个 hack;根本问题是您将间隔与绝对时间混为一谈,我不相信这也不会导致其他问题。


推荐阅读