以自定义格式减去日期

以自定义格式减去日期

我需要从当前日期中减去一些日期来确定某些连接的年龄。日期的格式如下:YYMMDDHHMISS。输出几乎可以是我可以用来确定的任何内容,例如最旧的连接、超过 1 小时、1 周、1 个月的连接数。

输入日期示例:211013134247

我已经从date命令 ( date '+%g%m%d%H%M%S') 获取这种格式的日期,但我不知道如何正确减去它以获得准确的结果。


我尝试了这个,但是一旦连接日期中的一个数字(如秒)大于当前日期,就会出现问题。示例:连接秒数为 53,当前秒数为 47。

$line = 连接日期
$date = 当前日期

  year=   $((${date:0:2} - ${line:0:2}))
  month=  $((${date:2:2} - ${line:2:2}))
  day=    $((${date:4:2} - ${line:4:2}))
  hour=   $((${date:6:2} - ${line:6:2}))
  minute= $((${date:8:2} - ${line:8:2}))
  second= $((${date:10:2} - ${line:10:2})) 

  age=$year$month$day$hour$minute$second

我也尝试过这个(一些代码无耻地从堆栈交换中窃取),但输出是错误的。我期望类似:0607********,如6年7个月等。输入日期通常不应相隔数年,因此年份计算可以被排除在外。

date="211013150325"
line="150325113419"
convert_date(){ printf `date '+%C'`'%s-%s-%s %s:%s:%s' ${1:0:2} ${1:2:2} ${1:4:2} ${1:6:2} ${1:8:2} ${1:10:2}; }
diff_dates(){
    TS1=$(date -d "$1" +%s)
    TS2=$(date -d "$2" +%s)
    TZ=UTC date -d @$((TS1-TS2)) +%g%m%d%H%M%S
    #+%Y.%m.%d.%H:%M:%S
}

date_converted=`convert_date $date`
echo $date_converted
line_converted=`convert_date $line`
echo $line_converted
diff_dates $date_converted $line_converted

root@SomeHost:~# date="211013150325"
root@SomeHost:~# line="150325113419"
root@SomeHost:~# convert_date(){ printf `date '+%C'`'%s-%s-%s %s:%s:%s' ${1:0:2} ${1:2:2} ${1:4:2} ${1:6:2} ${1:8:2} ${1:10:2}; }
root@SomeHost:~# diff_dates(){
>     TS1=$(date -d "$1" +%s)
>     TS2=$(date -d "$2" +%s)
>     TZ=UTC date -d @$((TS1-TS2)) +%g%m%d%H%M%S
>     #+%Y.%m.%d.%H:%M:%S
> }
root@SomeHost:~# 
root@SomeHost:~# date_converted=`convert_date $date`
root@SomeHost:~# echo $date_converted
2021-10-13 15:03:25
root@SomeHost:~# line_converted=`convert_date $line`
root@SomeHost:~# echo $line_converted
2015-03-25 11:34:19
root@SomeHost:~# diff_dates $date_converted $line_converted
701231085635

我可以删除TZ=UTC date -d @$((TS1-TS2)) +%g%m%d%H%M%S并使用其他东西获得更好的转化吗?我可以得到以echo $(($TS2-$TS1))秒为单位的时间,但我不知道如何将其转换为不以 1970 年开头的日期......


也许(几乎可以肯定)我这样做是完全错误的,并且有更简单的方法可以做到这一点。
我花了两个多小时把这个问题拼凑起来,所以如果有什么地方没有意义,请指出,我会尽力解决它。

答案1

zsh

zmodload zsh/datetime
timestamp=211013134247
strftime -rs t %y%m%d%H%M%S $timestamp
print $(( EPOCHSECONDS - t ))

请注意,这%g是 iso 周年,而不是您要寻找的。例如,2021 年 1 月 1 日(这里是date该非标准的 GNU 实现-d):

$ date -d 2021-01-01 +%gW%V-%A
20W53-Friday

这是 2020 年 ISO 第 53 周的星期五,因为该周 2020 年的天数多于 2021 年的天数,因此被算作 2020 年的一周,而不是 2021 年的一周。

您只想将%g/%G%V(ISO 周数)结合使用。%y/%Y是当前年份。

标准date不支持解析日期并重新格式化它们以进行输出(而不是设置系统时间)。他们中的一些人以不同且不兼容的方式支持将其作为扩展。在那些这样做的实现中,大多数实现都支持在 style 中指定输入格式strptime()(如上面zshstrftime内置-r),但 GNUdate是一个值得注意的例外。

  • ast-open datedate(如果在编译时启用,也是 ksh93 的内置命令):

    $ date -p %y%m%d%H%M%S -d 211013134247 +%FT%T%z
    2021-10-13T13:42:47+0100
    $ date -p %y%m%d%H%M%S -d 211013134247 +%s
    1634128967
    
  • busybox date

    $ date -D '%y%m%d%H%M%S' -d 211013134247 +%FT%T%z
    2021-10-13T13:42:47+0100
    $ date -D '%y%m%d%H%M%S' -d 211013134247 +%s
    1634128967
    
  • BSD date

    $ date -jf %y%m%d%H%M%S 211013134247 +%FT%T%z
    2021-10-13T13:42:47+0100
    $ date -jf %y%m%d%H%M%S 211013134247 +%s
    1634128967
    

对于 GNU date,您需要将时间戳转换为其支持的格式之一。

可以是标准 2021-10-13T13:42:47 格式:

$ timestamp=211013134247
$ date -d "20$(echo "$timestamp" | fold -w2 | paste -sd--T::)" +"%s"
1634128967

(假设年份仅为 2000 年至 2099 年)。

或者使用现在一些 shell 支持的ksh93-style ,包括:${param:offset:length}bash

$ date -d "20${t:0:2}-${t:2:2}-${t:4:2}T${t:6:2}:${t:8:2}:${t:10:2}" +%s
1634128967

答案2

我可以得到以echo $(($TS2-$TS1))秒为单位的时间,但我不知道如何将其转换为日期

您可以使用以下命令将秒转换为小时、分钟、秒:

 date -d@$SECVAR -u +%H:%M:%S

其中变量SECVAR包含秒

相关内容