为什么 %Z 给我的是数字偏移量而不是 Ruby 中的缩写时区名称?

Why is %Z giving me the numeric offset instead of the abbreviated time zone name in Ruby?

我试图从一个字符串中解析时间戳,然后用它的缩写时区显示它,但返回的是与 UTC 的数字偏移量,尽管我认为这是正确的用法。这是控制台会话:

[5] pry(main)> time_string = "2022-08-02T12:00:00 CDT"
=> "2022-08-02T12:00:00 CDT"
[6] pry(main)> DateTime.parse(time_string).zone
=> "-05:00"
[7] pry(main)> DateTime.parse(time_string).strftime("%Z")
=> "-05:00"

期待的是这将再次returnCDT

这是 macOS 上的 Ruby 2.7,Rails:

❯ ruby --version
ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin21]
❯ rails --version
Rails 6.1.6

来自 rails 的 strftime 文档,说它按预期工作。

Time zone:
  %z - Time zone as hour and minute offset from UTC (e.g. +0900)
          %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
          %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
          %:::z - hour, minute and second offset from UTC
                                            (e.g. +09, +09:30, +09:30:30)
  %Z - Equivalent to %:z (e.g. +09:00)

如果您有实际的时区名称,您可以使用它在博客 post

中获取缩写作为大纲 here
def human_timezone(time_string, timezone)
  time = time_string.in_time_zone(timezone)

  if time.zone.match?(/^\w/)
    time.zone
  else
    time.formatted_offset
  end
end

>> human_timezone('2019-03-28 16:00', 'Pacific Time (US & Canada)')
=> "PDT"
>> human_timezone('2019-03-28 16:00', 'Berlin')
=> "CET"
>> human_timezone('2019-05-01 16:00', 'Almaty')
=> "+06:00"

Ruby 不存储时区名称,它仅存储时间偏移量 (-5:00)。 因此,向后转换是不可能的,因为一个偏移量有多个时区。例如偏移量为 -5:00 的另一个时区。

> time_string = "2022-08-02T12:00:00 PET"
 => "2022-08-02T12:00:00 PET"
> DateTime.parse time_string
 => Tue, 02 Aug 2022 12:00:00 -0500