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?

dan
  • 43,914
  • 47
  • 153
  • 254

5 Answers5

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)> 
dan
  • 43,914
  • 47
  • 153
  • 254
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.

brad
  • 9,573
  • 12
  • 62
  • 89
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)

Sean DeNigris
  • 6,306
  • 1
  • 31
  • 37
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

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • Bear in mind that time zones are not necessarily offset by whole hours: https://www.timeanddate.com/time/time-zones-interesting.html - If using Rails you could use `Time.zone.formatted_offset` for the offset. – Wodin Oct 23 '19 at 15:59
3

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
dlauzon
  • 1,241
  • 16
  • 23