Convert a Ruby string to proper Date and Time - ruby

I have a Ruby variable containing Timestamp , I need to get Date and Time from it , I am able to get Date (but wrong) time is always 00:00 (note: li is a variable getting from a file)
li = 'Date: Wed, 25 Dec 2019 23:16:52 -0600'
date = li.delete("Date: ")
=> "Wd,25c2019231652-0600"
puts date
Wd,25c2019231652-0600
Date.parse(date).to_s
=> "2020-09-25"
Time.parse(date).to_s
=> "2020-09-25 00:00:00 +0530"
DateTime.parse(date).to_s
=> "2020-09-25T00:00:00+00:00"
DateTime.parse(date).strftime('%Y-%d-%m %H:%M:%S')
=> "2020-25-09 00:00:00"
I need to get correct date and Time (either in UTC or -0600)

li = 'Date: Wed, 25 Dec 2019 23:16:52 -0600'
require 'date'
Date.strptime(li, 'Date: %a, %d %b %Y %H:%M:%S %z')
#=> #<Date: 2019-12-25 ((2458843j,0s,0n),+0s,2299161j)>
See Date::strptime. Date-time formatting directives are given in the doc DateTime#strftime.

Related

Ruby: Datetime to UTC conversion

I am trying to convert the below date and time combination to UTC
from_date: "2017-06-19",from_time: "14:00"
to_date: "2017-06-19", to_time: "23:00"
Timezone: EDT
I am using below piece of code for conversion
Date.parse(dt).to_datetime + Time.parse(t).utc.seconds_since_midnight.seconds
And it gives the wrong date value for the to_date & to_time combination.
Output:
Date.parse(from_date).to_datetime +
Time.parse(from_time).utc.seconds_since_midnight.seconds
#⇒ **Mon, 19 Jun 2017 18:00:00 +0000**
Date.parse(to_date).to_datetime +
Time.parse(to_time).utc.seconds_since_midnight.seconds
#⇒ **Mon, 19 Jun 2017 03:00:00 +0000**
Above conversion should give "Tue, 20 Jun 2017 03:00:00 +0000" instead.
Below line of codes worked for me:
parsed_date = Time.zone.parse(from_date).strftime('%Y-%m-%d')
parsed_time = Time.zone.parse(from_time).strftime('%T')
Time.parse(parsed_date + ' ' + parsed_time).utc.strftime('%F %T')
require 'time'
from = Time.parse "2017-06-19 14:00 US/Eastern"
=> 2017-06-19 14:00:00 -0400
from.utc
=> 2017-06-19 18:00:00 UTC
to = Time.parse "2017-06-19 23:00 US/Eastern"
=> 2017-06-19 23:00:00 -0400
to.utc
=> 2017-06-20 03:00:00 UTC
Though you can also specify the timezone offset without using the string, doing it this way handles Daylight Savings Time.
I think this is shorter:
from_date = "2017-06-19"
from_time = "14:00"
DateTime.strptime("#{from_date}T#{from_time}ZEDT", "%Y-%m-%dT%H:%MZ%z").utc
=> Mon, 19 Jun 2017 18:00:00 +000
to_date = "2017-06-19"
to_time = "23:00"
DateTime.strptime("#{to_date}T#{to_time}ZEDT", "%Y-%m-%dT%H:%MZ%z").utc
=> Tue, 20 Jun 2017 03:00:00 +0000

How to parse date and time in custom format according to correct time zone [duplicate]

