将“date”与“-d”/“--date=”选项一起使用

将“date”与“-d”/“--date=”选项一起使用

我想用date它来计算 Raspberry Pi 上实时时钟的一些未来“闹钟时间”。这些“警报时间”将用于“唤醒”RPi。

我决定使用的方案如下:

  1. 启动后,我立即以我选择的格式获得当前的“基线”时间:

    $ BASETIME=$(date "+%D %X")
    $ echo $BASETIME
    05/03/21 14:03:43
    
  2. 之前shutdown,我需要从“基线”时间计算出至少一个“唤醒闹钟时间”;例如,距 BASETIME 6 小时。据我了解,-dor--date=选项用于此目的,但我没有得到正确的结果:

    $ date '+%D %X' -d "${BASETIME} + 6 hours"
    05/03/21 04:03:43
    

    结果已经过去了!?- 这显然是不正确的(至少不是我想要的:) 彻底阅读man date没有任何启发;它建议:

    日期字符串格式比此处轻松记录的更复杂......

    完整文档 [...] 可通过以下方式在本地获取:info '(coreutils) date invocation'

    但我在这里也没有发现任何有用的东西。

    一个接近的替代方案是:

    $ date "+%D %X" -d '+ 6 hours'
    05/03/21 10:10:11
    

    我可以通过这种方式获得正确的闹钟时间,这是相对于当前时间的,而不是相对于 BASETIME 的。

我的问题是:

  • 为什么date '+%D %X' -d "${BASETIME} + 6 hours" 递减时间而不是增量时间?

  • 从固定的 BASETIME 增加的正确方法是什么?

注意:FWIW,我的操作系统、内核和date版本:

$ date --version
date (GNU coreutils) 8.30
...

$ hostnamectl
...
Operating System: Raspbian GNU/Linux 10 (buster)
          Kernel: Linux 5.10.17-v7+
...

答案1

核心问题是创建的日期字符串BASETIME=$(date "+%D %X")不包含时区。使用BASETIME=$(date "+%D %X %z")将解决您的问题..

对于date '+%D %X' -d "${basetime} + 6 hours"+ 6(或+6+06等)被解释为时区值。

你可以看到它GNU date --debug选项(粗体我的):

$ date '+%D %X %z' -d "${basetime} + 6 hours" --debug
date: warning: value 5 has less than 4 digits. Assuming MM/DD/YY[YY]
date: parsed date part: (Y-M-D) 0021-05-03
date: **parsed time part: 14:03:43 UTC+06**
date: parsed relative part: +1 hour(s)
date: input timezone: parsed date/time string (+06)
date: warning: adjusting year value 21 to 2021
date: using specified time as starting value: '14:03:43'
date: starting date/time: '(Y-M-D) 2021-05-03 14:03:43 TZ=+06'
date: '(Y-M-D) 2021-05-03 14:03:43 TZ=+06' = 1620029023 epoch-seconds
date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns),
date:     new time = 1620032623 epoch-seconds
date: timezone: system default
date: final: 1620032623.000000000 (epoch-seconds)
date: final: (Y-M-D) 2021-05-03 09:03:43 (UTC)
date: final: (Y-M-D) 2021-05-03 05:03:43 (UTC-04)
05/03/21 05:03:43 AM -0400

此外,小时一词被解释为“添加 1 小时”。

如果您使用 TimeZone 值来表示时间,所有问题都会得到解决。
我建议使用%F %T %z以下格式:

$ basetime=$(date "+%F %T %z"); echo "$basetime"
2021-05-03 18:31:43 -0400

$ date '+%F %T %z' -d "${basetime} + 6 hours"
2021-05-04 00:31:43 -0400

这确实是未来的事情。它仍然可以使用“--debug”选项来执行。

避免时区(我不推荐)的解决方法是将相对项 ( +6 hours) 放在静态时间值之前:

$ date -d "+6 hours 2021-05-03 18:31:43"
Tue 04 May 2021 12:31:43 AM EDT

答案2

我还没有找到这个记录,但是诡计似乎是在将date字符串分配给 时使用的格式化顺序BASETIME。换句话说,反转命令of%D和导致在/选项%X下执行的计算产生正确的(希望的)结果:-d--date=

$ BASETIME=$(date "+%X %D")
$ echo $BASETIME
15:00:28 05/03/21

$ date '+%D %X' -d "${BASETIME} + 6 hours"
05/03/21 21:00:28 
# note that the output format need not be the same as the `BASETIME` format

$ date '+%D %X' -d "${BASETIME} + 24 hours"
05/04/21 15:00:28 
# note that the date advances correctly 

$ date '+%D %X' -d "${BASETIME} + 15 minutes"
05/03/21 15:15:28

$ date '+%D %X' -d "${BASETIME} + 6 months"
11/03/21 15:00:28

$ date '+%D %X' -d "${BASETIME} + 26 weeks"
11/01/21 15:00:28

笔记:

我在花时间提出问题后找到了这个答案。我将其发布在这里希望对其他人有所帮助。

相关内容