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

martincarlin87 picture martincarlin87 · Dec 17, 2013 · Viewed 7.9k times · Source

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.

Answer

Patrick Oscity picture Patrick Oscity · Dec 17, 2013

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")