Convert UTC to User-Defined Time Zone with ActiveSupport::TimeWithZone

103 views Asked by At

I'm needing to convert a UTC time to the equivalent time in the user's time zone as part of a Rake task. What I want to do is change a UTC timestamp for midnight and re-create the timestamp to be midnight in the time zone of the user.

Example

Convert a UTC time

Wed, 01 Mar 2017 00:00:00 UTC +00:00

to Eastern Daylight Time (EDT) when observing daylight saving time (spring/summer)

Wed, 01 Mar 2017 04:00:00 UTC +00:00
zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")
time = "Wed, 01 Mar 2017 00:00:00 UTC +00:00"
time.in_time_zone(zone)
=> Tue, 28 Feb 2017 19:00:00.000000000 EST -05:00

The above will still save as Wed, 01 Mar 2017 00:00:00 UTC +00:00 in the database, as Rails will convert all timestamps back to UTC. However, I'm needing to get Wed, 01 Mar 2017 04:00:00 UTC +00:00 as that is the true beginning of the day in the user's time zone.

3

There are 3 answers

0
Stefan On BEST ANSWER

You can parse a string relative to a timezone via ActiveSupport::TimeZone#parse. Just make sure to omit any time zone specifiers like "UTC +00:00":

zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")

time = zone.parse("Wed, 01 Mar 2017 00:00:00")
#=> Wed, 01 Mar 2017 00:00:00.000000000 EST -05:00

time.utc
#=> 2017-03-01 05:00:00 UTC

The last call to utc is just for illustration purposes, Rails will perform this conversion automatically when saving time to the database.

With numeric input:

time = zone.local(2017, 3, 1)
#=> Wed, 01 Mar 2017 00:00:00.000000000 EST -05:00
0
spickermann On

When you want to initialize the time to a specific time in a specific timezone, then you need to initialize the time with the correct EST or EDT zone identifier (EST -05:00 or EDT -04:00).

time = "Wed, 01 Mar 2017 00:00:00 EST -05:00"
time.in_time_zone('UTC')
#=> Wed, 01 Mar 2017 05:00:00.000000000 UTC +00:00

time = "Wed, 01 Mar 2017 00:00:00 EDT -04:00"
time.in_time_zone('UTC')
#=> Wed, 01 Mar 2017 04:00:00.000000000 UTC +00:00
0
Akeel Ahmed Qureshi On
utc_time = "Wed, 01 Mar 2017 00:00:00 UTC +00:00"
zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")
usr_time = utc_time.in_time_zone(zone)
midnight_time = usr_time.beginning_of_day
utc_midnight_time = midnight_time.utc

Now, you can save utc_midnight_time in the database.

If you also want to create a timestamp and suppose you have a Scheduler model. Then you can do this, Scheduler.create(timestamp: utc_midnight_time) and save it.