bash脚本遍历日期被卡住了吗?

时间:2020-03-12 01:33:41

标签: bash time

我正在使用下面的bash脚本启动python程序。它完全按照我的期望遍历日期/时间。但是,然后它被卡在了``2018-11-04 01:45:00''。将15分钟添加到“ 2018-11-04 01:45:00”将返回“ 2018-11-04 01:00:00”,而不是“ 2018-11-04 02:00:00”。有人遇到过吗?

    #!/bin/bash

    dEND=$(date +"%F %T" -d "2020-03-15 00:00:00")
    dCUR=$(date +"%F %T" -d "2018-11-04 01:00:00")
    echo $dCUR $dEND

    typeset -i sEND=1
    typeset -i sCUR=0
    echo $sCUR $sEND

    while( (( $sCUR < $sEND )) );do
       dCUR=$(date +"%F %T" -d "$dCUR 15 minutes")

       typeset -i sEND=$(date +%s -d "$dEND")
       typeset -i sCUR=$(date +%s -d "$dCUR")
       echo $dCUR $dEND $sCUR
    done
    echo done
    $ dCUR=$(date +"%F %T" -d "2018-11-04 00:00:00")
    $ echo $dCUR
    2018-11-04 00:00:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 00:15:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 00:30:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 00:45:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:00:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:15:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:30:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:45:00
    $ dCUR=$(date +"%F %T" -d "$dCUR 15 minutes");echo $dCUR
    2018-11-04 01:00:00

3 个答案:

答案 0 :(得分:2)

我怀疑您(或更准确地说,您的计算机)可能位于百慕大巴哈马(或更准确地说,被配置为 if ) ,巴西,加拿大,古巴,斐济,格陵兰,海地,墨西哥,圣皮埃尔和密克隆群岛,特克斯和凯科斯群岛以及美国。

由于您的个人资料中没有您的位置信息,我无法确定,但是我很想知道我离现实有多近。


您的代码在我的系统上可以正常使用,但是我所在的地理区域无法节省夏令时。

这种转换通常发生在许多地方的凌晨2-3点左右,因此这可能只是您选择的日期的人工产物。从here页开始,似乎确实有几个地方在11月4日做了切换(因此,我在此答案第一段中列出的位置)。

您可以通过运行完全相同的实验(使用11月5日而不是您选择的日期)来确认这一点。您还可以添加%z格式说明符,并且应该看到它从+08变为+07


与世界时间上的 most 问题一样,最好的解决方案是将所有本地时间尽快转换为UTC,并尽可能晚地将其转换为本地时间。这样,除了与最终用户(通常以当地时间来思考)进行交互之外,您通常拥有一致的时间基准。

作为示例,下面是一个脚本,该脚本的运行时间是在该范围内的时区,该脚本的运行时间是从凌晨1点到凌晨5点。

#!/bin/bash

# My region doesn't do DST but New York does, so fake it.

export TZ=America/New_York

# Helper functions for UTC/local conversion.

utcFmt="%F %T %z"
localFmt="%F %T"

utcToLocal() {
    echo "$(date +"${localFmt}" -d "$(date +"${utcFmt}" -d "$1")")"
}

localToUtc() {
    echo "$(date -u +"${utcFmt}" -d "$(date +"${utcFmt}" -d "$1")")"
}

# Init UTC values based on local time.

utcCur="$(localToUtc "2018-11-04 01:00:00")"
utcEnd="$(localToUtc "2018-11-04 05:00:00")"

echo "Going from ${utcCur} to ${utcEnd}"

while [[ "${utcCur}" < "${utcEnd}" ]] ; do
    # Display local time, but adjust UTC time.

    echo "At $(utcToLocal "${utcCur}")"
    utcCur="$(date -u +"${utcFmt}" -d "$utcCur 15 minutes")"
done

从输出中可以看到,有一个回滚到更早的时间,因为这是当您倒转时钟时发生的情况(请参见*标记):

Going from 2018-11-04 01:00:00 to 2018-11-04 05:00:00
At 2018-11-04 01:00:00
At 2018-11-04 01:15:00
At 2018-11-04 01:30:00
At 2018-11-04 01:45:00
At 2018-11-04 01:00:00 * Roll back one hour (once).
At 2018-11-04 01:15:00
At 2018-11-04 01:30:00
At 2018-11-04 01:45:00
At 2018-11-04 02:00:00 * Keep going.
At 2018-11-04 02:15:00
At 2018-11-04 02:30:00
At 2018-11-04 02:45:00
At 2018-11-04 03:00:00
At 2018-11-04 03:15:00
At 2018-11-04 03:30:00
At 2018-11-04 03:45:00
At 2018-11-04 04:00:00
At 2018-11-04 04:15:00
At 2018-11-04 04:30:00
At 2018-11-04 04:45:00

而且,如果您在夏令时的 other 结束时(一个小时消失了),您也可以看到它(再次注意*标记):< / p>

utcCur="$(localToUtc "2018-03-11 01:00:00")"
utcEnd="$(localToUtc "2018-03-11 05:00:00")"

Going from 2018-03-11 01:00:00 to 2018-03-11 05:00:00
At 2018-03-11 01:00:00
At 2018-03-11 01:15:00
At 2018-03-11 01:30:00
At 2018-03-11 01:45:00
At 2018-03-11 03:00:00 * Put clock foward one hour.
At 2018-03-11 03:15:00
At 2018-03-11 03:30:00
At 2018-03-11 03:45:00
At 2018-03-11 04:00:00
At 2018-03-11 04:15:00
At 2018-03-11 04:30:00
At 2018-03-11 04:45:00

答案 1 :(得分:1)

2018-11-04是11月的第一个星期日。目前,在夏令时和标准时间之间切换的北美地区和附近地区,在11月的第一个星期日(以及3月的第二个星期日,用于其他过渡)进行切换。这意味着在11月,时间从xDT的01:59:59变为xST的01:00:00(弹簧前进;后退)。加法和结果是正确的,即使这不是您期望的。

目前在欧洲切换的地点会在3月的最后一个星期日前进,然后在10月的最后一个星期日回退,因此,春季发生的变化比春季发生的变化晚2到3周,秋季发生的变化比美国提前1周。如果3月1日是星期一至星期四,则间隔为2周;否则,间隔为2周。星期五至星期日,三个星期。

其他国家/地区仍然有不同的规定,有时会受到农历和宗教观察的影响。

答案 2 :(得分:0)

GNU日期格式字符串非常灵活,但从长远来看并不可靠。

要执行所需的操作,请将日期转换为自纪元以来的秒数,添加15*60秒,然后转换回所需的格式。

那将是:

dCUR=$(date -d "@$(($(date --date="$dCUR" +%s) + 15 * 60))" +"%F %T"); echo $dCUR