来自https://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html
我知道gawk
在日期/时间上只有2个功能mktime
和strftime
。
因此,我可以使用返回长整数的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
源以正确处理这种情况。