linux – 给定时区的小时/分钟的GMT / UTC偏移,无夏令时(DST)

我已经在其他编程语言或操作系统中看到了与此问题相关的一些问题/答案,但我发现没有针对我的具体方案的常见解决方案.我想在
Linux shell脚本或纯C中获得给定时区(正常标识符,如EDT,CET或Europe / Berlin)的GMT偏移量.

一个简单的解决方案是:

$TZ=":Europe/Berlin" date +%z

但是这将打印当前的GMT偏移量(包括DST,如果它当前正在使用中).

这里有一个更好的例子来说明我的意思:

$TZ=":Europe/Berlin" date +%z --date="1 Jan 2014"
+0100

$TZ=":Europe/Berlin" date +%z --date="1 May 2014"
+0200

我需要一个选项来始终获得任何国家/城市的非DST值(此处:0100).

其他问题可以解决我的问题,并与此问题有关:

如何找到给定城市(欧洲/柏林)的正确非DST时区(Etc / GMT-1),而不知道提前的偏移量?

你怎么知道DST在给定的时间戳上是活跃的?

$TZ=":Europe/Berlin" date --date="2014-01-01"
Wed Jan  1 00:00:00 CET 2014

$TZ=":Europe/Berlin" date --date="2014-05-01"
Thu May  1 00:00:00 CEST 2014

标识符CEST(中欧夏令时)和CET(中欧时间)可能在世界其他地方并不常见,因此,如果有人需要,可以选择简单地获得DST = 1或DST = 0的选项.通过zdump,你可以获得更改DST的所有时间戳的isdst = 0或isdst = 1,但它不是那么容易使用的IMO.

最佳答案 这将在几秒钟内返回给定时区的当前年份与格林尼治标准时间的非DST偏差:

zdump -v "Europe/Berlin" | \
sed ":a;N;\$!ba;s/^.*$(echo -n $(date +%Y)) [^ ]* isdst=0 \
gmtoff=\([^\n]*\)\n.*$/\1/"

3600

这里发生的是sed匹配zdump为该时区返回的当前年份的第一个非dst行,然后用第一个匹配行的末尾替换整个zdump输出,这是GMT偏移量,以秒为单位.

如果需要将其格式化为HHMM或-HHMM:

offsetArray=($(zdump -v "America/New_York" | \
sed ":a;N;\$!ba;s/^.*$(echo -n $(date +%Y)) [^ ]* isdst=0 \
gmtoff=\(-*\)\([^\n]*\)\n.*$/\1+ \2/"))
echo "${offsetArray[0]:0:1}$(date -ud @${offsetArray[1]} +%H%M)"

-0500

这将创建一个包含两个元素的数组,即符号和偏移的绝对值(以秒为单位).它输出前者,并通过将日期作为时间(自1970年1月1日 – 1970年00:00:00 UTC / GMT)传递给日期来格式化后者.因为Bash数组赋值忽略前导空格,所以数组的第一个元素实际上是“”或“ – ”,显示的是第一个字符(即或 – ).

顺便说一句,我认为zdump列出的每年都应该与GMT有相同的非DST偏差,而我原来的答案只是抓住了它找到的第一年,但我编辑了答案以检查当前年份以适应自1901年以来时区发生变化的理论边缘情况.

(您可以删除尾部反斜杠以在一行中获取所有指令,或者在第二个示例中获取两行.)

点赞