Search code examples
rubytzinfo

Getting timezone in pure Ruby (no rails)


I am wondering if I can change the timezone in Ruby. I am currently in Asia/Kolkata (+0530).

In my system if I run:

>> puts (1935..1945).map { |x| "#{x} => #{Time.new(x).strftime('%z')}" }
1935 => +0530
1936 => +0530
1937 => +0530
1938 => +0530
1939 => +0530
1940 => +0530
1941 => +0530
1942 => +0630
1943 => +0630
1944 => +0630
1945 => +0630

As you can see timezone changes based on historical events.

I want Ruby (running on any server in any place) to show the timzeone +0630 when Asia/Kolkata or IST is set.


But if I run this code on a different system located at different part of the globe:

I get back:

1935 => +0100
1936 => +0100
1937 => +0100
1938 => +0100
1939 => +0100
1940 => +0100
1941 => +0200
1942 => +0200
1943 => +0100
1944 => +0100
1945 => +0100

Which is probably correct according to their timezone.

Now if I try to follow this question Change Time zone in pure ruby (not rails), and the answer:

p Time.new(1942).utc.localtime("+05:30").strftime('%z')
=> "+0530"

My requirement breaks. Because Asia/Kolkata isn't +05:30 during 1942.


If I mention IST:

p Time.new(1942).utc.+(Time.zone_offset('IST')).strftime('%z')
=> "+0000"

This returns "+0000". But my desired output is "+0630".


Now there are websites which let you do that. So it's technically not impossible to get the +0630 on any server if I enter "IST".


So is there a way to getting back the timezone in Ruby by mentioning the timezone (IST)?


Solution

  • For the time being, this works TZ=Asia/Kolkata ruby -e "p Time.new(1942).strftime('%z')"

    Setting the TZ environment variable also works from within Ruby: (seen in test_time_tz.rb)

    def with_tz(tz)
      old = ENV['TZ']
      ENV['TZ'] = tz
      yield
    ensure
      ENV['TZ'] = old
    end
    
    with_tz('Asia/Kolkata') do
      (1935..1945).each do |x|
        puts "#{x} => #{Time.local(x).strftime('%z')}"
      end
    end