Parsing date using strftime - ruby-on-rails

I have a problem parsing dates taken in from scraping a website using Nokogiri. I scrape the datetime using
#date = h4.at('time[itemprop="startDate"]')[:datetime]
This gives me 2015-04-28 19:30:00 UTC, which is inserted into my date column, of type "datetime".
Using strptime I am trying to parse the date into a "dd/mm" format, and enter it into my Rails table:
Date.strptime(#date, "%Y-%m-%d %H:%M:%S %Z").strftime("%m/%d/%Y")
#event=Event.new
#event.date= #date
Any help would be very much appreciated.

Here's some code that might help:
require 'date'
require 'time'
date = Date.strptime('2015-04-28 19:30:00 UTC', "%Y-%m-%d %H:%M:%S %Z")
# => #<Date: 2015-04-28 ((2457141j,0s,0n),+0s,2299161j)>
date.strftime('%m/%d/%y')
# => "04/28/15"
Parsing into a Date object stores only the year, month and day information.
datetime = DateTime.strptime('2015-04-28 19:30:00 UTC', "%Y-%m-%d %H:%M:%S %Z")
# => #<DateTime: 2015-04-28T19:30:00+00:00 ((2457141j,70200s,0n),+0s,2299161j)>
datetime.strftime('%m/%d/%y')
# => "04/28/15"
time = Time.strptime('2015-04-28 19:30:00 UTC', "%Y-%m-%d %H:%M:%S %Z")
# => 2015-04-28 19:30:00 UTC
time.strftime('%m/%d/%y')
# => "04/28/15"
Parsing into a DateTime, or Time object captures all the information.
The error you're seeing is often caused by a date string in a format you don't expect. That often happens when you expect a value in 'mm/dd/yy' order, but actually receive one in 'dd/mm/yy' order. This happens because the US uses 'mm/dd/yy' and most of the rest of the world uses 'dd/mm/yy':
date = Date.strptime('2015-28-04', '%Y-%m-%d')
# ~> -:7:in `strptime': invalid date (ArgumentError)
or
date = Date.strptime('28-04-2015', '%m-%d-%Y')
# ~> -:7:in `strptime': invalid date (ArgumentError)
You can work around that by using some rescue statements to try several different formats.
You don't want to use parse because it'll assume 'dd/mm/yyyy' and will blow up with US dates, and is slower because it tries multiple formats before giving up. So, using fixed formats you expect is the way to go but you need to search for your various formats of date/datetime strings you'll expect to find and write format strings to match. And, since you're scraping pages, it's possible to find a LOT of bad/malformed values so program defensively.

You don't need strftime and you can parse the date with parse. Just convert the string to a Date object and assign that to your ActiveRecord attribute:
#event = Event.new
#event.date = Date.parse('2015-04-28 19:30:00 UTC')

Related

comparing datetime and time produces a false result

I am using Mongoid and Chronic gem. Chronic produces a Time object, and Mongoid Date object produces a DateTime object. So in Mongoid, when i want to get today, I do something like this:
Lead.last.send('lead date') # => {DateTime}2015-03-30T00:00:00-04:00
In Chronic, when I parse today, I get this:
Chronic.parse('today') # => {Time}2015-03-30 23:00:00 -0400
And I compare the two with ==, it produces false, even though they are the same date. I need the following query to give a result, when 'lead date' refers to today:
Lead.where("lead date" => Chronic.parse('today'))
What options do I have?
Does this code accurately replicate your issue?
require 'chronic'
require 'date'
text = "2015-03-30T00:00:00-04:00"
datetime = DateTime.parse(text)
time = Chronic.parse(text)
datetime == time
#=> false
Use the DateTime #to_time method, or the Time #to_datetime method:
datetime.to_time == time
#=> true
datetime == time.to_datetime
#=> true

Ruby on Rails invalid date error when parsing datetime string to convert to a different format

In my Rails App (Rails 2.3.14 and Ruby 1.8.7) I am trying to convert a datetime string into a different format to perform a search on my MySQL database but I am getting an invalid date error and I can't seem to figure out why, I've read a good few similar questions but I still can't seem to resolve the issue.
# check if filter contains a time stamp
if params[:sSearch].include?('/') and params[:sSearch].include?(':')
datetime = DateTime.strptime(params[:sSearch], "%Y-%m-%d %H:%M")
params[:sSearch] = datetime
end
Example scenario
04/11/13 16:14
should convert to
2013-11-04 16:14
I thought it might have been to do with the fact that the seconds aren't included in the front-end representation of the string as the precise datetime in the database table is 2013-11-04 16:14:52 so I included the seconds now but still getting the same error and I don't think that should matter since I am using the LIKE operand with wildcards on either side of the search term, so even without the seconds it should work.
You should use slashes in the format and replace %Y (four digit year) with %y (abbreviated two digit year) to get the desired result. Besides, the order of the date fields is reversed. The correct format would be:
"%d/%m/%y %H:%M"
I think you confused the purpose of strptime and strftime. Whereas the p in strptime stands for "parse" (make DateTime from String), the f in strftime stands for "format" (the other direction).
require 'date'
DateTime.strptime("04/11/13 16:14", "%Y-%m-%d %H:%M")
# ArgumentError: invalid date
DateTime.strptime("04/11/13 16:14", "%d/%m/%Y %H:%M")
#=> #<DateTime: 0013-11-04T16:14:00+00:00 ((1722836j,58440s,0n),+0s,2299161j)>
# Wrong! You do not want the year 0013, but 2013
DateTime.strptime("04/11/13 16:14", "%d/%m/%y %H:%M")
#=> #<DateTime: 2004-11-13T16:14:00+00:00 ((2453323j,58440s,0n),+0s,2299161j)>
# Correct
you can later convert it to the desired format with DateTime#strftime like this:
# parse the user input to a DateTime object
datetime = DateTime.strptime("04/11/13 16:14", "%d/%m/%y %H:%M")
# reformat it
params[:sSearch] = datetime.strftime("%Y-%m-%d %H:%M")
strptime converts the given string into a datetime object using the format given.
DateTime.strptime("04/11/13 16:14", "%m/%d/%y %H:%M").strftime("%Y-%m-%d %H:%M")
There is a problem with your template, try: DateTime.strptime("04/11/13 16:14", "%d/%m/%y %H:%M")

RoR: Parse datetime UTC string into timezone specific

Datetimes are being stored in MySQL as UTC.
In my app I've set: config.time_zone = 'UTC'
In my application_controller I set the users selected timezone:
around_filter :user_time_zone, :if => :current_user
def user_time_zone(&block)
Time.use_zone(current_user.time_zone, &block)
end
I can confirm this works by <%= Time.zone.now%> as it returns the user's set timezone
I then do a select query to grab the datetime field, and present it to the user as part of an array.
In my view, I have:
<%= Time.zone.parse(item[1]).strftime("%m/%d/%Y %I:%M %p") %>
which just outputs the datetime as-is (UTC), not in the user's specific time zone.
What do I need to change in order for the date and time to display correctly in the user's desired timezone?
Thanks for your time and assistance.
Edit:
Per Benjamin's suggestions, I had to modify it slightly to get it to work (was getting the same error) - Time.strptime(item[1], '%Y-%m-%d %H:%M:%S').in_time_zone(Time.zone) but 2 issues still remain.
1 - the original datetime is: 2013-07-25 22:27:50, but what is displayed is: 2013-07-25 16:27:50 -1000 my user timezone is Hawaii at -10 from UTC, but this only shows a 6 hr difference?
2 - How do I get this in a format that is easily readable by users (07/25/2013 12:27 PM)? Thanks again
Solved:
Thanks to Benjamin. I forgot to mention that I'm (stuck) using 1.8.7, so I had to work through a few minor differences between 1.8.7 and 1.9.3, but got it working with:
<%= DateTime.strptime(item[1], '%Y-%m-%d %H:%M:%S').in_time_zone(Time.zone).to_formatted_s(:long)%>
Updated: Got it into the format I wanted (06/20/2013 01:00 AM) using:
DateTime.strptime(item[1], '%Y-%m-%d %H:%M ').in_time_zone(Time.zone).strftime("%m/%d/%Y %I:%M %p")
Try this
Time.strptime(item[1], '%Y-%m-%dT%H:%M:%S%z').in_time_zone(Time.zone)
Answer to the bonus questions
Check the time zone of your db server and double check your rails data (default config / user TZ)
use to_formatted_s http://api.rubyonrails.org/classes/Time.html#method-i-to_formatted_s

Rails 3 Activerecord TimeWithZone to String without offset

I have:
irb(main):016:0> t[0].change_date
=> Tue, 08 May 2012 18:33:53 FET +03:00
irb(main):017:0> t[0].change_date.class
=> ActiveSupport::TimeWithZone
irb(main):018:0> t[0].change_date.to_s
=> "2012-05-08 18:33:53 +0300"
How Can I get a string representation of datetime but without offset +3000? I need only "2012-05-08
18:33:53"
You can use strftime to format the way you would like to view the datetime.
The strftime documentation.
So, in your case, if you would like to see the date as: 2012-05-08 18:33:53, then use:
t[0].change_date.strftime("%Y-%m-%d %H:%M:%S")
You can use the helper method in ActiveSupport like
t[0].change_date.to_formatted_s(:db)
As the to_fomatted_s is aliased to_s you can also use
t[0].change_date.to_s(:db)
You can check support for time formats in the documentation date format (http://api.rubyonrails.org/classes/Date.html#DATE_FORMATS)

Converting twitter post dates to datetime in rails

I am trying to convert the twitter post dates into datetime objects but for some reason they are not converting correctly. If I do this:
d = '12:06 AM Oct 15th'
and
d = DateTime.parse(d)
or
Tweet.new :body => "test", :created_at => d
then the date ends up Sun Nov 15 00:06:00 -0500 2009. All dates are converting and containing the month of November. Am I totally missing something?
DateTime.parse expects the passed in string to be in a standard format. Since that is not the case with your strings, you'll have to use DateTime.strptime and pass it your string representation of date/time, along with the corresponding format string. In your case something like this should work:
d = DateTime.strptime '12:06 AM Oct 15th', '%H:%M %p %b %d'
d.to_s # => "2009-10-15T00:06:00+00:00"
You can check the documentation to see what each of the formatting directions means.
Always always always use the Chronic gem. Will solve all your problems when it comes to date/time parsing: http://github.com/mojombo/chronic
You might be able to get away with mangling it slightly and then using the parser:
s = '12:06 AM Oct 15th'
d = DateTime.parse(s.sub(/(\w\w\w) /, '\1'))
puts d.to_s
# => 2009-10-15T00:06:00+00:00

Resources