使用日期时,如何指定指定日期包含小时/分钟/秒的相对日期

时间:2017-01-19 13:40:00

标签: linux bash date scripting

在Bash中,我想计算日期(接收日期)和相对持续时间(保留持续时间)之和。

例如,让:

reception_date="2017-01-02 12:34:56"
retention_duration="+2 days"

我希望有:

expiration_date="2017-01-04--12-34-56"

请注意,保留期限可以是按日期识别的任何有效相对日期,例如+X weeks+X hours

我对date信息页面的第一次掌握让我使用date这样的

$ date -d '2017-01-02 12:34:56' +'%Y-%m-%d--%H-%M-%S'
2017-01-02--12-34-56
$ date -d '2017-01-02 12:34:56 +1 days' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--12-34-56
$ date -d '2017-01-02 12:34:56 +2 days' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--11-34-56
$ date -d '2017-01-02 12:34:56 +3 days' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--10-34-56
$ date -d '2017-01-02 12:34:56 +4 days' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--09-34-56
$ date -d '2017-01-02 12:34:56 +5 days' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--08-34-56

正如您所看到的,它似乎适用于+1 days,但是对于更高的值,我得到了非常不规则的结果。

以下示例按预期工作,但可读性较差:

$ date -d '2017-01-02 +1 days 12:34:56' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--12-34-56
$ date -d '2017-01-02 +2 days 12:34:56' +'%Y-%m-%d--%H-%M-%S'
2017-01-04--12-34-56
$ date -d '2017-01-02 +3 days 12:34:56' +'%Y-%m-%d--%H-%M-%S'
2017-01-05--12-34-56
$ date -d '+1 days 2017-01-02 12:34:56' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--12-34-56
$ date -d '+2 days 2017-01-02 12:34:56' +'%Y-%m-%d--%H-%M-%S'
2017-01-04--12-34-56
$ date -d '+3 days 2017-01-02 12:34:56' +'%Y-%m-%d--%H-%M-%S'
2017-01-05--12-34-56

在理想的解决方案中,我希望:

  • 正确的expiration_date
  • 可读的相对日期格式(向用户解释计算此到期日期的方式和原因)。

我不想玩秒转换等等,解决方案的人性化可读性是强制性的。

谢谢!

更多信息

我在RedHat上,日期版本:

$ date --version
date (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by David MacKenzie.

1 个答案:

答案 0 :(得分:2)

修订答案

this downstream bug-report comment开始,我发现您可以通过添加now来实现此目的:

$ date -d '2017-01-02 12:34:56 +2 days' +'%Y-%m-%d--%H-%M-%S'
2017-01-03--05-34-56      ## Oops
$ date -d '2017-01-02 12:34:56 now +2 days' +'%Y-%m-%d--%H-%M-%S'
2017-01-04--12-34-56      ## Much better

now阻止date+2解析为时区规范 以及 相对项< / strong>即可。两者之间的差异在the docs中解释,但在这种情况下,解析器显然有点奇怪。我想&#34;现在&#34;从人的角度来看也很奇怪,但可能更糟糕!

要查看date正在做什么,请在--debug命令中添加date标志。请参阅下面的完整说明。

原始答案

至少截至目前(仍然是date版本8.26),您必须将相对时间项目放在除时间之外的其他位置。问题是+ 1 hour被解释为两者作为相对时间作为时区(!!!!)。 --debug的{​​{1}}标记是您的朋友。

正确行为示例(cygwin,date v8.26;我的评论已添加):

date

错误行为的示例:

$ date --debug -d '+1 hour 2017-01-19 12:34:56'    ## Relative before the time
date: parsed relative part: +1 hour(s)             ## OK
date: parsed date part: (Y-M-D) 2017-01-19
date: parsed time part: 12:34:56
date: input timezone: -05:00 (set from TZ="America/New_York" environment value)  ## Also OK
date: using specified time as starting value: '12:34:56'
date: starting date/time: '(Y-M-D) 2017-01-19 12:34:56 TZ=-05:00'
date: '(Y-M-D) 2017-01-19 12:34:56 TZ=-05:00' = 1484847296 epoch-seconds
date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns),
date:     new time = 1484850896 epoch-seconds
date: output timezone: -05:00 (set from TZ="America/New_York" environment value)  ## Still OK
date: final: 1484850896.000000000 (epoch-seconds)
date: final: (Y-M-D) 2017-01-19 18:34:56 (UTC0)
date: final: (Y-M-D) 2017-01-19 13:34:56 (output timezone TZ=-05:00)
Thu, Jan 19, 2017  1:34:56 PM                 ## A sensible result

我猜你在UTC + 1时区,所以date(1)将$ date --debug -d '2017-01-19 12:34:56 + 1 hour' # +1 hour at the _end_ date: parsed date part: (Y-M-D) 2017-01-19 date: parsed time part: 12:34:56 TZ=+01:00 ## TZ=+1 oops! date: parsed relative part: +1 hour(s) ## Parsed as a relative part also! date: input timezone: +01:00 (set from parsed date/time string) ##Oops date: using specified time as starting value: '12:34:56' date: starting date/time: '(Y-M-D) 2017-01-19 12:34:56 TZ=+01:00' ##Oops date: '(Y-M-D) 2017-01-19 12:34:56 TZ=+01:00' = 1484825696 epoch-seconds date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns), date: new time = 1484829296 epoch-seconds date: output timezone: -05:00 (set from TZ="America/New_York" environment value) ## That's OK date: final: 1484829296.000000000 (epoch-seconds) date: final: (Y-M-D) 2017-01-19 12:34:56 (UTC0) date: final: (Y-M-D) 2017-01-19 07:34:56 (output timezone TZ=-05:00) Thu, Jan 19, 2017 7:34:56 AM ## Bogus! 解释为UTC + 1:00时区并没有伤害你。 修改has been reportedgnulib但似乎没有修补,因此您可能只需要使用已经遇到的解决方法。好消息是,您不必向用户+1 days提供相同的字符串。例如,

date

请注意rel="+2 days" base="$(date)" exp="$(date -d "$rel $base") echo "$base $rel is $exp" $base的顺序在最后两行中交换。

另一种选择当然是将所有内容切换为UTC,以便您可以说$rel(使用date --debug -d '2017-01-19 12:34:56 Z + 1 hour')来强制相关部分被解释为。