Ruby Strftime '%Z' Method Returns '0545' Instead of 'Npt'

Ruby's strftime not displaying timezone offset with '%Z'

The format directive %Z requests the symbolic time zone (name or abbreviation); %z is the offset. While you always know the offset, you may not know the symbolic time zone name.

I suspect that's what's going on with display_time. It was initialized with an offset, so it doesn't have any symbolic time zone name to display.

You can't reliably derive a name from an offset, either; for example, -0400 could be Atlantic Standard Time or Eastern Daylight Time. Most offsets will have more than one option for what time zone they are, and most time zones have more than one name anyway.

strftime(%Z) returns wrong result

Sadly, it seems there is no 'FJT' abbreviation assigned to 'Fiji' in timezone data used by Rails. Also, support for those abbreviations seems patchy regarding Pacific timezones.

irb(main):002:0> DateTime.now.in_time_zone('Samoa').strftime('%Z')
=> "+13"
irb(main):003:0> DateTime.now.in_time_zone('Midway Island').strftime('%Z')
=> "SST"
irb(main):004:0> DateTime.now.in_time_zone('Samoa').strftime('%Z')
=> "+13"
irb(main):005:0> DateTime.now.in_time_zone('Tokelau Is.').strftime('%Z')
=> "+13"
irb(main):006:0> DateTime.now.in_time_zone('Wellington').strftime('%Z')
=> "NZST"

UTC offset is displayed as fallback. If it's any help, remember that full name and additional information can be retrieved with .time_zone.tzinfo on ActiveSupport::TimeWithZone objects. 'FJ' code is recognized by TZInfo::Country.

irb(main):056:0> TZInfo::Country.get('FJ')
=> #<TZInfo::Country: FJ>
irb(main):057:0> TZInfo::Country.get('FJ').zone_info
=> [#<TZInfo::CountryTimezone: Pacific/Fiji>]

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

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"

Different output for DateTime.strftime vs Time.strftime for timezone abbreviations

The documentation on DateTime#strftime a bit unclear:

%Z — Time zone abbreviation name or something similar information.

To make it possible to show the offset both ways, DateTime shows the numeric value. To retrieve the abbreviated name, one should explicitly cast DateTime object to Time:

▶ DateTime.now.to_time.strftime("%Z")
#⇒ "CET"

Ruby: now.strftime(%a, %d %b %Y %X %z) gives wrong time

You should convert this time in a specific timezone. like:

time_zone = ActiveSupport::TimeZone.new(your_desire_time_zone)
converted_time = time.in_time_zone(time_zone)

or convert in UTC

converted_time = Time.now.utc

Then try to use strftime

converted_time.strftime("%a, %d %b %Y %X %z")

For more details, find here. Thanks.

Ruby strftime: Month without leading zero?

Some versions of strftime do allow prefixing with minus to format out leading zeros, for eg:

strftime "%-d/%-m/%y"

However this will depend on strftime on your system. So for consistency I would do something like this instead:

dt = Time.local(2010, 'Sep', 1)
printf "%d/%d/%d", dt.day, dt.month, dt.year

How to correctly set time format in strftime method?

If you stored time in your database in UTC than that time will always be in UTC when you fetch it. You need to display it according to user's local time zone. You have to do that using JavaScript, check this article.

Or if you need just Kiev time zone and nothing else you can do something like this:

<%= message.created_at.in_time_zone('Europe/Kiev').strftime("%H:%M") %>


Related Topics



Leave a reply



Submit