[ACCEPTED]-How do I change the zone offset for a time in Ruby on Rails?-ruby

Accepted answer
Score: 17

You don't explicitly say how you get the 16 actual variable but since you mention the 15 Time class so I'll assume you got the time 14 using that and I'll refer to that in my 13 answer

The timezone is actually part of the 12 Time class (in your case the timezone is 11 shown as UTC). Time.now will return the 10 offset from UTC as part of the Time.now 9 response.

>> local = Time.now
=> 2012-08-13 08:36:50 +0000
>> local.hour
=> 8
>> local.min
=> 36
>> 


... in this case I happen to 8 be in the same timezone as GMT

Converting between timezones

The easiest 7 way that I've found is to change the offset 6 using '+/-HH:MM' format to the getlocal 5 method. Let's pretend I want to convert 4 between the time in Dublin and the time 3 in New York

?> dublin = Time.now
=> 2012-08-13 08:36:50 +0000
>> new_york = dublin + Time.zone_offset('EST')
=> 2012-08-13 08:36:50 +0000
>> dublin.hour
=> 8
>> new_york.hour
=> 3

Assuming that 'EST' is the name 2 of the Timezone for New York, as Dan points 1 out sometimes 'EDT' is the correct TZ.

Score: 15

If given:

2011-10-25 07:21:35 -700

you want:

2011-10-25 07:21:35 UTC

then do:

Time.parse(Time.now.strftime('%Y-%m-%d %H:%M:%S UTC')).to_s

0

Score: 15

This takes advantage of the fact that Time#asctime doesn't 12 include the zone.

Given a time:

>> time = Time.now
=> 2013-03-13 13:01:48 -0500

Force it to 11 another zone (this returns an ActiveSupport::TimeWithZone):

>> ActiveSupport::TimeZone['US/Pacific'].parse(time.asctime)
=> Wed, 13 Mar 2013 13:01:48 PDT -07:00

Note that 10 the original zone is ignored completely. If 9 I convert the original time to utc, the 8 result will be different:

>> ActiveSupport::TimeZone['US/Pacific'].parse(time.getutc.asctime)
=> Wed, 13 Mar 2013 18:01:48 PDT -07:00

You can use to_time or 7 to_datetime on the result to get a corresponding Time or 6 DateTime.

This question uses an interesting approach with DateTime#change to 5 set the tz offset. (Remember that ActiveSupport 4 makes it easy to convert between Time and DateTime.) The 3 downside is that there's no DST detection; you 2 have to do that manually by using TZInfo's 1 current_period.

Score: 11

...

>> Time.at(Time.now.utc + Time.zone_offset('PST'))
=> Mon Jun 07 22:46:22 UTC 2010
>> Time.at(Time.now.utc + Time.zone_offset('PDT'))
=> Mon Jun 07 23:46:26 UTC 2010
>> Time.at(Time.now.utc + Time.zone_offset('CST'))
=> Tue Jun 08 00:46:32 UTC 2010

One note: make sure that the current 6 time object is set to UTC time first, otherwise 5 Ruby will try and convert the Time object 4 to your local timezone, thus throwing the 3 calculation. You can always get the adjusted 2 time by applying ".utc" to the end of the 1 above statements in that case.

Score: 10

For those that came across this while looking 3 for a non-rails solution (as I did), TZInfo 2 solved it for me...

require 'tzinfo'
def adjust_time time, time_zone="America/Los_Angeles"
    return TZInfo::Timezone.get(time_zone).utc_to_local(time.utc)
end

puts adjust_time(Time.now) 
#=> PST or PDT
puts adjust_time(Time.now, "America/New_York")
#=> EST or EDT

This also handles DST, which 1 is what I needed that wasn't handled above.

See: http://tzinfo.rubyforge.org/

Score: 5

in you environment.rb search for the following 2 line.

# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names.
config.time_zone = 'UTC'

Keep in mind ActiveRecord and Rails 1 always handle Time as UTC internally.

Score: 2

I'm using Rails 2.0 before they added the 4 code that makes weppos solution work. Here's 3 what I did

# Silly hack, because sometimes the input_date is in the wrong timezone
temp = input_date.to_time.to_a
temp[8] = true
temp[9] = "Eastern Daylight Time"
input_date = Time.local(*temp)

I break the time down into a 10 2 element array, change the timezone and then 1 convert the array back into a time.

Score: 1

Here is what worked for me...

def convert_zones(to_zone)
   to_zone_time = to_zone.localtime
end


# have your time set as time

time = convert_zones(time)
time.strftime("%b #{day}, %Y (%a) #{hour}:%M %p %Z")

0

Score: 1

This is what I did, as I am not using Rails 1 and don't want to use any non-core gems.

t = Time.now # my local time - which is GMT
zone_offset = 3600 # offset for CET - which is my target time zone
zone_offset += 3600 if t.dst? # an extra hour offset in summer
time_cet = Time.mktime(t.sec, t.min, t.hour, t.mday, t.mon, t.year, nil, nil, t.dst?, zone_offset)
Score: 0

Option 1

Use date_time_attribute gem:

my_date_time = DateTimeAttribute::Container.new(Time.zone.now)
my_date_time.date_time           # => 2001-02-03 22:00:00 KRAT +0700
my_date_time.time_zone = 'Moscow'
my_date_time.date_time           # => 2001-02-03 22:00:00 MSK +0400

Option 2

If time is used as an attribute, you 1 can use the same date_time_attribute gem:

class Task
  include DateTimeAttribute
  date_time_attribute :due_at
end

task = Task.new
task.due_at_time_zone = 'Moscow'
task.due_at                      # => Mon, 03 Feb 2013 22:00:00 MSK +04:00
task.due_at_time_zone = 'London'
task.due_at                      # => Mon, 03 Feb 2013 22:00:00 GMT +00:00
Score: 0

It's probably a good idea to store the time 7 as UTC and then show it in a specific time 6 zone when it is displayed. Here's an easy 5 way to do that (works in Rails 4, unsure 4 about earlier versions).

t = Time.now.utc

=> 2016-04-19 20:18:33 UTC

t.in_time_zone("EST")

=> Tue, 19 Apr 2016 15:18:33 EST -05:00

But if you really 3 want to store it in a specific timezone, you 2 can just set the initial Time object to 1 itself.in_time_zone like this:

t = t.in_time_zone("EST")
Score: 0

When Parsing a Time

I'd be interested to hear how you're setting 6 the variable foo to begin with.

If you're parsing 5 a time string that doesn't have a time zone 4 (what I was doing during a data import) then 3 you can use String#in_time_zone to force the time zone during 2 the parsing:

"Fri Jun 26 2019 07:00:00".in_time_zone( "Eastern Time (US & Canada)" ) 
# => Wed, 26 Jun 2019 07:00:00 EDT -04:00

Works like a charm and is super 1 clean.

Score: 0

You can do:

DateTime.parse('Fri Jun 26 07:00:00 UTC 2009').change(offset: '-0400')

Which returns:

Fri, 26 Jun 2009 07:00:00 -0400

0

More Related questions