怎么样:Date.parse(“ 123 456 789”)== 2019年5月3日,星期五?

时间:2019-03-19 16:09:59

标签: ruby

标题几乎说明了一切。我正在尝试评估CSV导入日期的有效性,但如果有人选择电话号码列作为出生日期,则日期解析仍会通过

3 个答案:

答案 0 :(得分:6)

  

如何:Date.parse(“ 123 456 789”)== 2019年5月3日,星期五?

Date._parse(带有下划线)返回原始数据:

Date._parse('123 456 789')
#=> {:yday=>123}

Ruby将123视为一年中的某一天,而当年的第123天是5月3日。

答案 1 :(得分:4)

Date#parse上的文档明确指出:

  

此方法不能用作验证器。

这意味着该方法是杂项的,它将根据任何输入产生一个日期。您需要改用Date#iso8601

main > Date.iso8601("2019-03-19")
#⇒ #<Date: 2019-03-19 ((2458562j,0s,0n),+0s,2299161j)>
main > Date.iso8601("123 456 789")
#⇒ ArgumentError: invalid date

答案 2 :(得分:0)

您(可能还有其他人)可能会发现以下方法很有用。我做了以下假设:

  • 年份必须为四位数;
  • 可以忽略和删除无效的逗号(例如,“ Jan,3 2019”);和 可以忽略和删除星期几,即使该日期对日期无效。

MON_NAMES = Date::MONTHNAMES.drop(1).concat(Date::ABBR_MONTHNAMES.drop(1))
  #=> ["January", "February", "March", "April", "May", "June",
  #    "July", "August", "September", "October", "November", "December",
  #    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  #    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] 
MON_REGEX = /\b#{Regexp.union(MON_NAMES)}\b(?!\A)/
  # => /\b(?-mix:January|February|...|December|Jan|Feb|...|Dec)\b(?!\A)/ 
MONTH_STR_TO_NBR = MON_NAMES.each_with_index.map { |mon,i| [mon, " #{1 + (i%12)} "] }.to_h 
  #=> {"January"=>" 1 ", "February"=>" 2 ", ... , "December"=>" 12 ",
  #    "Jan"=>" 1 ", "Feb"=>" 2 ", ... , "Dec"=>" 12 "} 
DAY_REGEX = /\b#{Regexp.union(Date::DAYNAMES + Date::ABBR_DAYNAMES)}\b,?/
  #=> /\b(?-mix:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sun|Mon|Tue|Wed|Thu|Fri|Sat)\b,?/

def my_parse(date_str, locale = :US)
  a = date_str.gsub(MON_REGEX, MONTH_STR_TO_NBR).
               gsub(DAY_REGEX, '').
               gsub(/(?<!\p{Alpha})(?:st|rd|th|,)(?!\p{Alpha})/, '').
               gsub(/[-\/]/, ' ').
               strip.
               split
  return nil if a.size != 3 || a.any? { |s| s.match?(/\D/) }
  yr_idx = a.index { |s| s.size == 4 }
  return nil if yr_idx.nil? || yr_idx == 1
  yr = a.delete_at(yr_idx)
  return nil unless a.all? { |s| [1,2].include? s.size }
  if yr_idx == 0
    mon, day = a
  else
    mon, day = locale == :US ? a : a.reverse
  end
  begin
    Date.strptime("%s %s %s" % [mon, day, yr], '%m %d %Y')
  rescue ArgumentError
    nil
  end
end      

my_parse("Tue, 12th January 2019")      #=> #<Date: 2019-01-12 (...)> 
my_parse("Tue, 12th January 2019", :UK) #=> #<Date: 2019-12-01 (...)> 
my_parse("12/4/2019", :US)              #=> #<Date: 2019-04-12 (...)>
my_parse("12/4/2019", :UK)              #=> #<Date: 2019-12-04 (...)>
my_parse("Jan 12, 2019")                #=> #<Date: 2019-12-01 (...)>
my_parse("2019 Jan 23rd")               #=> #<Date: 2019-01-23 (...)> 
my_parse("Jan 2019 4")                  #=> nil 
my_parse("1/2019/4")                    #=> nil 
my_parse("1/2019/4")                    #=> nil    
my_parse("Jen 12, 2019")                #=> nil 
my_parse("3 Jan 12, 2019")              #=> nil 

我鼓励读者找出我没有提到的其他假设。当然可以根据需要进行修改。可以很容易地进行一项更改,就是确认星期几(如果存在)对于给定日期是正确的。