我们经常在某些列中包含始终为GMT的日期时间值的csv文件 我们正在寻找一种方法将日期时间值从GMT更改为我们选择的时区 - 所需的目标时区可能因csv而异。调整也需要考虑夏令时。
来自csv的日期时间格式:
YYYY/MM/DD HH:MM:SS
示例数据:
col1,col2,col3,col4
aaa,bbb,2016/01/15 22:01:16,ccc
ddd,eee,,fff
hhh,iii,2014/09/19 00:53:37,jjj
kkk,lll,2015/11/15 22:01:16,mmm
nnn,ooo,2015/10/12 19:54:59,ppp
例如,如果我们想要将上面的样本数据从GMT调整到太平洋时间(GMT -8标准),我们期望的结果将是csv,其值如下:
col1,col2,col3,col4
aaa,bbb,2016/01/15 14:01:16,ccc
ddd,eee,,fff
hhh,iii,2014/09/18 17:53:37,jjj
kkk,lll,2015/11/15 14:01:16,mmm
nnn,ooo,2015/10/12 12:54:59,ppp
注意重新DST:对于上面的5行样本数据,DST仅对第3行和第5行的日期有效。调整可能在线与线之间有所不同,但在目标时区等效值(太平洋)方面是一致的。
日期时间格式本身可以保持原样 - 我们只需要调整时区的日期时间值,并最终将等效日期时间存储在东部,太平洋(或任何其他时区)而不是GMT。
如果可能的话,我们希望利用Ubuntu中本身可用的编辑工具,例如awk,因为我们已经有了使用它的清理例程。如果awk或类似解决方案不可能,将考虑其他解决方案。
其他说明:
感谢任何见解 - 谢谢!
编辑:
在研究这个问题时,我发现了这样的陈述:
echo "1/15/2016 10:01:16 GMT" | awk -v q='"' '{cmd="TZ=America/Los_Angeles date -d"q$0 q" +"q"%F %H:%M:%S %Z"q; cmd|getline x; close(cmd);print x}'
...有点是概念的证明,但是1)我不得不添加" GMT"我自己的字符串,2)输出日期格式略有不同 我希望找到一个可以应用于可能有数千行的csv的解决方案。
答案 0 :(得分:1)
使用GNU awk进行时间函数:
$ cat tst.awk
function dt2utcSecs(dateTime, cmd,line,ret) {
cmd = "TZ=UTC gawk -v dt='" dateTime "' 'BEGIN{print mktime(dt)}'"
ret = ( (cmd | getline line) > 0 ? line : -1 )
close(cmd)
return ret
}
BEGIN{
FS=OFS=","
split(cols,f)
}
{
for (i in f) {
dateTime = gensub(/[\/:]/," ","g",$(f[i]))
utcSecs = dt2utcSecs(dateTime)
if (utcSecs >= 0) {
$(f[i]) = strftime("%Y/%m/%d %T",utcSecs)
}
}
print
}
$ TZ='US/Pacific' gawk -v cols=3 -f tst.awk file
col1,col2,col3,col4
aaa,bbb,2016/01/15 14:01:16,ccc
ddd,eee,,fff
hhh,iii,2014/09/18 17:53:37,jjj
kkk,lll,2015/11/15 14:01:16,mmm
nnn,ooo,2015/10/12 12:54:59,ppp
只需设置cols=3,5,9
即可对这些字段进行转换。有关有效时区的列表,请参阅/ usr / share / zoneinfo。
请注意@webb's answer应该比上面的效率更高,因为上面调用shell为每个输入dateTime字段调用gawk一次,而@webbs只调用gawk两次。
答案 1 :(得分:1)
这是一个有趣的方式:
首先,将日期字符串转换为数字,utc时间戳,然后将数字时间戳转换为本地日期字符串:
TZ=UTC awk -F, '
BEGIN{OFS=","}
{ if(NR>1&&$3){
gsub("[/:]"," ",$3);
$3=mktime($3" GMT")};
print $0
}' infile.csv | awk -F, '
BEGIN{OFS=","}
{ if(NR>1&&$3){
$3=strftime("%Y/%m/%d %H:%M:%S %Z", $3, 0)};
print $0
}' > outfile.csv
输出:
col1,col2,col3,col4
aaa,bbb,2016/01/15 14:01:16 PST,ccc
ddd,eee,,fff
hhh,iii,2014/09/18 17:53:37 PDT,jjj
kkk,lll,2015/11/15 14:01:16 PST,mmm
nnn,ooo,2015/10/12 12:54:59 PDT,ppp
注意1:您可以通过删除第二个%Z
中的awk
来删除输出中的时区,但如果这样做,则只会伤害您未来的自我。
注意2:根据您的awk
版本,这可能有效,也可能无效。如果您的系统有gawk
,请尝试代替awk
。如果没有,则应该很容易安装gawk
。