Saya punya string: "31-02-2010"
dan ingin memeriksa apakah itu tanggal yang valid atau tidak. Apa cara terbaik untuk melakukannya?
Saya membutuhkan metode yang mengembalikan nilai true jika string adalah tanggal yang valid dan salah jika tidak.
Saya punya string: "31-02-2010"
dan ingin memeriksa apakah itu tanggal yang valid atau tidak. Apa cara terbaik untuk melakukannya?
Saya membutuhkan metode yang mengembalikan nilai true jika string adalah tanggal yang valid dan salah jika tidak.
Jawaban:
require 'date'
begin
Date.parse("31-02-2010")
rescue ArgumentError
# handle invalid date
end
Berikut ini satu baris sederhana:
DateTime.parse date rescue nil
Saya mungkin tidak akan merekomendasikan melakukan hal ini persis dalam setiap situasi dalam kehidupan nyata karena Anda memaksa penelepon untuk memeriksa nihil, misalnya. terutama saat memformat. Jika Anda mengembalikan tanggal default | kesalahan itu mungkin lebih ramah.
Date.strptime(date, '%d/%m/%Y') rescue nil
rescue
tidak dianjurkan.
d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i
is_valid?
? Mencoba 1.8, 2.0 dan 2.1. Tak satu pun dari mereka tampaknya memiliki yang itu. Semua tampaknya begitu valid_date?
.
Tanggal parsing dapat mengalami beberapa gotcha, terutama jika dalam format MM / DD / YYYY atau DD / MM / YYYY, seperti tanggal pendek yang digunakan di AS atau Eropa.
Date#parse
mencoba untuk mencari tahu mana yang akan digunakan, tetapi ada banyak hari dalam sebulan sepanjang tahun ketika ambiguitas antar format dapat menyebabkan masalah penguraian.
Saya akan merekomendasikan mencari tahu apa itu LOCALE pengguna, kemudian, berdasarkan itu, Anda akan tahu cara parsing menggunakan secara cerdas Date.strptime
. Cara terbaik untuk menemukan di mana pengguna berada adalah dengan bertanya kepada mereka saat mendaftar, dan kemudian memberikan pengaturan dalam preferensi mereka untuk mengubahnya. Dengan asumsi Anda dapat menggalinya dengan beberapa heuristik pintar dan tidak mengganggu pengguna untuk informasi itu, rentan terhadap kegagalan jadi tanyakan saja.
Ini adalah tes menggunakan Date.parse
. Saya di AS:
>> Date.parse('01/31/2001')
ArgumentError: invalid date
>> Date.parse('31/01/2001') #=> #<Date: 2001-01-31 (4903881/2,0,2299161)>
Yang pertama adalah format yang benar untuk AS: bb / hh / tttt, tetapi Date tidak menyukainya. Yang kedua benar untuk Eropa, tetapi jika pelanggan Anda sebagian besar berbasis di AS, Anda akan mendapatkan banyak tanggal yang diuraikan dengan buruk.
Ruby Date.strptime
digunakan seperti:
>> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>
01/01/2014
, bulan apa dan hari apa? Di AS, bulan akan menjadi yang pertama, seluruh dunia akan menjadi yang kedua.
Date.valid_date? *date_string.split('-').reverse.map(&:to_i)
require "date"
terlebih dahulu atau Anda akan mendapatkan "metode tidak ditentukan".
Date.valid_date? *Array.new(3).zip(date_string.split('-')).transpose.last.reverse.map(&:to_i)
Saya ingin memperpanjang Date
kelas.
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'
Cara lain untuk memvalidasi tanggal:
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)
Coba regex untuk semua tanggal:
/(\d{1,2}[-\/]\d{1,2}[-\/]\d{4})|(\d{4}[-\/]\d{1,2}[-\/]\d{1,2})/.match("31-02-2010")
Hanya untuk format Anda dengan nol di depan, tahun terakhir dan tanda hubung:
/(\d{2}-\d{2}-\d{4})/.match("31-02-2010")
[- /] berarti - atau /, garis miring harus di-escape. Anda dapat mengujinya di http://gskinner.com/RegExr/
tambahkan baris berikut, semuanya akan disorot jika Anda menggunakan regex pertama, tanpa yang pertama dan terakhir / (untuk digunakan dalam kode ruby).
2004-02-01
2004/02/01
01-02-2004
1-2-2004
2004-2-1
32-13-2010
yang salah.
'00/00/0000'
dan '99-99/9999'
merupakan kandidat yang mungkin.
Lebih mudah untuk memverifikasi kebenaran tanggal jika Anda menentukan format tanggal yang Anda harapkan. Namun, meskipun demikian, Ruby agak terlalu toleran untuk kasus penggunaan saya:
Date.parse("Tue, 2017-01-17", "%a, %Y-%m-%d") # works
Date.parse("Wed, 2017-01-17", "%a, %Y-%m-%d") # works - !?
Jelasnya, setidaknya satu dari string ini menetapkan hari kerja yang salah, tetapi Ruby dengan senang hati mengabaikannya.
Berikut adalah metode yang tidak; itu memvalidasi yang date.strftime(format)
mengubah kembali ke string input yang sama yang diurai dengan Date.strptime
sesuai 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
empuk nol. Jika Anda menginginkan sesuatu yang berbeda, lihat ruby-doc.org/stdlib-2.4.0/libdoc/date/rdoc/…
Memposting ini karena mungkin berguna untuk seseorang nanti. Tidak ada petunjuk apakah ini cara yang "baik" untuk melakukannya atau tidak, tetapi ini berhasil untuk saya dan dapat diperpanjang.
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
Pengaya untuk kelas String ini memungkinkan Anda menentukan daftar pembatas di baris 4 dan kemudian daftar format yang valid di baris 5. Bukan ilmu roket, tetapi membuatnya sangat mudah untuk diperpanjang dan memungkinkan Anda mencentang string seperti ini:
"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
Anda dapat mencoba yang berikut ini, yang merupakan cara sederhana:
"31-02-2010".try(:to_date)
Tapi Anda perlu menangani pengecualian tersebut.
Date.parse tidak memunculkan pengecualian untuk contoh ini:
Date.parse("12!12*2012")
=> Thu, 12 Apr 2018
Date.parse("12!12&2012")
=> Thu, 12 Apr 2018
Saya lebih suka solusi ini:
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
Metode:
require 'date'
def is_date_valid?(d)
Date.valid_date? *"#{Date.strptime(d,"%m/%d/%Y")}".split('-').map(&:to_i) rescue nil
end
Pemakaian:
config[:dates].split(",").all? { |x| is_date_valid?(x)}
Ini mengembalikan benar atau salah jika config [: tanggal] = "12/10 / 2012,05 / 09/1520"