来自https://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html
我知道gawk在日期/时间上只有2个功能mktimestrftime

因此,我可以使用返回长整数的mktime解析任何日期,以便进行任何数学运算,并可以使用strftime格式化所需的输出

对于"1970 01 01 00 00 00"之后的任何日期,这都像一个咒语

使用awk,如何格式化1970年之前的日期?

$ awk 'BEGIN{t=mktime("1970 01 01 00 00 00"); print t; print strftime("%Y-%m-%d", t) }'
10800
1970-01-01
$ awk 'BEGIN{t=mktime("1960 01 01 00 00 00"); print t; print strftime("%Y-%m-%d", t) }'
-315608400
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: strftime: second argument less than 0 or too big for time_t

最佳答案

不幸的是,正如您所看到的,gawk不能直接做到这一点。 gawk manual说:



手册未说明如果给定的日期超出范围,strftime()会做什么。

但是即使在我的系统上,它对于time_t负值也表现得很合理,但gawk的strftime()函数不支持它们(尽管mktime()可以),因此无法处理1970年之前的日期。我认为这是gawk中的错误。

(我的建议是使用Perl而不是Awk,但这不能回答您提出的问题。)

原则上,您可以通过在awk中重新实现strftime()之类的功能来重新发明轮子。但这太过分了。

如果您的系统具有有效的GNU coreutils date命令,则可以从gawk调用它。以您的1960年1月1日为例:

$ cat 1960.awk
#!/usr/bin/awk -f

BEGIN {
    timestamp = mktime("1960 00 00 00 00 00")
    print "mktime() returned " timestamp

    if (0) {
        # This doesn't work
        s = strftime("%Y-%m-%d %H:%M:%S", timestamp)
        print "strftime() returned ", s
    }
    else {
        # This works
        "date '+%Y-%m-%d %H:%M:%S' -d @" timestamp | getline t
        print "The date command printed \"" t "\""
    }
}
$ ./1960.awk
mktime() returned -318355200
The date command printed "1959-11-30 00:00:00"
$

(我放弃了从shell提示中单行确定引号和反斜杠的顺序。)

如果您有一个大型的现有awk程序,并且需要向其中添加此功能,则这可能很有意义。但是,如果您不愿意在awk中执行此操作,则可以考虑使用其他方法。 awk可能不是您要完成的目标的正确工具。

或者,如果您真的很雄心勃勃,则可以修改gawk源以正确处理这种情况。

10-07 15:46