This question already has answers here:
Rails: How to parse date-time string into a specific time zone
(7 answers)
Closed 6 years ago.
> input = "12/31/2015 23:59"
> format = "%m/%d/%Y %H:%M"
> Time.zone = "US/Eastern"
> Time.zone.utc_offset
=> -18000
> Time.strptime(input, format)
=> 2015-12-31 23:59:00 +0100
> DateTime.strptime(input, format)
=> Thu, 31 Dec 2015 23:59:00 +0000
Whereas I want to get 2015-12-31 23:59:00 -0500
As you can see both versions of strptime ignore configured time zone (one uses UTC and one uses system/machine time zone).
How to parse given input in custom format in Time.zone?
One solution would be to convert parsed time into ISO string, strip incorrect time zone information and parse again, this time using Time.zone.parse which uses Time.zone:
> parsed = Time.strptime(input, "%m/%d/%Y %H:%M")
> Time.zone.parse(parsed.to_s.gsub(/\+\d\d:?\d\d/, ""))
=> 2015-12-31 23:59:00 -0500
One solution would be to convert parsed time into ISO string, strip incorrect time zone information and parse again, this time using Time.zone.parse which uses Time.zone:
> parsed = Time.strptime(input, "%m/%d/%Y %H:%M")
> Time.zone.parse(parsed.to_s.gsub(/\+\d\d:?\d\d/, ""))
=> 2015-12-31 23:59:00 -0500
It's also possible to append time zone to input (and format):
> DateTime.strptime(input + Time.zone.name, format + " %Z")
=> Thu, 31 Dec 2015 23:59:00 -0500
Both solutions seem like a hackish and I was hoping something more elegant.

convert ruby date to string without losing format

I'm trying to convert a Ruby Date object to a string. The format of the date is: Sun, 15 Sep 2013
However, when I convert it to a string using #to_s it gives me the following: "2013-09-15"
Instead, I want it to become: "Sun, 15 Sep 2013"
Use Date#strftime there are so many options
require 'date'
date = Date.parse("Sun, 15 Sep 2013") # => #<Date: 2013-09-15 ((2456551j,0s,0n),+0s,2299161j)>
date.strftime("%a, %d %b %Y") # => "Sun, 15 Sep 2013"
strftime works well, however, if you find that you're using the same format in multiple places, you will find using the Rails Date#to_formatted_s method a more appropriate option. You can use the built-in formats:
date.to_formatted_s(:short)
date.to_formatted_s(:long)
or, you can create your own formats, adding them to Date::DATE_FORMATS:
Date::DATE_FORMATS[:my_format] = '%a, %d %b %Y'
date.to_formatted_s(:my_format)
This will keep you from spreading formatting strings throughout your app.

Ruby: combine Date and Time objects into a DateTime

