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

Time:05-26

I'm trying to parse a timestamp from a string, and then subsequently display it with its abbreviated time zone, but what's coming back is the numeric offset from UTC despite what I believe is the correct usage. Here's the console session:

[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"

What I'm expecting here is that this will return CDT again.

This is Ruby 2.7 on macOS, with Rails:

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

CodePudding user response:

From the strftime docs for rails, says it's working as intended.

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)

If you have the actual timezone name you can use that to get the abbreviation as outline here in the blog post

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"

CodePudding user response:

Ruby doesn't store timezone name, it stores only the time offset (-5:00). So, backward conversion is not possible because there are multiple timezones for one offset. For e.g. another timezone with -5:00 offset.

> 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
  • Related