【问题标题】:BASH looping though timeBASH 循环时间
【发布时间】:2017-05-04 10:28:21
【问题描述】:

使用 BASH,我想以十分钟的间隔从开始日期循环到结束日期。 我试过了

begin_date="2015-01-01 00:00:00"
end_date="2015-02-20 00:00:00"
d=$begin_date
while [ "$d" != "$end_date" ]; do
    echo $d
    d=$(date -d "${d} + 10 min" +"%Y-%m-%d %H:%M")
done

但它没有用。看着Bash:Looping thru dates

#This works
d=$(date -I -d "${d} + 1 day")

#This doesn't work
d=$(date -d "${d} + 1 day" +"%Y-%m-%d")

我在格式字符串中遗漏了什么?

【问题讨论】:

  • 定义“它不起作用”。它产生什么输出?
  • 它没有增加十分钟或一天。
  • 你链接到的问题具体解释了为什么-I很重要,但你还是把它拿出来了。

标签: bash date for-loop time increment


【解决方案1】:

表达式date -d "${d} + 10 min" 似乎不会产生偏移量为 10 分钟的日期。事实上,当我运行您的代码时,我看到一个日期计数器在倒退。(将此诊断作为您问题的一部分发布将有助于其他人了解问题所在;您不应该要求其他人运行您的代码只是为了看看它做了什么。)

无论如何,明智的做法是将日期转换为Unix epoch,然后从那里获取。

for ((d=$(date -d "$begin_date" +%s); d <= $(date -d "$end_date" +%s); d += 600))
do
    date -d @$d +"%F %H:%M"
done

在 shell 中进行日期运算可能会相当低效;将其转换为例如如果您发现 Awk 或 Perl 太慢或需要运行很多次,那么可能值得您花时间。

【讨论】:

  • 谢谢,代码完美运行。已经与它战斗了大约8个小时!我不得不谷歌时代才能理解你的答案:-)
  • 感谢您的反馈;添加了一个维基百科链接。
  • 我在说+10 min时也经历了这种罕见的时间倒流
  • 我认为+10 min 似乎有时间倒退的原因是+10 部分被解析为时区规范,如果T00:00 或类似的存在于时间戳中。 date -d '2015-01-01T00:00 + 10 + 20 minutes' 给了我Wed Dec 31 15:20:00 CET 2014,所以时间明显提前了 9 小时,因为 CET 是 +1,我要求 +10,然后按规定提前 20 分钟。
【解决方案2】:

你链接的例子只需要稍微调整一下:

#!/bin/bash

## User-specified dates.
# See [GNU Coreutils: Date] for more info
# [GNU Coreutils: Date]: https://www.gnu.org/software/coreutils/manual/html_node/Combined-date-and-time-of-day-items.html#Combined-date-and-time-of-day-items
begin_date="2015-01-01T00:00"
end_date="2015-01-01T00:40"

# Run through `date` to ensure iso-8601 consistency
startdate=$(date --iso-8601='minutes' --date="${begin_date}")
enddate=$(date --iso-8601='minutes' --date="${end_date}")

# Do loop
d="$startdate"
while [ "$d" != "$enddate" ]; do 
  echo $d
  d=$(date --iso-8601='minutes' --date="$d + 10 minutes")
done

请注意,-I-d 选项分别等效于 --iso-8601--date

【讨论】:

  • 谢谢,Sigve,您的回答也有效。不确定我是否可以将多个答案打勾。
  • 在进一步测试中,我改变接受 Sigve 的回答。我运行了这两种方法一个月。 Sigve 的速度稍微快一些(虽然不是很多)@tripleee 的真实 1m1.310s 用户 0m1.156s sys 0m55.953s vs Sigve 的真实 0m57.308suser 0m0.953s sys 0m52.250s 但是,我改变答案的原因是我需要从日期派生的四个变量(旧/新路径 (YYYYMMDD) 和旧/新名称 foo_HHMM),上面的代码很容易重新格式化日期,而其他代码则不然。
  • 对开始日期和结束日期的小幅修正。不要使用 Z(即 UTC)。 code begin_date="2015-01-01T00:00" end_date="2015-01-01T00:40" code
猜你喜欢
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 2016-05-13
  • 2019-07-29
相关资源
最近更新 更多