将YYYY-MM-DD HH:MM:SS转换为相对于0的秒

问题描述

有一个csv文件,其中的行有5个用逗号隔开的字段:

2020-07-31 15:15:55,xx,yy,zz,t
2020-07-31 15:16:57,t
2020-07-31 15:17:00,t

并且我想以秒为单位(相对时间)将第一行用作0,所以输出是这样的:

0,t
62,t
65,t

我可以使用任何编程语言来完成工作,例如bash,awk,sed,perl ...,然后覆盖同一文件或创建一个新文件。

解决方法

perl -MTime::Piece -F,-lane '
    BEGIN {$,= ","}
    $t = Time::Piece->strptime(shift(@F),"%F %T")->epoch;
    if ($. == 1) {$start = $t}
    print $t - $start,@F;
' file
,

这是UNIX环境无法轻松处理的问题。 使用teip

$ teip -d,-f1 -- sh -c "date -f- +%s" < file.txt |
  awk -F,'NR==1{n=$1}{$1=$1-n};4' OFS=,xx,yy,zz,t
62,t
65,t
,

@anubhava的原始答案(只有2个字段):

您可以将此awkmktime函数一起使用。 这将输出两个用逗号分隔的字段:

awk 'BEGIN {
   FS=OFS=","                 # set input and output field separators to comma
}
{
   gsub(/[-:]/," ",$1)      # replace - and : with a space
   tm = mktime($1)            # convert date-time string to EPOCH value
   if (NR == 1)               # for 1st records store this value in first
      first = tm
   print (tm - first),$2     # print difference and 2nd field for each record
}' file

结果:

0,xx
62,xx
65,xx

由@smeterlink改进

这将使用NF变量检测所有逗号分隔的字段,因此即使只有第一个字段也可以使用。这样可以混合使用不同数量字段的行:

get.awk

BEGIN {
   FS=OFS=",$1)      # replace - and : with a space
   tm = mktime($1)            # convert date-time string to EPOCH value
   if (NR == 1)               # for 1st records store this value in first
      first = tm
   {
      printf (tm - first)     # print difference
      if (NF > 1)             # print 2nd to last fields only if they exist
      {
         for (i = 2; i < NF; i += 1)
         printf ","$i
         print ","$NF
      }
      else
         print ""             # otherwise print newline after printf
   }
}

file.csv

2020-07-31 15:15:55,t
2020-07-31 15:16:57,t
2020-07-31 15:17:00,t
2020-07-31 15:17:23,abc,009-%5
2020-07-31 15:18:00
2020-07-31 15:19:00,xx

结果

awk -f get.awk file.csv
0,t
88,009-%5
125
185,xx
,

这是一个可行的部分答案,考虑到日期不变,因此将其省略。

cat file.csv | awk -F ' ' '{print $2}'| awk -F ':|,' '{printf ($1*3600+$2*60+$3)}{print ","$4","$5","$6","$7}'

这将输出此结果,该结果仍保留到第一个值,可以从文件中读取:

54955,t
55017,t
55020,t

现在,由于所有行的值都相同,因此可以手动输入:

cat file.csv | awk -F ' ' '{print $2}'| awk -F ':|,' '{printf ($1*3600+$2*60+$3-54955)}{print ","$7}'

这将给出期望的结果:

0,t

*** 稍后添加:由于此线程提供了一种将时间转换为纪元的方法,这是绝对的: Convert date to epoch time using AWK in linux 所以它会像这样:

cat file.csv | awk -F,'{ OFS = FS;command="date -d " "\"" $1 "\""  " +%s";command | getline $1;close(command);print}'
1596201355,t
1596201417,t
1596201420,t

** 稍后再添加: 保留第一个值的方法是使用以下awk表达式:

| awk -F,'NR==1{pattern=$1}{printf ($1-pattern)}{print ","$2","$3","$5}'

因此,之前说明的2种方式将保持不变: 这种情况只能在同一天起作用:

cat file.csv | awk -F ' ' '{print $2}'| awk -F ':|,"$7}' | awk -F,"$5}'

这(使用纪元)将考虑以下日子:

cat file.csv | awk -F,'{ OFS = FS;command="date -d " "\"" $1 "\""  " +%s";command | getline $1;close(command);print}' | awk -F,"$5}'

到目前为止最好的解决方案:将考虑使用时代的日子,并且可以与awk的任何变体一起使用,包括BSD变体。它还可以检测到有多少个字段,即使只有第一个字段也可以使用:
cat file.csv | awk -F,'NR==1{pattern=$1}{printf ($1-pattern)}{if (NF > 1){for (i = 2; i < NF; i += 1) printf ","$i; print ","$NF} else print ""}'

file.csv

2020-07-31 15:15:55,xx

结果

0,xx

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...