3

I'm embarrassed (and shocked) I can't find a good answer this on SO or google, and please feel free to point me to a dup if there is one, but...

I want a function (in pure ruby ideally but active_support solutions are ok) that works like this:

Input: A datetime string of some reasonable format (eg, 2016-12-25 12:00) and a timezone. Not an offset, but a timezone, such as America/Chicago or America/New_York). Eg,

make_time_in_zone('2016-12-25 12:00', 'America/Chicago')

Output: A Time or DateTime object representing that exact point in time. That is, the function should use the timezone to account for both offsets and daylight savings time adjustments, so that you can know, eg, what the UTC time was when it struck noon on Christmas in America/Chicago.

I know that I can set the timezone to the desired one, create the Time object, and then the set the timezone back to the system one, but I consider this an unacceptable solution, and want a function that actually supports this use case.

Jonah
  • 15,806
  • 22
  • 87
  • 161
  • See if this works for you in some way: http://stackoverflow.com/questions/34175813/convert-string-to-date-of-specific-timezone/34176272#34176272 – Beartech Nov 21 '16 at 05:41
  • Not quite. `in_time_zone` does the other direction: take an exact point in time, and tell you the date and time it was in some timezone. the rounding to midnight and adding trick won't alway work, either, (at least for the general case) because depending on the zone and time, `in_time_zone` can move you forward *or* backward a day – Jonah Nov 21 '16 at 05:46
  • Still not clear on what you want. "...so that you can know, eg, what time it was at noon on Christmas in America/Chicago". Do you mean in UTC? Because at noon on Xmas in America/Chicago it was noon. Not meaning to be a smart ass, really not understanding what you want. – Beartech Nov 21 '16 at 05:49
  • "Do you mean in UTC?" -- effectively, yes, this is what I'm asking. I give you a date, time, and zone, you give me a UTC timestamp. I'm just couching it in terms of converting to a ruby `Time` object, but it's the same thing. – Jonah Nov 21 '16 at 05:52
  • Also in_time_zone would move you backward or forward a day because that's the way time zones work. At 21:00 in Seattle it is 05:00 in Greenwich. But in Seattle it is 11/20 and in Greenwich it is 11/21. So it is not clear what you mean by move back or forwards a day. – Beartech Nov 21 '16 at 05:58
  • I hope my last comment clarified. What I was attempting to say in my first comment is that because of the fact you just mentioned about how timezones work, you cannot use `in_time_zone` plus a rounding to midnight and then adding back trick to accomplish what I want here. – Jonah Nov 21 '16 at 06:06
  • I didn't think that was what I was doing, but I was referring to that answer not specifically as working for you but a jumping off point. I think you misunderstood the answer in the context of what that person was asking for. – Beartech Nov 21 '16 at 06:09
  • @Jonah, please add some example what you really want? – Shefalee Chaudhary Nov 21 '16 at 06:35

2 Answers2

3

Rails stores current zone in current Thread, so most correct way is setting a zone for parsing. Something like

Time.use_zone('America/Chicago') { Time.zone.parse('2016-12-25 12:00')}

There is also more "hackish" way, but it is not from public API.

ActiveSupport::TimeZone['America/Chicago'].parse('2016-12-25 12:00')
dimuch
  • 12,728
  • 2
  • 39
  • 23
3

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
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88