如何在合并的日期和时间中增加1小时

时间:2018-09-17 13:22:56

标签: awk

我有一个用逗号分隔的输入文件,其中有7列,其中:

  • 第3列是日期,格式为yyyymmdd
  • 第4列是HHMMSS格式的时间。

我想通过在合并的日期时间格式中添加一小时来更新这两列。这意味着:

  • 如果HH <23,仅更新第四列
  • 如果HH> = 23,请在移至第二天的同时更新两列。

下面您将找到我的尝试之一,其中包含输入和预期输出。

评论:正如下面的评论中指出的那样,我无权访问GNU awk。因此,当我使用时间函数strftime

时,我的尝试失败了
awk 'BEGIN { FS=OFS="," }                 
     {
        if($4<230000)                    
            $4=sprintf("%06d",$4+10000)
        else
           {
             $4=sprintf("%06d",$4-230000)
             $3+=86400  
            }
            print                                             
      }' Test.txt > A.txt

样本数据:

1039,1018,20180915,000000,0,0,A
1039,1018,20180915,010000,0,0,A
1039,1018,20180915,020000,0,0,A
1039,1018,20180915,030000,0,0,A
1039,1018,20180915,240000,0,0,A

预期输出:

1039,1018,20180915,010000,0,0,A
1039,1018,20180915,020000,0,0,A
1039,1018,20180915,030000,0,0,A
1039,1018,20180915,040000,0,0,A
1039,1018,20180916,010000,0,0,A

4 个答案:

答案 0 :(得分:3)

使用系统命令将1天添加到第3列

awk '
BEGIN { FS=OFS="," }
{
    if($4<230000)
        $4=sprintf("%06d",$4+10000)
    else {
         $4=sprintf("%06d",$4-230000)
         date="$( date -d '19500101')";
         #print strftime("%Y%m%d",$3);
         #$3+=86400


         # # GNU date
         # $3 = strftime("%Y%m%d", (24*3600)+mktime(substr($3,1,4)" "substr($3,5,2)" "substr($3,7)" 00 00 00"))

         # BSD date
         $3=((sprintf("date -j -v+1d -f \"%%Y%%m%%d\" %s \"+%%Y%%m%%d\"", $3) | getline line) > 0 ? line: "INVALID DATE" )
    }
    print
 }' Test.txt

date命令是GNU date。参见GNU Coreutils: date invocation

如果您在macOS上运行此脚本,请确保已安装coreutils。如果没有,请使用brew进行安装。

brew install coreutils

更新

不再使用date命令。结合@ ExpertNoob1的答案。

awk '
BEGIN { FS=OFS="," }
{
    if($4<230000)
        $4=sprintf("%06d",$4+10000)
    else {
         $4=sprintf("%06d",$4-230000)
         date="$( date -d '19500101')";
         #print strftime("%Y%m%d",$3);
         #$3+=86400
         $3 = strftime("%Y%m%d", (24*3600)+mktime(substr($3,1,4)" "substr($3,5,2)" "substr($3,7)" 00 00 00"))
    }
    print
 }' Test.txt

答案 1 :(得分:2)

在没有可用的GNU awk扩展的情况下,我认为这可能就是您真正想要的。

#!/usr/bin/awk -f

BEGIN {
  OFS=FS=","
  split("31 28 31 30 31 30 31 31 30 31 30 31", days, " ")
}

{
  # Add one hour to the current time
  $4=sprintf("%06d", $4 + 10000 )

  # Is this a leap year?
  year=substr($3,1,4)
  if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
    days[2]=29
  } else {
    days[2]=28
  }
}

# too many hours
$4 >= 240000 {
  $3=$3 + int($4/240000)           # add days for sets of 24 hours
  $4=sprintf("%06d", $4 % 24000 )  # reduce time to < 24 hours

  # too many days
  if (substr($3,7,2) > days[substr($3,5,2)+0]) {
    $3=sprintf( "%04d%02d%02d", substr($3,1,4), substr($3,5,2)+1, substr($3,7,2)-days[substr($3,5,2)+0] )

    # too many months
    if (substr($3,5,2) > 12) {
      $3=sprintf( "%04d%02d%02d", substr($3,1,4)+1, substr($3,5,2)-12, substr($3,7,2) )
    }
  }
}

# print the line
1

这会从最小的单元到最大的单元逐步进行重大超量。显然可以将其压缩一点。事情散布开来进行评论。

  • 如果我们有太多的时间,则将它们作为天添加到日期的“天”部分。
  • 如果当前月份的天数过多,我们将增加月份。
  • 如果一年中的月份过多,我们会增加这一年。

似乎可以处理您的数据。以及大约leap年的日期和时间。我没有进一步测试。

请注意,它没有考虑DST转换或leap秒。

答案 2 :(得分:2)

好像我对您的情况读得不够仔细。正如一些人指出的那样,这是使用GNU awk的替代解决方案。

  #!/usr/bin/awk -f

    BEGIN { FS=OFS="," }
    {
        if($4<230000)
            $4=sprintf("%06d",$4+10000)
        else
           {
             $4=sprintf("%06d",$4-230000)
             year=substr($3, 1,4)
             month=substr($3, 5,2)
             day=substr($3, 7,2)
             dstr=year " " month " " day " 00 00 00"
             dstamp=mktime(dstr)
             dstamp+=86400
             $3=strftime("%Y%m%d",dstamp)
            }
            print
     }

$ ./script.awk Test.txt

1039,1018,20180915,010000,0,0,A
1039,1018,20180915,020000,0,0,A
1039,1018,20180915,030000,0,0,A
1039,1018,20180915,040000,0,0,A
1039,1018,20180916,010000,0,0,A

答案 3 :(得分:1)

$3 = strftime("%Y%m%d", (24*3600)+mktime(substr($3,1,4)" "substr($3,5,2)" "substr($3,7)" 00 00 00"))