How do you get DateTime.parse to return a time in your time zone?
Asked Answered
V

6

20

I need this

 require 'date'
 DateTime.parse "Mon, Dec 27 6:30pm"

to return a DateTime for 6:30pm in the EDT timezone, but it returns one in UTC. How can I get a EST DateTime or convert the UTC one into an EDT DateTime with a 6:30pm value?

Valenevalenka answered 2/1, 2011 at 2:56 Comment(0)
C
8

Final answer ;-)

require 'date'
estHoursOffset = -5
estOffset = Rational(estHoursOffset, 24)
date = (DateTime.parse("Mon, Dec 27 6:30pm") - (estHoursOffset/24.0)).new_offset(estOffset)

(or -4 for EDT)

Chunchung answered 2/1, 2011 at 3:3 Comment(10)
Cool, I didn't know about the new_offset method.Twilatwilight
I tried that, but it returns ` #<DateTime: 2011-12-27T13:30:00-05:00 (117884317/48,-5/24,2299161)>`, which is 1:30pm EDT. I need 6:30pm EDT.Valenevalenka
I updated it to reflect EST offset. (p.s. you wrote EST and then EDT in your question)Chunchung
Thanks. I wonder why the result is different when you call #new_offset(-5) vs. #new_offset(DateTime.now.offset)Valenevalenka
Now that I see what you're trying to do, you could also just append the timezone to the string, like: date = DateTime.parse("Mon, Dec 27 6:30pm EDT")Chunchung
I realized the difference between now.offset and -5 is that it seems now.offset returns Rational(-5, 24)Chunchung
I can't do that because I don't know whether the string will contain a time in addition to the dateValenevalenka
Something is weird about the result of your method. It's a datetime with 6:30pm, but the timezone is wrong.Valenevalenka
The last version returns: 2011-12-27T18:30:00-05:00Chunchung
No problem, I'm glad we got it. The flopping around was killing me - too long staring at the screen ;-)Chunchung
V
16

OK I'm going to offer an answer to my own question

require 'time'
ENV["TZ"] = "US/Eastern"
Time.parse("Mon, Dec 27 6:30pm").to_datetime
=> #<DateTime: 2011-12-27T18:30:00-05:00 (117884327/48,-5/24,2299161)> 
Valenevalenka answered 2/1, 2011 at 3:34 Comment(0)
C
13

In Rails, this worked nicely for me

DateTime.parse "Mon, Dec 27 6:30pm #{Time.zone}"

It won't work in vanilla Ruby though.

Cancan answered 21/8, 2012 at 10:34 Comment(0)
C
8

Final answer ;-)

require 'date'
estHoursOffset = -5
estOffset = Rational(estHoursOffset, 24)
date = (DateTime.parse("Mon, Dec 27 6:30pm") - (estHoursOffset/24.0)).new_offset(estOffset)

(or -4 for EDT)

Chunchung answered 2/1, 2011 at 3:3 Comment(10)
Cool, I didn't know about the new_offset method.Twilatwilight
I tried that, but it returns ` #<DateTime: 2011-12-27T13:30:00-05:00 (117884317/48,-5/24,2299161)>`, which is 1:30pm EDT. I need 6:30pm EDT.Valenevalenka
I updated it to reflect EST offset. (p.s. you wrote EST and then EDT in your question)Chunchung
Thanks. I wonder why the result is different when you call #new_offset(-5) vs. #new_offset(DateTime.now.offset)Valenevalenka
Now that I see what you're trying to do, you could also just append the timezone to the string, like: date = DateTime.parse("Mon, Dec 27 6:30pm EDT")Chunchung
I realized the difference between now.offset and -5 is that it seems now.offset returns Rational(-5, 24)Chunchung
I can't do that because I don't know whether the string will contain a time in addition to the dateValenevalenka
Something is weird about the result of your method. It's a datetime with 6:30pm, but the timezone is wrong.Valenevalenka
The last version returns: 2011-12-27T18:30:00-05:00Chunchung
No problem, I'm glad we got it. The flopping around was killing me - too long staring at the screen ;-)Chunchung
C
5

DateTime#change()

You can try using change() after parsing it to alter the timezone offset:

DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-0400' )
# => Wed, 27 Dec 2017 18:30:00 -0400

You can also just use the hours:

DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-4' )
# => Wed, 27 Dec 2017 18:30:00 -0400

But, be careful, you cannot use an integer:

DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: -4 )
# => Wed, 27 Dec 2017 18:30:00 +0000

If you need to determine the correct offset to use based on a time zone you can do something like this:

offset = ( Time.zone_offset('EDT') / 1.hour ).to_s
# => "-4"

DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: offset )
# => Wed, 27 Dec 2017 18:30:00 -0400

You can also use change() to manually set other parts of the DateTime as well, like setting the hour to noon:

DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-4', hour: 12 )
# => Wed, 27 Dec 2017 12:00:00 -0400

Be careful with that one because you can see that it's cleared the minutes as well.

Here's the docs for the change() method: http://api.rubyonrails.org/v5.1/classes/DateTime.html#method-i-change

Chassis answered 18/12, 2017 at 3:33 Comment(1)
Bear in mind that time zones are not necessarily offset by whole hours: timeanddate.com/time/time-zones-interesting.html - If using Rails you could use Time.zone.formatted_offset for the offset.Sillabub
U
4

If you're using Rails' ActiveSupport:

"Mon, Dec 27 6:30pm".in_time_zone(-4.hours).to_datetime
# => Mon, 27 Dec 2021 18:30:00 -0400
Time.find_zone(-4.hours).parse("Mon, Dec 27 6:30pm").to_datetime
# => Mon, 27 Dec 2021 18:30:00 -0400

If you want to use the local daylight saving time (DST) rules, you could use:

"Mon, Dec 27 6:30pm".in_time_zone("Eastern Time (US & Canada)")
# => Mon, 27 Dec 2021 18:30:00 EST -05:00 
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Dec 27 6:30pm")
# => Mon, 27 Dec 2021 18:30:00 EST -05:00
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Dec 27 6:30pm").to_datetime
# => Mon, 27 Dec 2021 18:30:00 -0500
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Jun 27 6:30pm")
# => Sun, 27 Jun 2021 18:30:00 EDT -04:00
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Jun 27 6:30pm").to_datetime
# => Sun, 27 Jun 2021 18:30:00 -0400
Time.find_zone("EST5EDT").parse("Mon, Jun 27 6:30pm").to_datetime
# => Sun, 27 Jun 2021 18:30:00 -0400

Notice the date in June, above, is automatically set to EDT (-0400) because this date is in DST, contrary to the December date.

To force EST regardless if date is within DST or not:

Time.find_zone("EST").parse("Mon, Jun 27 6:30pm")
# => Sun, 27 Jun 2021 18:30:00 EST -05:00
Time.find_zone("EST").parse("Mon, Jun 27 6:30pm").to_datetime
# => Sun, 27 Jun 2021 18:30:00 -0500
Uppercase answered 17/6, 2021 at 17:51 Comment(0)
A
0

Deadly simple:

irb(main):034> d = DateTime.parse('March 17, at 18:00')
=> #<DateTime: 2024-03-17T18:00:00+00:00 ((2460387j,64800s,0n),+0s,2299161j)>

irb(main):035> DateTime.new(d.year, d.month, d.day, d.hour, d.minute, 0, '-04:00')
=> #<DateTime: 2024-03-17T18:00:00-04:00 ((2460387j,79200s,0n),-14400s,2299161j)>
Adest answered 14/3 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.