Programing

문자열이 유효한 날짜인지 확인하는 방법

crosscheck 2020. 8. 11. 07:54
반응형

문자열이 유효한 날짜인지 확인하는 방법


문자열 "31-02-2010"이 있으며 유효한 날짜인지 확인하고 싶습니다. 이를 수행하는 가장 좋은 방법은 무엇입니까?

문자열이 유효한 날짜이면 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

예를 들어 호출자가 nil을 확인하도록 강제하기 때문에 실제 생활의 모든 상황에서 정확하게 이것을 수행하는 것은 권장하지 않습니다. 특히 포맷 할 때. 기본 날짜 | 오류를 반환하면 더 친숙 할 수 있습니다.


파싱 ​​날짜는 특히 미국 또는 유럽에서 사용되는 짧은 날짜와 같이 MM / DD / YYYY 또는 DD / MM / YYYY 형식 인 경우 일부 문제가 발생할 수 있습니다.

Date#parse 어떤 것을 사용할지 알아 내려고하지만, 형식 간의 모호함으로 인해 구문 분석 문제가 발생할 수있는 1 년 내내 한 달에 여러 날이 있습니다.

사용자의 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)>

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_hash = Date._parse(date.to_s)
Date.valid_date?(date_hash[:year].to_i,
                 date_hash[:mon].to_i,
                 date_hash[:mday].to_i)

Try regex for all dates:

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

For only your format with leading zeroes, year last and dashes:

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

the [-/] means either - or /, the forward slash must be escaped. You can test this on http://gskinner.com/RegExr/

add the following lines, they will all be highlighted if you use the first regex, without the first and last / (they are for use in ruby code).

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

A stricter solution

It's easier to verify the correctness of a date if you specify the date format you expect. However, even then, Ruby is a bit too tolerant for my use case:

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

Clearly, at least one of these strings specifies the wrong weekday, but Ruby happily ignores that.

Here's a method that doesn't; it validates that date.strftime(format) converts back to the same input string that it parsed with Date.strptime according to 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

Posting this because it might be of use to someone later. No clue if this is a "good" way to do it or not, but it works for me and is extendible.

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

This add-on for String class lets you specify your list of delimiters in line 4 and then your list of valid formats in line 5. Not rocket science, but makes it really easy to extend and lets you simply check a string like so:

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

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

You can try the following, which is the simple way:

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

But you need to handle the exception.


Date.parse not raised exception for this examples:

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

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

I prefer this solution:

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

Method:

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

Usage:

config[:dates].split(",").all? { |x| is_date_valid?(x)}

This returns true or false if config[:dates] = "12/10/2012,05/09/1520"

참고URL : https://stackoverflow.com/questions/2955830/how-to-check-if-a-string-is-a-valid-date

반응형