问题描述
在Ruby或Rails中,给定诸如America/Los_Angeles
之类的时区标识符,我看到了如何获得特定的时区偏移量缩写,如PDT:
Time.current.in_time_zone('America/Los_Angeles').zone
=> "PDT"
Time.Now.in_time_zone("America/Los_Angeles").strftime('%Z')
=> "PDT"
Time.Now.in_time_zone("America/Los_Angeles").strftime('%z')
=> "-0700"
甚至是时区本身的友好名称:
ActiveSupport::TimeZone::MAPPING.key('America/Los_Angeles')
=> "Pacific Time (US & Canada)"
但是如何获得Pacific Daylight Time
之类的字符串而不是PDT
来表示特定日期的完整时区偏移量名称?
输入:America/Los_Angeles
和特定的日期或日期时间
所需的输出:Pacific Daylight Time
解决方法
短篇小说:〜由于某种原因,〜(由于@bata mentioned in his answer的缩写不是唯一的,因此这可能是没有正式的缩写-人性化名称映射的原因)该标准似乎不支持它。您可能需要自己实现此映射。但是请继续阅读,如果您想获得一些指导,为什么它可能没有那么容易。
所以...这是一个有趣的兔子洞,可以落入...
使用了哪些宝石,它们从何处获取信息
ActiveSupport uses tzinfo gem for that,它依次使用tz-info gem。 tz-info
说uses one of two data sources:
-
Unix类系统中的
- zoneinfo目录
- TZInfo :: Data
Rails的Gemfile模板confirms that TZInfo data is used on window
起初,我认为可能会有PR机会为流行的宝石做出贡献。 Quick search suggests没有PDT
到任何“人类友好形式”的映射。
查看unix
的{{1}}数据库
zoneinfo
看起来像一个二进制文件...
$ cat /usr/share/zoneinfo/America/Los_Angeles
TZif2H*ˉ#pa&t\Ðݩ߉iip~KIR^-)4GJQ',3qo_O?/v( fe HG *)
x
q(a'Q
A 0C ΐ
#j$5 %J& '*'))6 "S 54+ !"V
eGYe턠g';gfiiHjke lmvG noV) pq6: XX YZ [\ ]^d _y`Mޠab-cgwdE G-Gӵ I
ros tOt v8vxx͠yz{f|~}H~^s*&
LMTPDTPSTPWTPPTTZif2^H*ˉ#pa&t\Ðݩ߉iip~KIR^-)4GJQ',3qo_O?/v( fe HG *)
x
q(a'Q
A 0C ΐ
#j$5 %J& '*'))6 "S 54+ !"V
eGYe턠g';gfiiHjke lmvG noV) pq6: XX YZ [\ ]^d _y`Mޠab-cgwdE G-Gӵ I
ros tOt v8vxx͠yz{f|~}H~^s*&
LMTPDTPSTPWTPPT
PST8PDT,M3.2.0,M11.1.0
嗯。无论采用哪种方式,此TZ似乎都没有“人类友好”的名称。
更多地挖掘$ strings /usr/share/zoneinfo/America/Los_Angeles
TZif2
v+ !
2s$
3Gt 4S
5'V 62
mvG n
oV) p
TZif2
v+
3Gt
5'V
mvG
oV)
PST8PDT,M11.1.0
格式,显然有unix tzinfo
和zic
工具
zdump
不是很有用...
$ zdump /usr/share/zoneinfo/America/Los_Angeles
/usr/share/zoneinfo/America/Los_Angeles Thu Sep 10 03:07:49 2020 PDT
gh。
但是阅读其中的一种工具的$ zic /usr/share/zoneinfo/America/Los_Angeles
"/usr/share/zoneinfo/America/Los_Angeles",line 1: line too long
时,我发现manpages
是官方的RFC8536。我不太擅长阅读这些,但是格式中有标头(带有版本)和
- data block(将其签出,显然它存储了TZ的所有历史更改)
- footer似乎包含PDT字符串等,并且未提及提供“友好”名称的可能性。
如果您在阅读RFC时遇到困难,似乎timezoneinfo
gem会尝试为不包含tzinfo-data
数据库(例如Windows)的系统重现相同的数据:
tzinfo
这里的 timezone 'America/Los_Angeles' do |tz|
tz.offset :o0,-28378,:LMT
tz.offset :o1,-28800,:PST
tz.offset :o2,3600,:PDT
tz.offset :o3,:PWT
tz.offset :o4,:PPT
tz.transition 1883,11,:o1,-2717640000,7227400,3
tz.transition 1918,3,:o2,-1633269600,29060207,12
tz.transition 1918,10,-1615129200,19375151,8
tz.transition 1919,-1601820000,29064575,12
tz.transition 1919,-1583679600,19378063,8
tz.transition 1942,2,:o3,-880207200,29164799,12
# ... [cut!]
方法定义为:https://github.com/tzinfo/tzinfo/blob/f361d7d0b859ba5b91d30ffd6b66c3c59f90e969/lib/tzinfo/format2/timezone_definer.rb#L37:L59(至少我认为是这样,直到在ruby中运行代码之前,您才知道)
如您所见,夏令时没有offset
和:LMT
的缩写。
随时自行探索更多内容。但是,看来transition
中存在从DST到DST的每个过渡。而且洛杉矶似乎已经计划了2060年之前的工作。如果您尝试计算2060年之后的时间,是否会遇到与DST相关的TZ错误,这真的很有趣吗?
最后一点:缩写
不知道tzinfo
的{{1}}数据库是否是这种情况,但是在gem中它们是在本地定义的!
如果所有定义(https://github.com/tzinfo/tzinfo-data/search?q=%3APDT&unscoped_q=%3APDT)都unix
的含义相同
但是请注意
- lib / tzinfo / data / definitions / Asia / Manila.rb定义正偏移量
tzinfo
,但 - lib / tzinfo / data / definitions / America / Dawson.rb用相同的缩写定义负偏移量
:PDT
。
这是什么意思-不知道。但这可能就是我们在任何地方都没有“全球友好时区名称”的原因。
数据库中可能存在错误。 official DB自述文件说:
,此历史本地时间信息数据库具有以下目标:
提供有关民事时间历史的数据摘要, 即使不是100%准确,也很有用。
了解现有的各种本地时间规则 在过去,因此可能在未来。
测试本地时间规则描述系统的普遍性。
时区数据文件中的信息绝对不是权威的; 修复和增强功能是受欢迎的。请查看文件CONTRIBUTING 有关详细信息。
我认为没有缩写的标准。此外,它们也不是唯一的,如您在此处看到的:https://www.timeanddate.com/time/zones/