如果我从当前日期中减去一个时间量,GNU 日期的工作方式很直观:
date '+%F %R'; date '+%F %R' --date='- 1 hour'
2021-04-19 15:35
2021-04-19 14:35
Run Code Online (Sandbox Code Playgroud)
但是,当我使用日期作为操作数时,结果出乎意料:
$ date '+%F %R' --date='2000/1/2 03:04:05 - 1 hour'
2000-01-02 06:04
$ date '+%F %R' --date='2000/1/2 03:04:05 + 1 hour ago'
2000-01-02 02:04
Run Code Online (Sandbox Code Playgroud)
怎样date
理解$date - 1 hour
表达?
ilk*_*chu 19
简而言之:--date
除非您指定时区,否则您给出的日期是当地时间+/- NNN
。只有在此之后的任何东西,即使它只是hour
被视为相对修饰符。所以- 1 hour
并不意味着从给定的时间中减去一小时,而是指定时间在时区 UTC-01 中,然后再增加一小时。
我认为应该适用于您正在尝试的内容,要么在偏移量之前明确给出时区,要么将偏移量放在首位,以免与时区混淆。
在这里,使用中欧夏令时时区 (CEST) 和今天的日期,并%Z
添加到输出中以显示时区。(你也可以%z
用来输出数字时区,或者+0200
在这里。)
$ date +'%F %T %Z' -d '2021-04-19 12:00:00 CEST + 5 hours'
2021-04-19 17:00:00 CEST
$ date +'%F %T %Z' -d '+ 5 hours 2021-04-19 12:00:00'
2021-04-19 17:00:00 CEST
Run Code Online (Sandbox Code Playgroud)
当然,对于问题中的一月日期,像 CEST 这样的夏季时区将是无效的。但是重新排列两者仍然有效,您给出的时间只是当时的当地时间。
$ date +'%F %T %Z' -d '+ 5 hours 2021-01-01 12:00:00'
2021-01-01 17:00:00 CET
Run Code Online (Sandbox Code Playgroud)
(因为2021-10-31 02:30:00
我得到了 CET,即使那个时间也存在于 CEST 中......)
(有关如何解释各种输入的更多示例,请参阅此答案的旧版本。)
根据@muru 对另一个问题的回答,我们还可以使用该--debug
选项让程序实际告诉我们它做了什么。注意第二行和第三行:
$ date --debug +'%F %T %Z' -d '2021-04-19 12:00:00 - 1 小时' 日期:解析日期部分:(YMD)2021-04-19 日期:解析时间部分:12:00:00 TZ=-01:00 日期:解析相关部分:+1 小时 日期:输入时区:-01:00(从解析的日期/时间字符串设置) 日期:使用指定时间作为起始值:'12:00:00' 日期:开始日期/时间:'(YMD) 2021-04-19 12:00:00 TZ=-01:00' 日期:'(YMD) 2021-04-19 12:00:00 TZ=-01:00' = 1618837200 纪元-秒 日期:时间调整后(+1 小时,+0 分钟,+0 秒,+0 ns), 日期:新时间 = 1618840800 纪元秒 日期:输出时区:+01:00(从 TZ="Europe/Berlin" 环境值设置) 日期:最终:1618840800.000000000(纪元秒) 日期:最终:(YMD) 2021-04-19 14:00:00 (UTC0) 日期:最终:(YMD)2021-04-19 16:00:00(输出时区 TZ=+01:00) 2021-04-19 16:00:00 CEST
手册页说:
日期字符串格式比此处轻松记录的要复杂 [...]
这确实看起来很贴切。更全面的文档在信息页面或在线:https : //www.gnu.org/software/coreutils/manual/html_node/Date-input-formats.html
是的,当 -d 值很简单时,它的效果很容易理解。
是的,a-d '- 1 hour'
会将时间抵消 1 小时。
$ date ; date -d '- 1 hour'
Mon 19 Apr 2021 07:58:52 AM EDT
Mon 19 Apr 2021 06:58:52 AM EDT
Run Code Online (Sandbox Code Playgroud)
date
生成的字符串指定了“时间点”。
默认情况下,“时间点”以本地时间写入。但它也可以写成 UTC0:
$ date ; date -u
Mon 19 Apr 2021 12:43:04 PM WAT
Mon 19 Apr 2021 11:43:04 AM UTC
Run Code Online (Sandbox Code Playgroud)
假设您的当地时间是 WAT - 西非时间 (WAT)。
当然,相同的“时间点”也可能发生在其他时区:
$ TZ=Asia/Kolkata date -d "Mon 19 Apr 2021 12:43:04 PM WAT"
Mon 19 Apr 2021 05:13:04 PM IST
Run Code Online (Sandbox Code Playgroud)
请注意,-d
值内的内容正是上面打印的日期。
这意味着“时间点”仅在包含时区时才完成。
这就是为什么打印带有%z
或%Z
添加的日期是个好主意的原因。从%F %R
这个意义上说,格式是不完整的,最好使用+'%F %R %z'
.
当您使用日期时,2000/1/2 03:04:05
您没有指定时区。
这就是为什么该命令date
将下一个- 1
表示时区的原因:
$ date -u -d '2000/1/2 03:04:05'; date -u -d '2000/1/2 03:04:05 - 1'
Sun 02 Jan 2000 03:04:05 AM WAT
Sun 02 Jan 2000 05:04:05 AM WAT
Run Code Online (Sandbox Code Playgroud)
那是假设您的当地时间是 WAT(并且不会因夏令时而改变,没有夏令时)。我不知道,因为你没有使用%z
也没有%Z
。时区更改将-d
值从+1
(WAT)更改为-1
2 小时时差。
此外,您hour
在那之后写道,这是一个额外的小时:
$ date -d '2000/1/2 03:04:05'; date -d '2000/1/2 03:04:05 - 1 hour'
Sun 02 Jan 2000 03:04:05 AM WAT
Sun 02 Jan 2000 06:04:05 AM WAT
Run Code Online (Sandbox Code Playgroud)
确认您的结果。
最后,+1:
$ date -d '2000/1/2 03:04:05 - 1 hour'; date -d '2000/1/2 03:04:05 + 1 hour ago'
Sun 02 Jan 2000 06:04:05 AM WAT
Sun 02 Jan 2000 02:04:05 AM WAT
Run Code Online (Sandbox Code Playgroud)
在+1
不改变时间值(因为它是在WAT,或1,已经),但hour ago
移位的时间1小时背面(从3到2)。
将时区放在-d
时间值中。
或者,将相关部分放在首位- 1 hour
$ date -d '2000/1/2 03:04:05 +0100 - 1 hour'
Sun 02 Jan 2000 02:04:05 AM WAT
$ date -d '-1 hour 2000/1/2 03:04:05'
Sun 02 Jan 2000 02:04:05 AM WAT
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1315 次 |
最近记录: |