How to convert time with timezone in ruby
There's no method for that, however you can make one for yourself:
class Time
require 'time'
def self.by_offset(offset)
at(now + zone_offset(offset))
end
end
Now, you can:
Time.by_offset('PST')
#=> 2014-11-03 10:11:14 +0530
Time.now
#=> 2014-11-03 18:11:13 +0530
Tested with 1.9.2, 2.0.0, and 2.1.2 Rubies(MRI).
Create a Time object from a timezone and date and time?
Just use in_time_zone
to parse the date in Time zone. You can pass Time zone as param.
in_time_zone(zone = ::Time.zone)
This will return exactly what you want.
'2016-12-25 12:00'.in_time_zone('America/Chicago')
#=> Sun, 25 Dec 2016 12:00:00 CST -06:00
'2016-12-25 12:00'.in_time_zone('America/New_York')
#=> Sun, 25 Dec 2016 12:00:00 EST -05:00
Rails 3: How to get today's date in specific timezone?
You should be able to do this: Time.current
. That would display the current time in Melbourne if that's what Time.zone
is set to.
Get Time Object at Start of Day in a Particular Time Zone
I ended up using the #local
method on the ActiveSupport::TimeZone
object passing components of the Date
object.
# Get example date and time zone...
date = Date.today
timezone = ActiveSupport::TimeZone['America/New_York']
# Get beginning of day for date in timezone
timezone.local(date.year, date.month, date.day)
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)
How do I.. get a value for time at 9:00am local, regardless of the timezone?
Ruby has a time class which maps to a time class in most databases. In most databases including mysql, it is represented as HH:mm:ss
so the date portion is ignored.
The time should always remain the same (09:00) unless it is changed externally. You could fetch this time components using t.hour
, and t.min
, and construct a Date
object with the correct date/time and the adjust for the users timezone.
>> t = Time.parse("09:00")
=> 2010-04-07 09:00:00 -0700
>> t.hour
=> 9
>> t.min
=> 0
Related Topics
Convert String with Comma to Integer
In Ruby/Rails, How to Encode/Escape Special Characters in Urls
How to Replace the Last Occurrence of a Substring in Ruby
Escape Double and Single Backslashes in a String in Ruby
How to Split String into Only Two Parts with a Given Character in Ruby
Turn Off Verbose SQL/Activerecord for Rails 3.1.1
Devise Skip_Confirmation! Fails to Avoid to Send the Confirmation Instructions
How to Expect Some (But Not All) Arguments with Rspec Should_Receive
How to Do Attr_Accessor_With_Default in Ruby
How to Define a Ruby Singleton Method Using a Block
How to Use Basic Authentication with Httparty in a Rails App
How to Install Ruby 1.9.3 on Ubuntu Without Rvm
Missing a Template for This Request Format and Variant
How to Find Where a Ruby Method Is Declared
How to Add Confirm Message with Link_To Ruby on Rails
Ruby: How to "Require" a File from the Current Working Dir
Why Is This Permissions Error Occurring with Mod_Passenger.So