如何检查一个string是否是一个有效的date

我有一个string: "31-02-2010"并要检查它是否是一个有效的date。 什么是最好的办法呢?

我需要一个方法,如果string是一个有效的date,返回true,如果不是,则返回false。

 require 'date' begin Date.parse("31-02-2010") rescue ArgumentError # handle invalid date end 
 d, m, y = date_string.split '-' Date.valid_date? y.to_i, m.to_i, d.to_i 

这里是一个简单的一行:

 DateTime.parse date rescue nil 

我可能不会build议在现实生活中的每一种情况下都这样做,因为你强迫调用者检查零,例如。 特别是格式化时。 如果您返回默认date,则可能会更友好。

parsingdate可能会遇到一些问题,特别是当它们处于MM / DD / YYYY或DD / MM / YYYY格式时,例如在美国或欧洲使用的短date。

Date#parse试图找出使用哪一个,但是一年中一个月有很多天,格式之间的歧义可能导致parsing问题。

我build议找出用户的LOCALE,然后,基于此,您将知道如何使用Date.strptime智能地进行Date.strptime 。 find用户所在位置的最好方法是在注册时询问他们,然后在他们的偏好中提供一个设置来更改它。 假设你可以通过一些聪明的启发式方法挖掘出来,而不是为了这个信息而困扰用户,那么很容易出现失败,所以请问。

这是一个使用Date.parse的testing。 我在美国:

 >> Date.parse('01/31/2001') ArgumentError: invalid date >> Date.parse('31/01/2001') #=> #<Date: 2001-01-31 (4903881/2,0,2299161)> 

第一个是美国的正确格式:mm / dd / yyyy,但是Date不喜欢它。 第二个对欧洲是正确的,但是如果你的客户主要以美国为基地,你会得到很多严重的分析date。

Ruby的Date.strptime用法如下:

 >> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)> 

Date.valid_date? *date_string.split('-').reverse.map(&:to_i)

我想延长Date类。

 class Date def self.parsable?(string) begin parse(string) true rescue ArgumentError false end end end 

 Date.parsable?("10-10-2010") # => true Date.parse("10-10-2010") # => Sun, 10 Oct 2010 Date.parsable?("1") # => false Date.parse("1") # ArgumentError: invalid date from (pry):106:in `parse' 

尝试所有date的正则expression式:

 /(\d{1,2}[-\/]\d{1,2}[-\/]\d{4})|(\d{4}[-\/]\d{1,2}[-\/]\d{1,2})/.match("31-02-2010") 

对于只有你的格式与前导零,最后一年和破折号:

 /(\d{2}-\d{2}-\d{4})/.match("31-02-2010") 

[ – /]表示要么 – 或/,正斜杠必须逃脱。 你可以在http://gskinner.com/RegExr/上testing

添加下面的行,如果你使用第一个正则expression式,它们将全部被突出显示,没有第一个和最后一个/(它们用于ruby代码)。

 2004-02-01 2004/02/01 01-02-2004 1-2-2004 2004-2-1 

另一种validationdate的方法:

 date_hash = Date._parse(date.to_s) Date.valid_date?(date_hash[:year].to_i, date_hash[:mon].to_i, date_hash[:mday].to_i) 

发布此信息是因为稍后可能对其他人有用。 没有线索,如果这是一个“好”的方式来做到这一点,但它适用于我,是可扩展的。

 class String def is_date? temp = self.gsub(/[-.\/]/, '') ['%m%d%Y','%m%d%y','%M%D%Y','%M%D%y'].each do |f| begin return true if Date.strptime(temp, f) rescue #do nothing end end return false end end 

这个String类的附加组件允许你在第4行中指定你的分隔符列表,然后在第5行中指定你的有效格式列表。不是火箭科学,而是使它很容易扩展,并且让你简单地检查一个string,如下所示:

 "test".is_date? "10-12-2010".is_date? params[:some_field].is_date? etc. 

更严格的解决scheme

如果您指定期望的date格式,则更容易validationdate的正确性。 然而,即使如此,Ruby对我的用例来说有点太宽容了:

 Date.parse("Tue, 2017-01-17", "%a, %Y-%m-%d") # works Date.parse("Wed, 2017-01-17", "%a, %Y-%m-%d") # works - !? 

显然,至less有一个string指定了错误的工作日,但是Ruby愉快地忽略了这一点。

这是一个方法,没有; 它validationdate.strftime(format)转换回相同的inputstring,它根据formatDate.strptimeparsing。

 module StrictDateParsing # If given "Tue, 2017-01-17" and "%a, %Y-%m-%d", will return the parsed date. # If given "Wed, 2017-01-17" and "%a, %Y-%m-%d", will error because that's not # a Wednesday. def self.parse(input_string, format) date = Date.strptime(input_string, format) confirmation = date.strftime(format) if confirmation == input_string date else fail InvalidDate.new( "'#{input_string}' parsed as '#{format}' is inconsistent (eg, weekday doesn't match date)" ) end end InvalidDate = Class.new(RuntimeError) end 
 require 'date' #new_date and old_date should be String # Note we need a () def time_between(new_date, old_date) new_date = (Date.parse new_date rescue nil) old_date = (Date.parse old_date rescue nil) return nil if new_date.nil? || old_date.nil? (new_date - old_date).to_i end puts time_between(1,2).nil? #=> true puts time_between(Time.now.to_s,Time.now.to_s).nil? #=> false