How to check if a string is a valid date
Solution 1
require 'date'
begin
Date.parse("31-02-2010")
rescue ArgumentError
# handle invalid date
end
Solution 2
Here is a simple one liner:
DateTime.parse date rescue nil
I probably wouldn't recommend doing exactly this in every situation in real life as you force the caller to check for nil, eg. particularly when formatting. If you return a default date|error it may be friendlier.
Solution 3
d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i
Solution 4
Parsing dates can run into some gotcha's, especially when they are in a MM/DD/YYYY or DD/MM/YYYY format, such as short dates used in U.S. or Europe.
Date#parse
attempts to figure out which to use, but there are many days in a month throughout the year when ambiguity between the formats can cause parsing problems.
I'd recommend finding out what the LOCALE of the user is, then, based on that, you'll know how to parse intelligently using Date.strptime
. The best way to find where a user is located is to ask them during sign-up, and then provide a setting in their preferences to change it. Assuming you can dig it out by some clever heuristic and not bother the user for that information, is prone to failure so just ask.
This is a test using Date.parse
. I'm in the U.S.:
>> Date.parse('01/31/2001')
ArgumentError: invalid date
>> Date.parse('31/01/2001') #=> #<Date: 2001-01-31 (4903881/2,0,2299161)>
The first was the correct format for the U.S.: mm/dd/yyyy, but Date didn't like it. The second was correct for Europe, but if your customers are predominately U.S.-based, you'll get a lot of badly parsed dates.
Ruby's Date.strptime
is used like:
>> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>
Solution 5
Date.valid_date? *date_string.split('-').reverse.map(&:to_i)
Salil
I'm a software engineering graduate from Nagpur University (BE) with good academic standing and strong professional experience. 12 year experience in Ruby, Ruby on Rails. Profound knowledge of working with dynamic and database-driven websites and services. Very solid understanding of Web 2.0 technologies HTML, XML, CSS, jQuery, jQuery-UI, Ajax and JavaScript. Knowledge of distributed revision control system like Git. Experience working with like PostgreSQL and MySQL database. Experience in Elastic Search Engine. Knowledge of NoSQL such as MongoDB. Experience with Agile, Iterative, and Test-Driven Development methods
Updated on October 04, 2020Comments
-
Salil over 3 years
I have a string:
"31-02-2010"
and want to check whether or not it is a valid date. What is the best way to do it?I need a method which which returns true if the string is a valid date and false if it is not.
-
corroded almost 14 yearswhy not just make a date_time drop down instead of taking in a string that you have to validate?
-
Salil almost 14 yearsclient's requirement. i already suggest it but can't do that :)
-
Seanny123 almost 11 yearsAs a general rule, aren't you supposed to do input validation on the front end of an application?
-
n13 over 10 yearsMuch better answers here - this is how to do it. stackoverflow.com/questions/597328/…
-
SparK over 8 yearsAlways validate on the backend, no matter how good your front-end is, don't trust it!
-
ymoreau over 5 yearsPossible duplicate of How do I validate a date in rails?
-
Aryeh Beitz over 5 yearsI use this:
"31-02-2010".to_time.present?
-
-
hoyhoy over 12 yearsYour LOCALE seems off. I get this >> Date.parse('01/31/2001') => Wed, 31 Jan 2001 >> ?> Date.parse('31/01/2001') ArgumentError: invalid date
-
Pier-Olivier Thibault almost 12 yearsIt's not a Date class feature, it's exception handling.
-
Greconomist almost 12 yearsDate.parse('2012-08-13== 00:00:00') # => Mon, 13 Aug 2012
-
Arnis Lapsa over 11 yearsexceptions should be used only when you don't really expect an error
-
yagooar over 11 yearsThis regular expressions only match some fixed formats, without caring about the semantics of a date. Your matcher allows dates such as
32-13-2010
which is wrong. -
yagooar over 11 yearsUsing a "catch-it-all" rescue should be considered an anti-pattern. It can hide out other errors which we don't expect and make the debugging of the code extremely difficult.
-
Matthew Brown about 11 yearsSo... if it is indeed an anti-pattern, how would you answer the question?
-
Neil Goodman over 10 yearsGood enough if you want a rough estimate if any arbitrary string could be parsed as a date.
-
mrt over 10 yearsAs bad as it looks with the exception handling this is how the default Rails validators are written as well: i.e. github.com/rails/rails/blob/…
-
n13 over 10 yearsSorry this is a wrong answer. It doesn't check whether or not a string is a valid date, it merely checks of Date.parse can parse the string. Date.parse seems to be very forgiving when it comes to dates, e.g. it will parse "FOOBAR_09_2010" as the date 2012-09-09.
-
n13 over 10 yearsThis is pretty simple and good for enforcing a xx-xx-YYYY format
-
Ashley Raiteri over 10 yearsIf you want to enforce a strict single format date string option, then this is the best option as it avoids Exceptions and is deterministic. Date.valid_date? is the method to use at least for Ruby 2. ruby-doc.org/stdlib-2.0.0/libdoc/date/rdoc/…
-
Matstar over 10 yearsWhat version of Ruby supports
is_valid?
? Tried 1.8, 2.0 and 2.1. None of them seem to have that one. All seem to havevalid_date?
, though. -
Matstar over 10 yearsExcellent, thanks. This one seems to be available at least in 1.8, 2.0 and 2.1. Note that you need to
require "date"
first or you'll get "undefined method". -
PJP almost 10 yearsWhere "rough estimate" means values like
'00/00/0000'
and'99-99/9999'
are possible candidates. -
cesoid over 9 yearsNot sure if I'm being daft here, but this seems to explain only how to parse a date, not how to validate it. The accepted answer uses the ArgumentError exception, but that doesn't seem like a good idea, for reasons noted in a comment there.
-
PJP over 9 yearsThere is a known situation where you can't validate a date. It's where the day and month values are ambiguous, and you have to know the format of the incoming date string. And, that is what the answer is saying. If it looks like
01/01/2014
, which is the month and which is the day? In the US month would be first, the rest of the world it'd be second. -
Tom Lord about 9 yearsA brilliant example of when custom regex is a BAD IDEA!
-
vincentp almost 9 yearsThis method can raise an exception 'ArgumentError: wrong number of arguments' instead of returning false. For example if your string contains slashes instead of dashes
-
vincentp almost 9 yearsMaybe we can do something like this, for handling bad formatted date :
Date.valid_date? *Array.new(3).zip(date_string.split('-')).transpose.last.reverse.map(&:to_i)
-
Ankita.P almost 9 yearsis there any valid_date? method for above solution because it gives error when I do Date.valid_date?(Date.parse('2015-07-13')) since parsed object is in the different date format
-
cesoid almost 9 yearsThe ambiguity that prevents you from validating the date only does so to the extent that it also prevents you from parsing the date, but you've made a good attempt at parsing it with known information. It would be nice to use some of what you have to try to validate as best as we can. Can you think of how to do that without using exceptions that Date.parse and Date.strptime create?
-
PJP almost 9 yearsDate parsing in "mm/dd/yyyy" or "dd/mm/yyyy" format REQUIRES foreknowledge of the date's format. Without that we can't determine which it is unless we have a sampling from one source/user, then parse using both forms and then see which form generated the most exceptions and use the other. This breaks down when parsing dates from multiple sources, especially when they're global or they've been entered by hand. The only accurate way to deal with dates is to not allow hand-entry, to force users to use date-pickers, or only allow ISO date formats that are unambiguous.
-
Mike Bethany over 7 yearsUsing error trapping as logic is really, really bad design.
-
baash05 about 7 yearsDateTime.parse "123" rescue nil . This returns a real date.. May 3 2017
-
bonafernando almost 7 years
Date.strptime(date, '%d/%m/%Y') rescue nil
-
smoyth about 6 yearsUse of inline
rescue
is discouraged. -
Lucas Caton about 6 yearsThat's exactly what I was looking for. Thank you!
-
oneWorkingHeadphone about 5 years@n13 points out, this one will bite you. It says explicitly in the docs that this is not a validator[1]. Try typing
Date.parse('Monterey')
into IRB, you will get a valid date. 1: ruby-doc.org/stdlib-2.6.1/libdoc/date/rdoc/… -
Qwertie about 5 yearsArguably
01/31/2001
is an invalid date and parse is working as intended. -
saGii almost 5 yearsthis fails for the cases like "2019-1-1" which is a valid date but the strftime makes it 2019-01-01
-
Nathan Long almost 5 years@saGii that doesn't fit the format specified (iso8601 - see
Date.today().iso8601
);%m
is zero-padded. If you want something different, see ruby-doc.org/stdlib-2.4.0/libdoc/date/rdoc/… -
csalvato over 3 yearsI like this method the best, personally. In my app, I opted to override String: stackoverflow.com/a/64190303/987115
-
Sunny over 3 yearsBuilding on top of that, you can simplify this to:
Date.valid_date?(*Date._parse(date).values)