代码之家  ›  专栏  ›  技术社区  ›  Salil

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

  •  99
  • Salil  · 技术社区  · 14 年前

    我有一根绳子: "31-02-2010" 并且想检查它是否是一个有效的日期。 最好的方法是什么?

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

    14 回复  |  直到 6 年前
        1
  •  100
  •   Dennis    10 年前
    require 'date'
    begin
       Date.parse("31-02-2010")
    rescue ArgumentError
       # handle invalid date
    end
    
        2
  •  45
  •   Max Schulze Sohan    10 年前
    d, m, y = date_string.split '-'
    Date.valid_date? y.to_i, m.to_i, d.to_i
    
        3
  •  45
  •   the Tin Man    7 年前

    下面是一个简单的一行程序:

    DateTime.parse date rescue nil
    

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

        4
  •  27
  •   the Tin Man    13 年前

    解析日期可能会遇到一些gotcha,特别是当它们是mm/dd/yyyy或dd/mm/yyyy格式时,例如在美国或欧洲使用的短日期。

    Date#parse 试图找出要使用哪种格式,但在一年中的一个月中有很多天格式之间的不确定性会导致解析问题。

    我建议您找出用户的区域设置,然后基于此,您将知道如何使用 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.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>
    
        5
  •  26
  •   Samer Buna    11 年前

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

        6
  •  8
  •   ironsand    9 年前

    我想延长 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'
    
        7
  •  3
  •   MrFox    13 年前

    尝试所有日期的regex:

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

    添加以下行,如果使用第一个regex,它们都将突出显示,没有第一个和最后一个(它们用于Ruby代码)。

    2004-02-01
    2004/02/01
    01-02-2004
    1-2-2004
    2004-2-1
    
        8
  •  3
  •   Slava Zharkov    8 年前

    验证日期的另一种方法:

    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)
    
        9
  •  3
  •   Nathan Long    8 年前

    更严格的解决方案

    如果您指定了预期的日期格式,就更容易验证日期的正确性。然而,即便如此,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) 转换回与解析时相同的输入字符串 Date.strptime 根据 format .

    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
    
        10
  •  2
  •   Dave Sanders    13 年前

    发布这个,因为它可能在以后对某人有用。不知道这是不是一个“好”的方法,但它对我有效,是可扩展的。

    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
    

    这个字符串类的附加组件允许您在第4行中指定分隔符列表,然后在第5行中指定有效格式列表。不是火箭科学,但可以很容易地扩展,让您简单地检查这样的字符串:

    "test".is_date?
    "10-12-2010".is_date?
    params[:some_field].is_date?
    etc.
    
        11
  •  0
  •   sander    7 年前
    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
    
        12
  •  0
  •   kellanburket    6 年前

    您可以尝试以下简单方法:

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

    但你需要处理这个例外。

        13
  •  0
  •   Igor Biryukov    6 年前

    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
    
        14
  •  -1
  •   Templum Iovis    7 年前

    方法:

    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].split(",").all? { |x| is_date_valid?(x)}
    

    如果config[:dates]=“12/10/2012,05/09/1520”,则返回“真”或“假”