linux - 在 linux 上比较两个日期时是否也考虑了时区差异

标签 linux bash datetime

我有几个时间戳要比较。

  1. 开始日期:2017-04-04T21:27:37.991Z
  2. 结束日期: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 zulu02: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/

相关文章:

linux - Xampp 无法在 Linux 上运行

python - 通过 Shell 在所有函数的开头和结尾添加日志语句

c# - 在 C# 中解析确切日期不应强制您创建 IFormatProvider

datetime - 从 pandas (python) DataFrame 对象中提取小时、日期和月份

excel - 将日期从 Excel 导入到 Matlab

java - 为什么我在 --config java 菜单中看不到我的 Oracle java jdk 之一?

linux - 如何从另一台 PC 连接到 VMware?

python - 解析字符串的多个日志文件

regex - AWK 打印找到匹配项的列号

bash - 如何使用 sed bash 删除特定模式