Simple question, but I can't find a good or definitive answer. What is the best and most efficient way to combine Ruby Date and Time objects (objects, not strings) into a single DateTime object?
I found this, but it's not as elegant you would hope:
d = Date.new(2012, 8, 29)
t = Time.now
dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec, t.zone)
By the way, the ruby Time object also stores a year, month, and day, so you would be throwing that away when you create the DateTime.
When using seconds_since_midnight, changes in daylight savings time can lead to unexpected results.
Time.zone = 'America/Chicago'
t = Time.zone.parse('07:00').seconds_since_midnight.seconds
d1 = Time.zone.parse('2016-11-06').to_date # Fall back
d2 = Time.zone.parse('2016-11-07').to_date # Normal day
d3 = Time.zone.parse('2017-03-12').to_date # Spring forward
d1 + t
#=> Sun, 06 Nov 2016 06:00:00 CST -06:00
d2 + t
#=> Mon, 07 Nov 2016 07:00:00 CST -06:00
d3 + t
#=> Sun, 12 Mar 2017 08:00:00 CDT -05:00
Here's an alternative, similar to #selva-raj's answer above, using string interpolation, strftime, and parse. %F is equal to %Y-%m-%d and %T is equal to %H:%M:%S.
Time.zone = 'America/Chicago'
t = Time.zone.parse('07:00')
d1 = Time.zone.parse('2016-11-06').to_date # Fall back
d2 = Time.zone.parse('2016-11-07').to_date # Normal day
d3 = Time.zone.parse('2017-03-12').to_date # Spring forward
Time.zone.parse("#{d1.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 06 Nov 2016 07:00:00 CST -06:00
Time.zone.parse("#{d2.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 07 Nov 2016 07:00:00 CST -06:00
Time.zone.parse("#{d3.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 12 Mar 2017 07:00:00 CDT -05:00
Simple:
Date.new(2015, 2, 10).to_datetime + Time.parse("16:30").seconds_since_midnight.seconds
# => Object: Tue, 10 Feb 2015 16:30:00 +0000
You gotta love Ruby!
If using Rails, try any of these:
d = Date.new(2014, 3, 1)
t = Time.parse("16:30")
dt = d + t.seconds_since_midnight.seconds
# => ActiveSupport::TimeWithZone
dt = (d + t.seconds_since_midnight.seconds).to_datetime
# => DateTime
dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec)
# => DateTime
If you are using Ruby on Rails, this works great.
I built a method to extend the DateTime class to combine a date and a time. It takes the zone from the date so that it does not end up an hour off with daylight savings time.
Also, for convenience, I like being able to pass in strings as well.
class DateTime
def self.combine(d, t)
# pass in a date and time or strings
d = Date.parse(d) if d.is_a? String
t = Time.zone.parse(t) if t.is_a? String
# + 12 hours to make sure we are in the right zone
# (eg. PST and PDT switch at 2am)
zone = (Time.zone.parse(d.strftime("%Y-%m-%d")) + 12.hours ).zone
new(d.year, d.month, d.day, t.hour, t.min, t.sec, zone)
end
end
So you can do:
DateTime.combine(3.weeks.ago, "9am")
or
DateTime.combine("2015-3-26", Time.current)
etc...
I found another way, I hope this is correct.
datetojoin=Time.parse(datetime).strftime("%Y-%m-%d")
timetojoin=Time.parse(time).strftime("%T")
joined_datetime = Time.parse(datetojoin +" "+ timetojoin).strftime("%F %T")
Any thoughts? Please share.

convert String to DateTime

I need to parse following String into a DateTime Object:
30/Nov/2009:16:29:30 +0100
Is there an easy way to do this?
PS: I want to convert the string above as is. The colon after the year is not a typo. I also want to solve the problem with Ruby and not RoR.
Shouldn't this also work for Rails?
"30/Nov/2009 16:29:30 +0100".to_datetime
DateTime.strptime allows you to specify the format and convert a String to a DateTime.
I have had success with:
require 'time'
t = Time.parse(some_string)
This will convert the string in date to datetime, if using Rails:
"05/05/2012".to_time
Doc Reference: https://apidock.com/rails/String/to_time
I used Time.parse("02/07/1988"), like some of the other posters.
An interesting gotcha was that Time was loaded by default when I opened up IRB, but Time.parse was not defined. I had to require 'time' to get it to work.
That's with Ruby 2.2.
convert string to date:
# without timezone
DateTime.strptime('2012-12-09 00:01:36', '%Y-%m-%d %H:%M:%S')
=> Sun, 09 Dec 2012 00:01:36 +0000
# with specified timezone
DateTime.strptime('2012-12-09 00:01:36 +8', '%Y-%m-%d %H:%M:%S %z')
=> Sun, 09 Dec 2012 00:01:36 +0800
refer to:
https://ruby-doc.org/stdlib-3.1.1/libdoc/date/rdoc/Date.html
in Ruby 1.8, the ParseDate module will convert this and many other date/time formats. However, it does not deal gracefully with the colon between the year and the hour. Assuming that colon is a typo and is actually a space, then:
#!/usr/bin/ruby1.8
require 'parsedate'
s = "30/Nov/2009 16:29:30 +0100"
p Time.mktime(*ParseDate.parsedate(s)) # => Mon Nov 30 16:29:30 -0700 2009
You can parse a date time string with a given timezone as well:
zone = "Pacific Time (US & Canada)"
ActiveSupport::TimeZone[zone].parse("2020-05-24 18:45:00")
=> Sun, 24 May 2020 18:45:00 PDT -07:00

Resources