文字列"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
呼び出し側に強制的に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
どちらを使用するかを考えようとしますが、フォーマット間のあいまいさが解析の問題を引き起こす可能性がある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)>
1つ目は、米国向けの正しい形式であるmm / dd / yyyyでしたが、Dateはそれを好みませんでした。2番目はヨーロッパでは正解でしたが、顧客が主に米国を拠点としている場合は、多くの不適切に解析された日付が表示されます。
Ruby Date.strptime
は次のように使用されます。
>> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>
01/01/2014
、月と日はどちらですか。米国の月が最初で、残りの世界は2番目です。
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'
すべての日付に対して正規表現を試してください:
/(\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/でテストできます
次の行を追加します。最初と最後の/なしで最初の正規表現を使用すると、それらはすべて強調表示されます(これらはRubyコードで使用されます)。
2004-02-01
2004/02/01
01-02-2004
1-2-2004
2004-2-1
32-13-2010
は間違っているような日付を許可します。
'00/00/0000'
と'99-99/9999'
は、候補のような値であり、可能な候補を意味します。
期待する日付形式を指定すると、日付が正しいかどうかを確認しやすくなります。ただし、その場合でも、Rubyは私の使用例に対して少し寛容です。
Date.parse("Tue, 2017-01-17", "%a, %Y-%m-%d") # works
Date.parse("Wed, 2017-01-17", "%a, %Y-%m-%d") # works - !?
明らかに、これらの文字列の少なくとも1つは間違った曜日を指定していますが、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
後で誰かに役立つかもしれないので、これを投稿します。これが「良い」方法であるかどうかの手掛かりはありませんが、私にとっては機能し、拡張可能です。
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
この例では、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)}
config [:dates] = "12/10 / 2012,05 / 09/1520"の場合、これはtrueまたはfalseを返します