【问题标题】:Awk and calculating start time from end time and durationawk 并从结束时间和持续时间计算开始时间
【发布时间】:2015-11-05 10:14:32
【问题描述】:

我有一个包含十进制格式的日期、结束时间和持续时间的文件,我需要计算开始时间。该文件如下所示:

20140101;1212;1.5
20140102;1515;1.58
20140103;1759;.69
20140104;1100;12.5
...

时间 12:12 的持续时间 1.5 表示一个半小时,开始时间为 12:12 - 1:30 = 10:42 AM 或 11:00 - 12.5 = 11:00 - 12:30 = 下午 22:30。有没有一种简单的方法可以在 Awk 中计算这种时间差异,或者它是一种很好的拆分-乘-减-处理-自己重新处理的方法?

由于值以小时和分钟为单位,因此只有分钟很重要,秒可以被丢弃,例如持续时间 1.58 表示 1:34,剩余的 0.8 秒可以被丢弃。

我使用的是 GNU Awk 4.1.3

【问题讨论】:

  • 1.58 是什么意思? 1 小时 34 分钟和几秒钟?更好地展示预期的输出。
  • 您的 awk 版本实际上是 gawk 吗?检查awk --version。祝你好运。

标签: time awk


【解决方案1】:

当您使用gawk 时,请利用其原生time functions

gawk -F\; '{tmst=sprintf("%s %s %s %s %s 00",\
                  substr($1,1,4),\
                  substr($1,5,2),\
                  substr($1,7,2),\
                  substr($2,1,2),\
                  substr($2,3,2))
            t1=mktime(tmst)
            seconds=sprintf("%f",$3)+0
            seconds*=60*60
            difference=strftime("%H%M",t1-seconds)
            print $0""FS""difference}' file

结果

20140101;1212;1.5;1042
20140102;1515;1.58;1340
20140103;1759;.69;1717
20140104;1100;12.5;2230

检查:https://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html

说明:

  • tmst=sprintf(..) :用于从文件中创建日期字符串 符合mktime函数YYYY MM DD HH MM SS [DST]datespec
  • t1=mktime(tmst) :将 datespec 转换为时间戳而不是 可以 由gawk 处理(从 1 开始经过的秒数) 1970 年 1 月)
  • seconds=sprintf("%f",$3)+0 :将第三个字段转换为浮点数。
  • seconds*=60*60 :将小时(浮点数)转换为秒。
  • difference=strftime("%H%M",t1-seconds) :获取差异 人的方式,几小时一分钟。

【讨论】:

  • 谢谢您,先生。我实际上尝试过使用 mktime,但在第四行得到了负值。我一定是搞错了。
  • 很可能是奇怪字符问题..尝试在文件中手动输入整行
【解决方案2】:

我强烈建议使用支持日期时间计算的编程语言,因为夏令时会发生变化,因此计算的细节可能会很棘手。例如,您可以使用 Python:

start_times.py

import csv
from datetime import datetime, timedelta

with open('input.txt', 'rb') as csvfile:
    reader = csv.reader(csvfile, delimiter=';', quotechar='|')
    for row in reader:

        end_day = row[0]
        end_time = row[1]
        # Create a datetime object
        end = datetime.strptime(end_day + end_time, "%Y%m%d%H%M")

        # Translate duration into minutes
        duration=float(row[2])*60

        # Calculate start time
        start = end - timedelta(minutes=duration)

        # Column 3 is the start day (can differ from end day!)
        row.append(start.strftime("%Y%m%d"))
        # Column 4 is the start time
        row.append(start.strftime("%H%M"))

        print ';'.join(row)

运行:

python start_times.py

输出:

20140101;1212;1.5;20140101;1042
20140102;1515;1.58;20140102;1340
20140103;1759;.69;20140103;1717
20140104;1100;12.5;20140103;2230  <-- you see, the day matters!

上面的例子是使用系统的时区。如果输入数据指向不同的时区,Pyhon 的 datetime 模块允许指定它。

【讨论】:

  • 非常好的 Python sn-p!将import pdb 移到开头可能更好,而不是每次循环时都导入它。
  • @fedorqui 这只是为了调试! :) 谢谢。 pdb.set_trace() 真不错!
  • 哇,我从来没有听说过这个模块,真的很高兴知道它:)
【解决方案3】:

我会这样做:

awk 'BEGIN{FS=OFS=";"}
     { h=substr($2,0,2); m=substr($2,3,2); mins=h*60 + m; diff=mins - $3*60;
       print $0, int(diff/60) ":" int(diff%60)
     }' file

也就是说,将所有内容转换为分钟,然后再转换回小时/分钟。

测试

$ awk 'BEGIN{FS=OFS=";"}{h=substr($2,0,2); m=substr($2,3,2); mins=h*60 + m; diff=mins - $3*60; print $0, int(diff/60) ":" int(diff%60)}' a
20140101;1212;1.5;10:42
20140102;1515;1.58;13:40
20140103;1759;.69;17:17

【讨论】:

  • 它无法处理例如“20140104;1100;12.5”。它产生“20140101;1100;12.5;-1:-30”。
  • @JamesBrown 然后从一开始就提供更具代表性的输入,以及预期的输出。
  • @JamesBrown 您提供的示例的输出应该是什么?使用此类信息更新您的原始问题
猜你喜欢
  • 1970-01-01
  • 2010-11-22
  • 2017-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 2021-04-10
  • 2019-08-24
相关资源
最近更新 更多