如何检查字符串是否是有效日期

时间:2010-06-02 07:46:13

标签: ruby-on-rails ruby string date

我有一个字符串:"31-02-2010",想要检查它是否是有效日期。 最好的方法是什么?

我需要一个方法,如果字符串是有效日期,则返回true;如果不是,则返回false。

15 个答案:

答案 0 :(得分:103)

require 'date'
begin
   Date.parse("31-02-2010")
rescue ArgumentError
   # handle invalid date
end

答案 1 :(得分:48)

这是一个简单的一个班轮:

DateTime.parse date rescue nil

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

答案 2 :(得分:46)

d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i

答案 3 :(得分:27)

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

Date#parse试图找出使用哪个,但是一年中有很多天,格式之间的模糊不清可能导致解析问题。

我建议找出用户的LOCALE,然后,基于此,您将知道如何使用Date.strptime进行智能解析。找到用户所在位置的最佳方法是在注册期间询问他们,然后在他们的首选项中提供一个设置以进行更改。假设您可以通过一些聪明的启发式挖掘它而不打扰用户获取该信息,那么很容易失败,所以请问。

这是使用Date.parse的测试。我在美国:

>> 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并不喜欢它。第二个对欧洲来说是正确的,但如果你的客户主要是美国的,那么你会得到很多糟糕的解析日期。

Ruby的Date.strptime用作:

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

答案 4 :(得分:26)

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

答案 5 :(得分:8)

我想延长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'

答案 6 :(得分:3)

尝试所有日期的正则表达式:

/(\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/

上对此进行测试

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

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

答案 7 :(得分:3)

验证日期的另一种方法:

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)

答案 8 :(得分:3)

更严格的解决方案

如果指定了预期的日期格式,则更容易验证日期的正确性。然而,即便如此,Ruby对我的用例有点过于宽容:

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

显然,这些字符串中至少有一个指定了错误的工作日,但Ruby很高兴忽略了这一点。

这是一种没有的方法;它根据date.strftime(format)验证format转换回使用Date.strptime解析的相同输入字符串。

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

答案 9 :(得分:2)

发布此信息是因为它稍后可能对某人有用。不知道这是否是一个“好”的方式,但它适用于我并且是可扩展的。

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行指定你的有效格式列表。不是火箭科学,但是它很容易扩展,让你只需检查字符串就像这样:

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

答案 10 :(得分:0)

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

答案 11 :(得分:0)

您可以尝试以下方法,这是一种简单的方法:

"31-02-2010".try(:to_date)

但你需要处理异常。

答案 12 :(得分:0)

此示例的Date.parse未引发异常:

Date.parse("12!12*2012")
=> Thu, 12 Apr 2018

Date.parse("12!12&2012")
=> Thu, 12 Apr 2018

我更喜欢这个解决方案:

Date.parse("12!12*2012".gsub(/[^\d,\.,\-]/, ''))
=> ArgumentError: invalid date

Date.parse("12-12-2012".gsub(/[^\d,\.,\-]/, ''))
=> Wed, 12 Dec 2012

Date.parse("12.12.2012".gsub(/[^\d,\.,\-]/, ''))
=> Wed, 12 Dec 2012

答案 13 :(得分:0)

类似于@ironsand的解决方案,我更喜欢在String上创建一个重写的实例方法:

class String
  def valid_datetime?
    to_datetime
    true
  rescue ArgumentError
    false
  end
end

答案 14 :(得分:-1)

方法:

git merge origin zag902

用法:

require 'date'
def is_date_valid?(d)
  Date.valid_date? *"#{Date.strptime(d,"%m/%d/%Y")}".split('-').map(&:to_i) rescue nil
end

如果config [:dates] =&#34; 12/10 / 2012,05 / 09/1520&#34;

,则返回true或false