У меня есть строка: "31-02-2010"
и хочу проверить, действительно ли она действительная дата.
Каков наилучший способ сделать это?
Мне нужен метод, который возвращает true, если строка является допустимой датой и false, если это не так.
У меня есть строка: "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
Я, вероятно, не рекомендовал бы делать это в любой ситуации в реальной жизни, поскольку вы вынуждаете вызывающего абонента проверять нуль, например. особенно при форматировании. Если вы вернете ошибку даты по умолчанию, она может быть более дружественной.
Даты анализа могут запускаться в некоторые файлы, особенно когда они находятся в формате MM/DD/YYYY или DD/MM/YYYY, например короткие даты, используемые в США или Европе.
Date#parse
пытается выяснить, что использовать, но есть много дней в месяц в течение года, когда двусмысленность между форматами может вызвать проблемы с анализом.
Я бы порекомендовал узнать, что такое LOCALE пользователя, то на основе этого вы будете разумно разбираться с помощью Date.strptime
. Лучший способ найти, где находится пользователь, - спросить их во время регистрации, а затем предоставить настройку в своих настройках, чтобы изменить ее. Предполагая, что вы можете выкапывать его с помощью какой-то умной эвристики и не беспокоить пользователя этой информацией, склонны к провалу, поэтому просто спросите.
Это тест с использованием Date.parse
. Я в U.S.:
>> Date.parse('01/31/2001')
ArgumentError: invalid date
>> Date.parse('31/01/2001') #=> #<Date: 2001-01-31 (4903881/2,0,2299161)>
Первым был правильный формат для U.S.: 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'
Попробуйте регулярное выражение для всех дат:
/(\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/
добавьте следующие строки, все они будут выделены, если вы используете первое регулярное выражение, без первого и последнего/(они предназначены для использования в рубиновом коде).
2004-02-01
2004/02/01
01-02-2004
1-2-2004
2004-2-1
Другой способ подтверждения даты:
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. Не наука о ракетах, но делает ее очень простой в расширении и позволяет просто проверять строку как так:
"test".is_date?
"10-12-2010".is_date?
params[:some_field].is_date?
etc.
Проще проверить правильность даты, если вы укажете формат даты, который вы ожидаете. Однако даже в этом случае 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 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
Метод:
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)}
Это возвращает true или false, если config [: dates] = "12/10/2012,05/09/1520"