使用 macos ootb /bin/date 的意外输出解析秒数

Unexpected output parsing seconds with macos ootb /bin/date

使用 MacOS ootb /bin/date 将以秒为单位的时间间隔格式化为 minutes:seconds 使用 "+%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) 又指向 strftime其中说:

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

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

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

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

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

...因为我在美国太平洋时区。我目前使用的是太平洋夏令时,但是在 1970 年 1 月 1 日午夜后 200 秒,UTC,这个区域本来是太平洋 标准 时间,所以它使用它来显示时间和日期。

你看到的基本上是一样的,但由于你所在的地区比 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;根本问题是您混淆了时间间隔和绝对时间,我不相信这不会导致其他问题。