我有几个时间戳要比较。
- 开始日期:2017-04-04T21:27:37.991Z
- 结束日期:2017-04-05
我比较 bash
中的两个时间戳,方法是将它们转换为秒,然后将它们置于 if
条件中,如下所示:
startDateSecs=$(date -d ${startDate} +%s)
endDateSecs=$(date -d ${endDate} +%s)
我得到的值是:
startDateSecs = 1491341257
endDateSecs = 1491330600
我的时区目前是 IST(印度标准时间)。我知道第一个时间戳上的 Z
符号意味着它从 UTC 偏移 0。
当我比较这两个时间戳时,2017-04-05 较低,因为它也考虑了我现在的时区?
最佳答案
Q: is lower because it takes into account my present timezone too?
一句话:有时?
但正确答案要长一些。继续阅读。
TL;DR 简单的解决方案,使用:
endDateSecs=$(date -d "${endDate}Z" +%s)
强制以 UTC0 格式输入时间。输出时间,以秒为单位,也是UTC0。
表面上相等:
这两个给出相同的 string 作为结果:
$ TZ=America/New_York date -d '2017-04-05' +'%FT%T'
2017-04-05T00:00:00
$ TZ=Asia/Kolkata date -d '2017-04-05' +'%FT%T'
2017-04-05T00:00:00
但是:这些时间点是否相同? 否
$ TZ=America/New_York date -d '2017-04-05' +'%FT%T%z'
2017-04-05T00:00:00-0400
$ TZ=Asia/Kolkata date -d '2017-04-05' +'%FT%T%z'
2017-04-05T00:00:00+0530
这两个“时间点”是:+0530-(-0400)
9:30(相隔九个半小时)。
这就是为什么使用时区定义完全限定时间点非常重要,或者,如果缺少时区定义,请理解时间将以表示local(计算输出时间值时TZ取哪个值有效)。
date
的一个非常有用的选项是使用 --debug
。这将阐明哪个 TZ(必须选择一个)对输入和输出有效:
$ TZ=Asia/Kolkata date --debug -d '2017-04-05' +'%FT%T%z'
date: parsed date part: (Y-M-D) 2017-04-05
date: input timezone: +05:30 (set from TZ="Asia/Kolkata" environment value)
date: warning: using midnight as starting time: 00:00:00
date: starting date/time: '(Y-M-D) 2017-04-05 00:00:00 TZ=+05:30'
date: '(Y-M-D) 2017-04-05 00:00:00 TZ=+05:30' = 1491330600 epoch-seconds
date: output timezone: +05:30 (set from TZ="Asia/Kolkata" environment value)
date: final: 1491330600.000000000 (epoch-seconds)
date: final: (Y-M-D) 2017-04-04 18:30:00 (UTC0)
date: final: (Y-M-D) 2017-04-05 00:00:00 (output timezone TZ=+05:30)
2017-04-05T00:00:00+0530
可以清楚的看到输入和输出时区是一样的。
这就是输出字符串为 midnight (00:00:00) 的原因。
跨越时区:
现在应该很明显,如果输入 TZ 与输出 TZ 不同,则生成的字符串应该反射(reflect)一个等于时区偏移量的时间偏移量。
比较:
$ TZ=Asia/Kolkata date -d '2017-04-05T00:00:00+0530' +'%FT%T%z' ; \
> TZ=Asia/Kolkata date -d '2017-04-05T00:00:00-0400' +'%FT%T%z'
2017-04-05T00:00:00+0530
2017-04-05T09:30:00+0530
两个值均以本地时间(印度时间)表示:结果指标:+0530。
但是每个“时间点”彼此相隔 09:30。
这里的关键问题是:输入 TZ 和输出 TZ 是否相等?
开始日期:
这应该会影响 startDate:2017-04-04T21:27:37.991Z
它是祖鲁语“时间点”(与 UTC 零差),但输出 TZ 是您的语言环境值:Asia/Kolkata
。这是结果:
$ TZ=Asia/Kolkata date -d '2017-04-04T21:27:37.991Z' +'%FT%T%z'
2017-04-05T02:57:37+0530
时间点 21:27 zulu
是 02:57 ITC
(第二天)。
日期-u
如果使用日期选项 -u
(UTC0),对于任何有效的本地时区,将避免如上所示跨越多个时区:
$ TZ=Asia/Kolkata date -ud '2017-04-04T21:27:37.991Z' +'%FT%T%z'
2017-04-04T21:27:37+0000
请注意,结果是 zulu time
,输入也是如此。
由于输入和输出相等,因此日期字符串等于源日期。
秒
现在,为了详细解释整个问题的最后转折:+'%s'
纪元时间戳(秒)始终以祖鲁时间定义。
通过询问以秒为单位的时间,输出将引用 UTC0 (zulu)。
如果输入在别的地方,会出现时间差:
$ TZ=Asia/Kolkata date -d '2017-04-04T21:27:37.991-0400' +'%s%z'; \
> TZ=UTC0 date -d '2017-04-04T21:27:37.991-0400' +'%s%z'; \
> TZ=UTC0 date -d '2017-04-04T21:27:37.991+0530' +'%s%z';
1491355657+0530
1491355657+0000
1491321457+0000
前两个是相同的“时间点”,表示为纪元产量 1491355657 UTC0,即使打印的时区不同也是如此。
第三个值是其他一些“时间点”:自纪元以来 1491321457 秒。
也许这会很难处理,但这是确切的事实。
决赛
现在我们可以这样说:
$ date -d "$startDate" +'%s'
1491341257
将始终打印 1491341257
,因为该值完全符合祖鲁语中的时区。
但是:
$ TZ=America/New_York date -d "$endDate" +'%s%z' ; \
> TZ=Asia/Kolkata date -d "$endDate" +'%s%z'
1491364800-0400
1491330600+0530
将随着 TZ 的生效而改变。
您可以通过添加时区时间或使用 -u
TZ=America/New_York date -d "${endDate}IST" +'%s%z'
TZ=America/New_York date -d "${endDate}Z" +'%s%z'
TZ=America/New_York date -ud "${endDate}Z" +'%s%z'
TZ=America/New_York date -ud "${endDate}" +'%s%z'
TZ=Asia/Kolkata date -d "${endDate}Z" +'%s%z'
TZ=Asia/Kolkata date -ud "${endDate}" +'%s%z'
将打印:
1491330600-0400 # a different value: Crossing TZ's
1491350400-0400
1491350400+0000
1491350400+0000
1491350400+0530
1491350400+0000
关于linux - 在 linux 上比较两个日期时是否也考虑了时区差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43239694/