Bash

在 2 個值之間生成時間戳

  • August 11, 2021

我試圖以 30 分鐘的間隔在 2 個時間戳值之間生成一個時間戳系列。

這是我已經準備好的。

start_ts='2021-08-07 15:00:00'
end_ts='2021-08-11 05:00:00'

while ! [[ $start_ts > $end_ts ]]; do
   echo $start_ts
   start_ts=$(date -d "$start_ts + 30 minutes" +"%Y%m%d% H%:%M:%S")
done

但我收到這個錯誤。

date: invalid date ‘ 2021-08-07 15:00:00 + 30 minutes’

您的特殊問題是+ 30被解釋為無效時區。

您可以通過在 UTC 時間工作來解決這個問題(這也可以避免 DST 更改的問題)並使用:

date -ud "$start_ts +0 + 30 minutes" +'%Y%m%d %T'

(注意 +0 指定時區與 UTC 的 0 偏移量,因此下一個+30 minute被解釋為偏移量)。

或者,要仍然使用本地時間,在時間戳之後插入todaynow,以確保以下內容被解釋為偏移量:

date -d "$start_ts now + 30 minutes" +'%Y%m%d %T'

雖然在這裡,當您使用 GNU 特定的擴展時,您可以這樣做:

start_ts=$(date -ud '2021-08-07 15:00:00' +%s)
end_ts=$(date -ud '2021-08-11 05:00:00' +%s)

seq -f "@%.0f" "$start_ts" "$((30 * 60))" "$end_ts" |
 date -uf - +'%Y%m%d %T'

避免date每個時間戳執行一個。請注意,這seq不是標準命令,但是當您擁有 GNUdate時,您還將擁有 GNU seq,它是同一個 GNU 軟體包 ( coreutils) 的一部分。

或者使用內置支持時間戳解析和格式化的 zsh shell,這將避免對 GNU 的依賴date

#! /bin/zsh -
zmodload zsh/datetime

format='%Y%m%d %T'
TZ=UTC0 strftime -rs start_ts $format '20210807 15:00:00'
TZ=UTC0 strftime -rs end_ts   $format '20210811 05:00:00'
for ((t = start_ts; t <= end_ts; t += 30 * 60))
 TZ=UTC0 strftime $format $t

請注意,這些可能會生成與您所在時區中的任何時間都不對應的時間戳。比如這裡的英國大陸是沒有2021-03-28 01:30:00的,因為那天我們切換到夏令時,所以掛鐘時間從 00:59:59.99 直接跳到了 02:00:00.00。相反,在 2021 年 10 月 31 日,從 01:00:00 到 02:00:00 的時間戳將出現兩次。那天上面的程式碼仍然會在 00:30:00、01:00:00、01:30:00、02:00:00、02:30:00 迭代,而不會超過 01:00 -> 02 :00 間隔兩次。

如果這不是您想要的,您應該刪除使其與 UTC 時間( 和 )一起工作的部分-u+0但是TZ=UTC0您的格式應該包括時區偏移量 ( %z) 以使時間戳不模棱兩可(假設您的時區偏移量總是整分鐘數,現在到處都是這樣)。

引用自:https://unix.stackexchange.com/questions/664201