如何为存储在变量中的日期/时间添加间隔

时间:2018-07-23 13:57:24

标签: linux bash datetime

我正在Fedora 27机器上编写bash脚本。该脚本会定期运行Python程序,偶尔显示进度消息。除了在行中添加时间间隔并将其添加到存储在变量中的时间之外,该行均有效。

有人知道如何做到这一点吗?

这是脚本的最低版本。

#!/usr/bin/env bash

next_run_dat=${1}
echo -n 'Next run will be at: ';echo ${next_run_dat}

now_dat=`date +'%Y-%m-%d %H:%M:%S'`
echo -n 'The time is now: ';echo ${now_dat}

while [[ ${now_dat} < ${next_run_dat} ]]
do
    sleep 10
    now_dat=`date +'%Y-%m-%d %H:%M:%S'`
    echo -n 'The time is now: ';echo ${now_dat}
done

while true
do
    echo 'This line represents a run.'
    sleep 5

    # ==> PROBLEM LINE BELOW <==
    next_run_dat=$(date -d "${next_run_dat} + 25 seconds" +'Y-%m-%d %H:%M:%S')
    echo -n 'Next run will be at: ';echo ${next_run_dat}

    now_dat=`date +'%Y-%m-%d %H:%M:%S'`
    echo -n 'The time is now: ';echo ${now_dat}

    while [[ ${now_dat} < ${next_run_dat} ]]
    do
        sleep 5
        now_dat=`date +'%Y-%m-%d %H:%M:%S'`
        echo -n 'The time is now: ';echo ${now_dat}
    done
done

这是运行最低版本的输出:

$ bash control_bash_minimal.sh '2018-07-23 09:38:00'
Next run will be at: 2018-07-23 09:38:00
The time is now: 2018-07-23 09:37:36
The time is now: 2018-07-23 09:37:46
The time is now: 2018-07-23 09:37:56
The time is now: 2018-07-23 09:38:06
This line represents a run.
date: invalid date ‘2018-07-23 09:38:00 + 25 seconds’
Next run will be at: 
The time is now: 2018-07-23 09:38:11
This line represents a run.
Next run will be at: Y-07-23 09:38:41
The time is now: 2018-07-23 09:38:16
^C

非常感谢您对此问题的帮助。

3 个答案:

答案 0 :(得分:3)

输入格式将+用于两个不同的目的:在时间戳中指定时区,并指定相对于时间戳的相对增量。在您的情况下,date尝试将25 seconds解析为时区。如果您指定了明确的时区,则可以添加偏移量:

$ date -d "2018-07-23 09:38:00"
Mon Jul 23 09:38:00 EDT 2018

$ date -d "2018-07-23 09:38:00 + 25 seconds"
date: invalid date ‘2018-07-23 09:38:00 + 25 seconds’

# I used a minus sign here to make the output match
# the first example...
$ date -d "2018-07-23 09:38:00-0400 + 25 seconds"
Mon Jul 23 09:38:25 EDT 2018

# ... but positive timezone offsets work too
# (Note that date uses the timezone to parse the
#  input, but converts the result to your local
#  timezone.)
$ date -d "2018-07-23 09:38:00+0100 + 25 seconds"
Mon Jul 23 04:38:25 EDT 2018

也许可以在不添加我不知道的明确时区的情况下进行歧义消除。

答案 1 :(得分:2)

注释:这是对chepner's answer

的扩展注释

摘自GNU coreutils的手册:

  

组合的日期和时间项   ISO 8601日期和时间扩展格式由ISO 8601日期,“ T”字符分隔符和ISO 8601时间组成。如果将“ T”替换为空格,则也可以识别这种格式。

     

在这种格式下,一天中的时间应使用24小时表示法。允许小数秒,小数点前可以带逗号或句点。不支持ISO 8601的分钟和小时分数。通常,主机支持纳秒级的时间戳分辨率;多余的精度会被静默丢弃。

可悲的是,他们没有提及是否应包括时区。

尝试解开source code和用过的GNUlib给我一种chepner是正确的感觉。符号的双重用法使日期解析器失效。更准确地说,它假设+-之后的第一个数字是时区偏移量,以小时为单位。通常,时区的格式为+HH:MM-HH:MM,但是单个数字将其实现为+HH:00。显然,该数字必须小于或等于24。例如:

$ TZ=UTC date -d "2018-07-23T09:38:00 + 9 seconds"
Mon 23 Jul 00:38:01 UTC 2018
$ TZ=UTC date -d "2018-07-23T09:38:00 + 9 2 seconds"
Mon 23 Jul 00:38:02 UTC 2018

此处,假定日期为UTC + 09:00,然后转换为UTC,并以一秒为单位递增,在第二种情况下为2秒。

OP的示例失败,因为假设+ 25 seconds为UTC + 25:00,但这是无效的时区:

$ date -d "2018-07-23T09:38:00 + 25 seconds"
date: invalid date ‘2018-07-23T09:38:00 + 25 seconds’

那么,如何增加相对时间而不落入TZ陷阱?

日期解析器期望相对时间使用带符号或无符号的数字。因此,我们实际上并不需要添加加号,因此可以通过删除+符号来利用它来增加时间:

$ date -d "2018-07-23T09:38:00 25 seconds"
Mon 23 Jul 09:38:25 UTC 2018

这仅在您添加相对时间时有效,而在您减去时不起作用。但同样,我们可以通过在解析器中添加前零秒,几小时或几天或任何零天来欺骗解析器:

$ date -d "2018-07-23T09:38:00 - 25 seconds"
date: invalid date ‘2018-07-23T09:38:00 - 25 seconds’
$ date -d "2018-07-23T09:38:00 0 hours - 25 seconds"
Mon 23 Jul 09:37:35 UTC 2018

您还可以使用关键字nextprev

$ date -d "2018-07-23T09:38:00 next 25 seconds"
Mon 23 Jul 09:38:25 UTC 2018
$ date -d "2018-07-23T09:38:00 prev 25 seconds"
Mon 23 Jul 09:37:35 UTC 2018

如果时区不是很重要,只需在UTC中运行,只需在字符串末尾添加Z

$ date -d "2018-07-23T09:38:00Z + 25 seconds"
Mon 23 Jul 09:38:25 UTC 2018

但是最简单的方法是使用浮点数。由于时区的时区为HH:MM,浮点数不能解释为时区,因此

$ date -d "2018-07-23T09:38:00 + 25.0 seconds"
Mon 23 Jul 09:38:25 UTC 2018
$ date -d "2018-07-23T09:38:00 - 25.0 seconds"
Mon 23 Jul 09:37:35 UTC 2018

答案 2 :(得分:1)

您可以使用BASH算术将日期转换为EPOCH秒,并且不添加秒数:

dt='2018-07-23 09:38:00'
newdt=$(date -d "@$(( $(date -d "$dt" +%s) + 25))" +'%Y-%m-%d %H:%M:%S')

echo "$newdt"

2018-07-23 09:38:25