我想用date
它来计算 Raspberry Pi 上实时时钟的一些未来“闹钟时间”。这些“警报时间”将用于“唤醒”RPi。
我决定使用的方案如下:
启动后,我立即以我选择的格式获得当前的“基线”时间:
$ BASETIME=$(date "+%D %X") $ echo $BASETIME 05/03/21 14:03:43
之前
shutdown
,我需要从“基线”时间计算出至少一个“唤醒闹钟时间”;例如,距 BASETIME 6 小时。据我了解,-d
or--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
笔记:
我在花时间提出问题后找到了这个答案。我将其发布在这里希望对其他人有所帮助。