代码之家  ›  专栏  ›  技术社区  ›  ccpizza

macos ootb/bin/date的意外输出解析时间(秒)

  •  0
  • ccpizza  · 技术社区  · 3 年前

    将时间间隔(秒)格式化为 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) 这反过来又指向 strftime 它说:

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

    根据上述内容,我预计3600将被解析并格式化为 01:00:00 而不是 02:00:00 .

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

    0 回复  |  直到 3 年前
        1
  •  1
  •   Gordon Davisson    3 年前

    基本问题是 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
    

    你可以通过告诉 日期 以UTC格式输出,可以使用 -u 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
    

    但至少在我看来,这仍然只是一次黑客攻击;根本问题是,你把时间间隔和绝对时间混为一谈,我不相信这也会导致其他问题。