Bir dizem var: "31-02-2010"
ve bunun geçerli bir tarih olup olmadığını kontrol etmek istiyorum. Bunu yapmanın en iyi yolu ne?
Dize geçerli bir tarihse true, değilse false döndüren bir yönteme ihtiyacım var.
Bir dizem var: "31-02-2010"
ve bunun geçerli bir tarih olup olmadığını kontrol etmek istiyorum. Bunu yapmanın en iyi yolu ne?
Dize geçerli bir tarihse true, değilse false döndüren bir yönteme ihtiyacım var.
Yanıtlar:
require 'date'
begin
Date.parse("31-02-2010")
rescue ArgumentError
# handle invalid date
end
İşte basit bir tek astar:
DateTime.parse date rescue nil
Arayan kişiyi sıfır olup olmadığını kontrol etmeye zorlarken, muhtemelen gerçek hayattaki her durumda tam olarak bunu yapmanızı tavsiye etmem. özellikle biçimlendirirken. Varsayılan bir tarih döndürürseniz | hata daha kolay olabilir.
Date.strptime(date, '%d/%m/%Y') rescue nil
rescue
kullanımı tavsiye edilmez.
d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i
is_valid?
? 1.8, 2.0 ve 2.1 denendi. Hiçbirinde buna sahip değil gibi görünüyor. valid_date?
Yine de hepsi var gibi görünüyor .
Ayrıştırma tarihleri, özellikle ABD veya Avrupa'da kullanılan kısa tarihler gibi AA / GG / YYYY veya GG / AA / YYYY biçiminde olduklarında bazı sorunlara rastlayabilir.
Date#parse
hangisinin kullanılacağını bulmaya çalışır, ancak yıl boyunca bir ay içinde, formatlar arasındaki belirsizliğin ayrıştırma sorunlarına neden olabileceği birçok gün vardır.
Kullanıcının LOCALE'sinin ne olduğunu bulmanızı öneririm, o zaman buna dayanarak, akıllıca nasıl ayrıştırılacağını bileceksiniz. Date.strptime
. Bir kullanıcının nerede olduğunu bulmanın en iyi yolu, kayıt sırasında onlara sormak ve ardından bunu değiştirmek için tercihlerinde bir ayar sağlamaktır. Bazı zekice sezgisel yöntemlerle bulabileceğinizi ve kullanıcıyı bu bilgiler için rahatsız etmeyeceğinizi varsayarsak, başarısızlığa meyillidir, bu yüzden sadece sorun.
Bu, kullanan bir testtir Date.parse
. ABD'deyim:
>> Date.parse('01/31/2001')
ArgumentError: invalid date
>> Date.parse('31/01/2001') #=> #<Date: 2001-01-31 (4903881/2,0,2299161)>
İlki ABD için doğru formattı: aa / gg / yyyy, ancak Tarih bundan hoşlanmadı. İkincisi Avrupa için doğruydu, ancak müşterileriniz ağırlıklı olarak ABD merkezli ise, çok sayıda kötü ayrıştırılmış tarih alırsınız.
Ruby'ler Date.strptime
şu şekilde kullanılır:
>> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>
01/01/2014
ay hangisi ve hangi gün? ABD'de ay ilk, dünyanın geri kalanı ikinci ay olacak.
Date.valid_date? *date_string.split('-').reverse.map(&:to_i)
require "date"
Önce yapmanız gerektiğini veya "tanımsız yöntem" alacağınızı unutmayın.
Date.valid_date? *Array.new(3).zip(date_string.split('-')).transpose.last.reverse.map(&:to_i)
Uzatmak istiyorum Date
Sınıfı .
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'
Tarihi doğrulamanın başka bir yolu:
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)
Tüm tarihler için normal ifadeyi deneyin:
/(\d{1,2}[-\/]\d{1,2}[-\/]\d{4})|(\d{4}[-\/]\d{1,2}[-\/]\d{1,2})/.match("31-02-2010")
Yalnızca başında sıfır, son yıl ve kısa çizgiler içeren biçiminiz için:
/(\d{2}-\d{2}-\d{4})/.match("31-02-2010")
[- /], - veya / anlamına gelir, eğik çizgiden kaçınılmalıdır. Bunu http://gskinner.com/RegExr/ adresinde test edebilirsiniz.
aşağıdaki satırları ekleyin, ilk normal ifadeyi kullanırsanız, birinci ve sonuncu / (bunlar ruby kodunda kullanım içindir) olmadan vurgulanacaktır.
2004-02-01
2004/02/01
01-02-2004
1-2-2004
2004-2-1
32-13-2010
hangisinin yanlış olduğu gibi tarihlere izin verir .
'00/00/0000'
ve '99-99/9999'
olası adaylardır.
Beklediğiniz tarih biçimini belirtirseniz, bir tarihin doğruluğunu doğrulamak daha kolaydır. Bununla birlikte, o zaman bile, Ruby benim kullanım durumum için biraz fazla toleranslı:
Date.parse("Tue, 2017-01-17", "%a, %Y-%m-%d") # works
Date.parse("Wed, 2017-01-17", "%a, %Y-%m-%d") # works - !?
Açıkçası, bu dizelerden en az biri yanlış hafta içi günü belirtir, ancak Ruby bunu mutlu bir şekilde görmezden gelir.
İşte olmayan bir yöntem; buna göre date.strftime(format)
ayrıştırdığı aynı girdi dizgesine dönüştüğünü doğrular .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
sıfır dolgulu. Farklı bir şey istiyorsanız, bkz. Ruby-doc.org/stdlib-2.4.0/libdoc/date/rdoc/…
Daha sonra birinin işine yarayabileceği için bunu yayınlamak. Bunu yapmanın "iyi" bir yolu olup olmadığına dair hiçbir ipucu yok, ama benim için işe yarıyor ve uzatılabilir.
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 sınıfı için bu eklenti, 4. satırdaki sınırlayıcı listenizi ve ardından 5. satırdaki geçerli biçimler listenizi belirlemenizi sağlar. Roket bilimi değildir, ancak genişletmeyi gerçekten kolaylaştırır ve aşağıdaki gibi bir dizeyi basitçe kontrol etmenizi sağlar:
"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
Aşağıdakileri deneyebilirsiniz, bu basit yol:
"31-02-2010".try(:to_date)
Ancak istisnayı halletmeniz gerekiyor.
Date.parse bu örnekler için istisna oluşturmadı:
Date.parse("12!12*2012")
=> Thu, 12 Apr 2018
Date.parse("12!12&2012")
=> Thu, 12 Apr 2018
Bu çözümü tercih ediyorum:
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
Yöntem:
require 'date'
def is_date_valid?(d)
Date.valid_date? *"#{Date.strptime(d,"%m/%d/%Y")}".split('-').map(&:to_i) rescue nil
end
Kullanımı:
config[:dates].split(",").all? { |x| is_date_valid?(x)}
Config [: dates] = "12/10/2012, 05/09/1520" ise bu doğru veya yanlış döndürür