我试图在 2 个时间戳值之间生成一个间隔为 30 分钟的时间戳系列。
这是我已经准备好的。
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’
答案1
您的具体问题是被+ 30
解释为无效的时区。
您可以通过使用 UTC 时间来解决这个问题(这也可以避免 DST 更改带来的问题)并使用:
date -ud "$start_ts +0 + 30 minutes" +'%Y%m%d %T'
(注意 +0 指定与 UTC 偏移量为 0 的时区,因此下一个+30 minute
被解释为偏移量)。
或者,要仍然使用本地时间,请在时间戳之后插入today
或now
,以确保后面的内容被解释为偏移量:
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
不是一个标准命令,但是当您拥有 GNU 时date
,您还将拥有 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
) 以使时间戳不模糊(假设您的时区偏移量始终为整整几分钟,现在到处都是这种情况)。