【发布时间】:2020-07-04 18:48:09
【问题描述】:
总体目标:使用 jq 将 GMT 中的字符串解析为时间,并将格式化时间和该时间的差异输出到“现在”。但是,jqs(1.6 版,Debian 测试)时区处理对我来说似乎很困惑:
$ jq --version
jq-1.6
$ date
Sa 4. Jul 19:36:08 BST 2020
$ echo '""' | jq 'now | strftime("%H:%M")'
"18:36" // OK, strftime is supposed to give GMT
$ echo '""' | jq 'now | strflocaltime("%H:%M")'
"19:36" // also OK, British Summer time is one hour ahead, strflocaltime should give local time
$ echo '"2020-07-04T18:14:12Z"' | jq 'strptime("%Y-%m-%dT%H:%M:%SZ") | strftime("%H:%M")'
"18:14" // strptime parses GMT, so this is fine
$ echo '"2020-07-04T18:14:12Z"' | jq 'strptime("%Y-%m-%dT%H:%M:%SZ") | strflocaltime("%H:%M")'
"18:14" // but why is this not 19:14?!
$ echo '"2020-07-04T18:14:12Z"' | jq 'strptime("%Y-%m-%dT%H:%M:%SZ") | mktime | strftime("%H:%M")'
"19:14" // and why does "mktime" change things around?
$ echo '"2020-07-04T18:14:12Z"' | jq 'strptime("%Y-%m-%dT%H:%M:%SZ") | mktime | strflocaltime("%H:%M")'
"20:14" // and why does strflocaltime kick in after, but not before mktime?
$ echo '"2020-07-04T18:14:12Z"' | jq 'fromdate | strftime("%H:%M")'
"19:14" // I thought fromdate was synonymous to strptime?
$ echo '"2020-07-04T18:14:12Z"' | jq 'fromdate | strflocaltime("%H:%M")'
"20:14" // I suppose this is the same issue as above with mktime
更长的版本:我正在使用 API 来显示附近火车站的到达时间,特别是我想显示接下来的几列火车以及从现在开始它们将离开的分钟数。我想使用jq 来解析该数据。数据包含格式为"2020-07-04T18:14:12Z" 的时间字符串。我的理解是,jq 中的 fromdate 和 strptime 都应该将该数据解析为 GMT 时间戳(来自手册页:“在所有情况下,这些内置函数都专门处理 UTC 时间。”,手册页似乎可互换使用 GMT 和 UTC),jq 内的任何操作都使用 UTC,如果使用 strflocaltime,则只有最终输出位于本地时区。
但是,考虑到jq 的输出和上面显示的各种输入,这种理解肯定是错误的。特别是,我不明白如何正确可靠地将时间字符串解析为 GMT 时间戳,b) 一旦完成,fromdate、mktime、now 和 strptime 的输出分别有何不同当传递到strf[local]time 以产生上面看到的输出数组时。
编辑:进一步研究并使用前两个答案中的信息,主要问题似乎是fromdate 的夏令时应用(或不应用)取决于TZ 环境变量的设置:
$ TZ=BST jq -n '"2020-07-05T07:38:57Z" | fromdate'
1593934737
$ TZ=Etc/UTC jq -n '"2020-07-05T07:38:57Z" | fromdate'
1593934737
$ TZ=Europe/London jq -n '"2020-07-05T07:38:57Z" | fromdate'
1593938337
$ TZ=Asia/Tokyo jq -n '"2020-07-05T07:38:57Z" | fromdate'
1593934737
$ TZ=America/Los_Angeles jq -n '"2020-07-05T07:38:57Z" | fromdate'
1593938337
$ TZ=Asia/Kathmandu jq -n '"2020-07-05T07:38:57Z" | fromdate'
1593934737
$ unset TZ; jq -n '"2020-07-05T07:38:57Z" | fromdate'
1593938337
请注意,伦敦、洛杉矶和未设置的 TZ 获得的 Unix 纪元时间戳与东京、加德满都、UTC 和(我认为格式错误?)BST 不同。我相信这不应该发生,因为时间戳应该与时区无关。不幸的是,目前它似乎忽略了永久时区偏移(东京和加德满都给出与 UTC 相同的结果,两者都没有 DST)但它确实考虑了 DST,除非在不遵守 DST 的时区运行。
strflocaltime,当给定时间戳时,似乎根据TZ 的当前值应用永久和 DST 时区更正。
不幸的是,这似乎暗示我首先需要将 TZ 设置为 Etc/Utc 以使 fromdate 正常运行,然后当我想打印本地时间时,我需要将 TZ 重新设置为本地时区。
【问题讨论】:
-
我无法回答“为什么”部分,但这表明函数已编写,
strptime(fmt)仅用于解析(验证),如果输入符合请求的格式并且如果通过,请使用mktime进行进一步的自定义。我想,没有它,strptime(fmt)的输出就无法重用