Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the timezone function in ruby's stdlib?

The ruby docs state that I can pass a timezone to the Time initializer:

zone = timezone("Europe/Athens")      # Eastern European Time, UTC+2
Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200

However, when I try calling timezone I get undefined method 'timezone'. Is there a particular require that I need?

like image 559
Lou Zell Avatar asked Oct 25 '25 05:10

Lou Zell


2 Answers

The timezone method you are referring to is actually just an example. It doesn't exist in Ruby. I agree, the wording and example is perhaps a bit misleading.

Ruby stdlib passes around timezones as strings, by either passing a timezone UTC offset or name. This is shown in the first example:

You can pass a UTC offset:

Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200

Note the string "+02:00".

Then the "incriminated" example you are referring to:

Or a timezone object:

zone = timezone("Europe/Athens")      # Eastern European Time, UTC+2
Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200

The way you should read this example is as if somewhere you have a piece of code, here the hypothetical method timezone, that returns an object representing a TZ that can be provided to the initializer.

A practical example is the following one, using the widely adopted tzinfo library:

[2] pry(main)> require 'tzinfo'
=> true
[3] pry(main)> tz = TZInfo::Timezone.get('America/New_York')
=> #<TZInfo::DataTimezone: America/New_York>
[4] pry(main)> Time.new(2002, 10, 31, 2, 2, 2, tz)
=> 2002-10-31 02:02:02 -0500
[5] pry(main)> Time.new(2002, 10, 31, 2, 2, 2)
=> 2002-10-31 02:02:02 +0100

Note how in the example above the hypothetical method timezone is replaced with the actual code that initializes a new TZ object from tzinfo.

Finally, you can access the timezone setting by calling zone on the Time object. Note that what you get depends on the object you used to initialize the zone. By default it is a string, but if I use tzinfo as in the example below, I get the tzinfo instance.

[6] pry(main)> Time.new(2002, 10, 31, 2, 2, 2, tz).zone
=> #<TZInfo::DataTimezone: America/New_York>
[7] pry(main)> Time.new.zone
=> "CET"

To summarize, there is no timezone method defined (which actually the way it is show in the docs would require it to be defined in Kernel, which would be even more strange in Ruby). It was just a placeholder example.

like image 162
Simone Carletti Avatar answered Oct 26 '25 22:10

Simone Carletti


Indeed the timezone method is undefined. There is a trick though on Unix to convert Time object to any time zone. The timezone("Europe/Athens") is meant to talk to the C library underling the Time class ("zoneinfo" database located in /usr/share/zoneinfo/). So you can temporarily change the "system" time zone for the current process by setting the env variable TZ to an appropriate value.

class Time
  def convert_zone(to_zone)
    original_zone = ENV["TZ"]
    utc_time = dup.gmtime
    ENV["TZ"] = to_zone
    to_zone_time = utc_time.localtime
    ENV["TZ"] = original_zone
    return to_zone_time
  end
end

t = Time.now
t.convert_zone("Europe/Athens")

This is the equivalent of writing your own timezone method :)

like image 21
disanv Avatar answered Oct 27 '25 00:10

disanv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!