How to get Rails to interpret a time as being in a specific time zone?
In Ruby 1.8.7, how to set the time zone of a time?
In the following examples, my system time zone is PST (-8:00 hours from UTC)
Given a time (21 Feb 2011, 20:45
), presume that the time is in EST:
#this interprets the time as system time zone, i.e. PST
Time.local(2011,02,21,20,45)
#=> Mon Feb 21 20:45:00 -0800 2011
#this **converts** the time into EST, which is wrong!
Time.local(2011,02,21,20,45).in_time_zone "Eastern Time (US & Canada)"
#=> Mon, 21 Feb 2011 23:45:00 EST -05:00
But, the output I want is:
Mon Feb 21 20:45:00 -0500 2011
(Note the -0500 (EST) as opposed to -0800 (PST) and the hour is same, i.e. 20
, not 23
)
UPDATE (see the better version of this below)
I managed to get this to work, but I don't like it:
DateTime.new(2011,02,21,20,45).change :offset => -(300.0 / 1440.0)
# => Mon, 21 Feb 2011 20:45:00 +0500
Where
300 = 5 hrs x 60 minutes
1440 = number of minutes in a day
or the "right" way:
DateTime.civil(2011,02,21,20,45,0,Rational(-5, 24))
Question: Now, is there a way to determine the accurate(i.e. catering for daylight saving time etc) UTC offset from Time.zone
so that I can pass it to开发者_开发技巧 the change method?
Reference: DateTime::change
method
UPDATE (better version)
Thanks to @ctcherry for all the help!
Determine the accurate time zone info from Time.zone
:
DateTime.civil(2011,02,21,20,45,0,Rational((Time.zone.tzinfo.current_period.utc_offset / 3600), 24))
In ruby 1.8.7 it doesn't appear to be very easy to do what are asking for according to the documentation:
http://www.ruby-doc.org/core-1.8.7/classes/Time.html
However in 1.9 it looks a lot easier by passing the timezone offset to the localtime() method on a Time object:
http://www.ruby-doc.org/core/classes/Time.html#M000346
UPDATE
The offset for Time.zone is easy since its an object on its own: (This is in a Rails console)
ruby-1.8.7-p248 :001 > Time.zone
=> #<ActiveSupport::TimeZone:0x103150190 @current_period=nil, @name="Central Time (US & Canada)", @tzinfo=#<TZInfo::TimezoneProxy: America/Chicago>, @utc_offset=nil>
ruby-1.8.7-p248 :002 > Time.zone.utc_offset
=> -21600
ruby-1.8.7-p248 :003 > Time.zone.formatted_offset
=> "-06:00"
So I think this will (almost) accomplish what you want:
require 'time'
t = "21 Feb 2011, 20:45"
Time.parse(t) # => Mon Feb 21 20:45:00 -0700 2011
t += " -05:00" # this is the trick
Time.parse(t) # => Mon Feb 21 18:45:00 -0700 2011
It still returns the time based on your system time zone, but the actual time is the correct time that you are seeking.
By the way, this is tested on 1.8.7-p334.
精彩评论