У мене є рядок: "31-02-2010"
і хочу перевірити, чи це дійсна дата чи ні. Який найкращий спосіб це зробити?
Мені потрібен метод, який повертає true, якщо рядок є дійсною датою, а false - якщо ні.
У мене є рядок: "31-02-2010"
і хочу перевірити, чи це дійсна дата чи ні. Який найкращий спосіб це зробити?
Мені потрібен метод, який повертає true, якщо рядок є дійсною датою, а false - якщо ні.
Відповіді:
require 'date'
begin
Date.parse("31-02-2010")
rescue ArgumentError
# handle invalid date
end
Ось простий один вкладиш:
DateTime.parse date rescue nil
Я, напевно, не рекомендував би робити це саме в будь-якій ситуації реального життя, оскільки ви змушуєте абонента перевірити наявність нуля, наприклад. особливо при форматуванні. Якщо ви повернете дату за замовчуванням | помилка, це може бути дружнішим.
Date.strptime(date, '%d/%m/%Y') rescue nil
rescue
не рекомендується.
d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i
is_valid?
? Пробували 1,8, 2,0 та 2,1. Ніхто з них, схоже, не має цього. valid_date?
Однак, схоже , все є.
Дати розбору можуть стикатися з деякими готчами, особливо коли вони є у форматі 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's Date.strptime
використовується як:
>> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>
01/01/2014
, який місяць і який день? У США місяць був би першим, інший світ - другим.
Date.valid_date? *date_string.split('-').reverse.map(&:to_i)
require "date"
спершу або ви отримаєте "не визначений метод".
Date.valid_date? *Array.new(3).zip(date_string.split('-')).transpose.last.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)
Спробуйте регулярно встановити всі дати:
/(\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
32-13-2010
неправильні.
'00/00/0000'
і '99-99/9999'
можливі кандидати.
Простіше перевірити правильність дати, якщо ви вкажете очікуваний формат дати. Однак навіть тоді Рубі трохи занадто толерантний до мого використання:
Date.parse("Tue, 2017-01-17", "%a, %Y-%m-%d") # works
Date.parse("Wed, 2017-01-17", "%a, %Y-%m-%d") # works - !?
Зрозуміло, що принаймні один із цих рядків вказує неправильний будній день, але Рубі це радісно ігнорує.
Ось метод, який ні; він перевіряє, що 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
Date.today().iso8601
); %m
нульова підкладка. Якщо ви хочете чогось іншого, дивіться ruby-doc.org/stdlib-2.4.0/libdoc/date/rdoc/…
Опублікуйте це, оскільки пізніше це може бути корисним комусь. Немає поняття, чи це "хороший" спосіб зробити це чи ні, але це працює для мене і є розтяжним.
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.
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
Ви можете спробувати наступне, що є простим способом:
"31-02-2010".try(:to_date)
Але вам потрібно обробити виняток.
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
Спосіб:
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 [: дати] = "12/10 / 2012,05 / 09/1520"