Set time zone offset in Ruby
Change the time zone on your OS; Ruby will pick up the change.
How do I change the zone offset for a time in Ruby on Rails?
I'm using Rails 2.0 before they added the code that makes weppos solution work. Here's 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 element array, change the timezone and then convert the array back into a time.
How do you get the local timezone offset in +hh:mm format?
strftime
with %z
(:
means hour and minute offset from UTC with a colon):
Time.current.strftime("%:z")
Change Time zone in pure ruby (not rails)
You can use the Time
extensions from Active Support outside of Rails:
require 'active_support/core_ext/time'
t = Time.now
#=> 2014-08-15 15:38:56 +0200
t.in_time_zone('Pacific Time (US & Canada)')
#=> Fri, 15 Aug 2014 06:38:56 PDT -07:00
Now you can do
class Time
def to_pst
in_time_zone('Pacific Time (US & Canada)')
end
end
t = Time.now
#=> 2014-08-15 15:42:39 +0200
t.to_i
#=> 1408110159
t.to_pst
#=> Fri, 15 Aug 2014 06:42:39 PDT -07:00
t.to_pst.to_i
#=> 1408110159
# timestamp does not change!
Additionally you might also want the time extensions on Numeric
and Date
:
require 'active_support/core_ext/date'
require 'active_support/core_ext/numeric/time'
2.days.from_now
#=> 2014-08-17 15:42:39 +0200
Get UTC offset for Timezone at given date via Ruby/tzinfo?
You can use the period_for_local
method. For these examples, I'm using the timezone I live in (America/Sao_Paulo
), in where the offset is -03:00
during winter (March to October) and -02:00
during summer (Daylight Saving Time):
# Sao Paulo timezone
zone = TZInfo::Timezone.new('America/Sao_Paulo')
# date in January (Brazilia Summer Time - DST)
d = DateTime.new(2017, 1, 1, 10, 0)
period = zone.period_for_local(d)
puts period.offset.utc_total_offset / 3600.0
# date in July (Brazilia Standard Time - not in DST)
d = DateTime.new(2017, 7, 1, 10, 0)
period = zone.period_for_local(d)
puts period.offset.utc_total_offset / 3600.0
The output is:
-2.0
-3.0
The utc_total_offset
method returns the offset in seconds, so I divided by 3600 to get the value in hours.
Note that I also used 3600.0
to force the results to be a float. If I just use 3600
, the results will be rounded and timezones like Asia/Kolkata
(which has an offset of +05:30
) will give incorrect results (5
instead of 5.5
).
Note that you must be aware of DST changes, because you can have either a gap or a overlap.
In São Paulo timezone, DST starts at October 15th 2017: at midnight, clocks shift forward to 1 AM (and offset changes from -03:00
to -02:00
), so all the local times between 00:00 and 01:00 are not valid. In this case, if you try to get the offset, it will get a PeriodNotFound
error:
# DST starts at October 15th, clocks shift from midnight to 1 AM
d = DateTime.new(2017, 10, 15, 0, 30)
period = zone.period_for_local(d) # error: TZInfo::PeriodNotFound
When DST ends, at February 18th 2018, at midnight clocks shift back to 11 PM of 17th (and offset changes from -02:00
to -03:00
), so the local times between 11 PM and midnight exist twice (in both offsets).
In this case, you must specify which one you want (by setting the second parameter of period_for_local
), indicating if you want the offset for DST or not:
# DST ends at February 18th, clocks shift from midnight to 11 PM of 17th
d = DateTime.new(2018, 2, 17, 23, 30)
period = zone.period_for_local(d, true) # get DST offset
puts period.offset.utc_total_offset / 3600.0 # -2.0
period = zone.period_for_local(d, false) # get non-DST offset
puts period.offset.utc_total_offset / 3600.0 # -3.0
If you don't specify the second parameter, you'll get a TZInfo::AmbiguousTime
error:
# error: TZInfo::AmbiguousTime (local time exists twice due do DST overlap)
period = zone.period_for_local(d)
Ruby / Rails - Change the timezone of a Time, without changing the value
Sounds like you want something along the lines of
ActiveSupport::TimeZone.new('America/New_York').local_to_utc(t)
This says convert this local time (using the zone) to utc. If you have Time.zone
set then you can of course to
Time.zone.local_to_utc(t)
This won't use the timezone attached to t - it assumes that it's local to the time zone you are converting from.
One edge case to guard against here is DST transitions: the local time you specify may not exist or may be ambiguous.
How can I get the utc offset in Rails?
require 'time'
p Time.zone_offset('EST') #=> -18000 #(-5*60*60)
Rails timezone from offset
You can get a timezone using the []
method on ActiveSupport::TimeZone
. You can either pass a timezone name, hour offset or second offset. For instance:
ActiveSupport::TimeZone["America/Los_Angeles"]
=> (GMT-08:00) America/Los_Angeles
ActiveSupport::TimeZone[-8]
=> (GMT-08:00) America/Los_Angeles
But keep in mind that an offset is not equivalent to a timezone since multiple timezones can be on the same offset on any one day.
Related Topics
Using Send_File to Download a File from Amazon S3
Which Style of Ruby String Quoting Do You Favour
How to Clear the Terminal in Ruby
Why Does Adding "Sleep 1" in an After Hook Cause This Rspec/Capybara Test to Pass
Convert Utc to Local Time in Rails 3
How to Group by Count in Array Without Using Loop
Unable to Obtain Stable Firefox Connection in 60 Seconds (127.0.0.1:7055)
How to Sort an Array in Ruby to a Particular Order
Set Utf-8 as Default String Encoding in Heroku
Ruby: How to Write Multi-Line String With No Concatenation
Launching Background Process in Capistrano Task
Using Rvm on Ubuntu 12.04 to Use Rails. the Program 'Rails' Is Currently Not Installed
Ruby on Rails: Advanced Search
Ruby on Windows Causes Error Cannot Load Such File Bcrypt_Ext
How Do Rvm and Rbenv Actually Work
How to Create a Class Instance from a String Name in Ruby
Rails Console: Reload! Not Reflecting Changes in Model Files? What Could Be Possible Reason