簡體   English   中英

循環遍歷日期的 bash 腳本卡住了嗎?

[英]bash script looping through dates gets stuck?

我正在使用下面的 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

我懷疑您(或更准確地說,您的機器)可能位於(或更准確地說,配置為好像它位於)巴哈馬、百慕大、巴西、加拿大、古巴、斐濟、格陵蘭、海地、墨西哥、聖皮埃爾密克隆、特克斯和凱科斯群島以及美國。

我不能確定,因為您的個人資料沒有關於您所在位置的信息,但我很想知道我離現實有多近。


你的代碼在我的系統上運行良好,但我的地理區域不做夏令時。

在許多地方,這種轉換往往發生在凌晨 2 點到 3 點左右,因此它可能只是您選擇的日期的產物。 這里的這個頁面來看,似乎有幾個地方確實在 11 月 4 日進行了切換(因此我在此答案的第一段中列出了位置列表)。

您可以通過運行完全相同的實驗來確認這一點,但使用 11 月 5 日而不是您選擇的日期。 您還可以添加%z格式說明符,您應該會看到它從(例如) +08更改為+07


與世界時間的大多數問題一樣,最好的解決方案是盡快將所有本地時間轉換為 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

而且,如果您轉到夏令時的另一端(一個小時消失的地方),您也可以看到(再次注意*標記):

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

2018-11-04 是十一月的第一個星期天。 在夏令時和標准時間之間切換的北美地區和附近地區目前在 11 月的第一個星期日(以及其他過渡的 3 月的第二個星期日)進行。 這意味着在 11 月,時間從 01:59:59 xDT 到 01:00:00 xST(春天向前;后退)。 添加和結果是正確的——即使它不是你所期望的。

歐洲的地方目前在 3 月的最后一個星期天向前轉換,在 10 月的最后一個星期日回落,因此比美國的變化在春季晚 2 或 3 周,在秋季早 1 周。 如果 3 月 1 日是周一至周四,則間隔為 2 周; 周五至周日,3 周。

其他國家仍然有不同的規則,有時會受到農歷和宗教觀察的影響。

GNU 日期格式字符串非常靈活,但從長遠來看是不可靠的。

要執行您想要的操作,請將日期轉換為自紀元以來的秒數,添加15*60秒,然后轉換回您想要的格式。

那將是:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM