স্ট্রিংটি বৈধ তারিখ কিনা তা কীভাবে পরীক্ষা করবেন


114

আমার একটি স্ট্রিং রয়েছে: "31-02-2010"এবং এটি বৈধ তারিখ কিনা তা পরীক্ষা করতে চাই। এটা করার সবচেয়ে ভালো উপায় কি?

আমার এমন একটি পদ্ধতি দরকার যা স্ট্রিংটির বৈধ তারিখ হলে সত্য হয় এবং তা না হলে মিথ্যা।


2
আপনার যাচাই করতে হবে এমন স্ট্রিংয়ের পরিবর্তে কেবল একটি ডেটটাইম ড্রপ ডাউন করবেন না কেন?
corroded

ক্লায়েন্টের প্রয়োজনীয়তা আমি ইতিমধ্যে এটি প্রস্তাব দিয়েছি কিন্তু এটি করতে পারি না :)
সলিল

একটি সাধারণ নিয়ম হিসাবে, আপনি কি কোনও অ্যাপ্লিকেশনের সামনের প্রান্তে ইনপুট বৈধতা দেওয়ার কথা বলছেন না?
Seanny123

এখানে আরও অনেক ভাল উত্তর - এটি এটি করতে হয়। stackoverflow.com/questions/597328/...
N13

3
আপনার ফ্রন্ট-এন্ড যত ভালই হোক না কেন, সর্বদা ব্যাকএন্ডে বৈধতা দিন, এটি বিশ্বাস করবেন না!
স্পার্ক করুন

উত্তর:


112
require 'date'
begin
   Date.parse("31-02-2010")
rescue ArgumentError
   # handle invalid date
end

27
এটি কোনও তারিখ শ্রেণীর বৈশিষ্ট্য নয়, এটি ব্যতিক্রম হ্যান্ডলিং।
পিয়ের-অলিভিয়ার থিবল্ট

3
তারিখ.পারস ('2012-08-13 == 00:00:00') # => সোমবার, 13 আগস্ট 2012
বব

13
একটি "ক্যাচ-ইট-অল" রেসকিউ ব্যবহার করে একটি অ্যান্টি-প্যাটার্ন হিসাবে বিবেচনা করা উচিত। এটি অন্যান্য ত্রুটিগুলি আড়াল করতে পারে যা আমরা প্রত্যাশা করি না এবং কোডটির ডিবাগিংকে অত্যন্ত কঠিন করে তোলে।
ইয়াগুয়ার

8
সুতরাং ... এটি যদি সত্যই কোনও বিরোধী ধাঁচের হয় তবে আপনি কীভাবে প্রশ্নের উত্তর দেবেন?
ম্যাথু ব্রাউন

11
দুঃখিত এটি একটি ভুল উত্তর। স্ট্রিংটি বৈধ তারিখ কিনা তা এটি যাচাই করে না, এটি কেবল তারিখের পরীক্ষা করে থাকে p পার্স স্ট্রিংটিকে পার্স করতে পারে। তারিখ.পার্স তারিখের সময় খুব ক্ষমাযোগ্য মনে হয়, যেমন এটি 2012-09-09 তারিখ হিসাবে "FOOBAR_09_2010" কে পার্স করবে।
n13

54

এখানে একটি সাধারণ লাইনার:

DateTime.parse date rescue nil

আপনি সম্ভবত আহ্বানকারীকে বাস্তব জীবনে প্রতিটি পরিস্থিতিতে ঠিক এটি করার পরামর্শ দেবেন না, যেমন আপনি কলারকে শূন্যতার জন্য পরীক্ষা করতে বাধ্য করেন, যেমন। বিশেষত যখন ফর্ম্যাট করা হয়। আপনি যদি কোনও ডিফল্ট তারিখ ফেরত দেন | ত্রুটিটি বন্ধুত্বপূর্ণ হতে পারে।


8
ডেটটাইম.পারস "123" রেসকিউ শিল। এটি আসল তারিখটি
ফেরায়

3
Date.strptime(date, '%d/%m/%Y') rescue nil
Bonafernando

1
ইনলাইন ব্যবহার rescueনিরুৎসাহিত করা হয়।
স্মোকথ

52
d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i

এটি একটি এক্সএক্স-এক্সএক্স-
ওয়াইওয়াই

আপনি যদি কঠোর একক বিন্যাসের তারিখের স্ট্রিং বিকল্পটি প্রয়োগ করতে চান, তবে এটি ব্যতিক্রমগুলি এড়িয়ে যায় এবং নির্বিচারবাদী হওয়ায় এটি সর্বোত্তম বিকল্প। Date.valid_date? রুবি 2. জন্য অন্তত ব্যবহারের পদ্ধতি ruby-doc.org/stdlib-2.0.0/libdoc/date/rdoc/...
অ্যাশলে Raiteri

4
রুবি কোন সংস্করণ সমর্থন করে is_valid?? 1.8, 2.0 এবং 2.1 চেষ্টা করেছেন। তাদের কারও কাছেই এটি আছে বলে মনে হয় না। valid_date?যদিও সব আছে বলে মনে হচ্ছে ।
হেনরিক এন

29

পার্সিংয়ের তারিখগুলি কিছু গোচাতে চলে যেতে পারে, বিশেষত যখন তারা এমএম / ডিডি / ওয়াইওয়াইওয়াই বা ডিডি / এমএম / ওয়াইওয়াই ফর্ম্যাটে থাকে যেমন মার্কিন যুক্তরাষ্ট্র বা ইউরোপে সংক্ষিপ্ত তারিখগুলি ব্যবহৃত হয়।

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)>

প্রথমটি ছিল মার্কিন যুক্তরাষ্ট্রে সঠিক ফর্ম্যাট: মিমি / ডিডি / ইয়ে, কিন্তু তারিখটি এটি পছন্দ করে না। দ্বিতীয়টি ইউরোপের পক্ষে সঠিক ছিল তবে আপনার গ্রাহকরা যদি মূলত মার্কিন-ভিত্তিক হন তবে আপনি প্রচুর খারাপভাবে পার্সড তারিখ পেয়ে যাবেন।

রুবি এর Date.strptimeমতো ব্যবহৃত হয়:

>> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>

আপনার লোকাল বন্ধ আছে। আমি এটি পেয়েছি >> তারিখ.পারস ('01 / 31/2001 ') => বুধ, 31 জানুয়ারী 2001 >>?> তারিখ পার্স ('31 / 01/2001') যুক্তি
ত্রুটি

আমি এখানে খাঁটি হয়ে যাচ্ছি কিনা তা নিশ্চিত নন, তবে এটি কেবলমাত্র একটি তারিখকে কীভাবে পার্স করা যায় তা ব্যাখ্যা করতে পারে, এটি কীভাবে বৈধ করা যায় না। গৃহীত উত্তরটি আর্গুমেন্টআরর ব্যতিক্রম ব্যবহার করে, তবে এটি একটি মন্তব্যে উল্লিখিত কারণগুলির জন্য, এটি একটি ভাল ধারণা বলে মনে হয় না।
সিসয়েড

একটি পরিচিত পরিস্থিতি রয়েছে যেখানে আপনি কোনও তারিখ বৈধ করতে পারবেন না। এখানেই দিন এবং মাসের মানগুলি অস্পষ্ট, এবং আপনাকে আগত তারিখের স্ট্রিমের ফর্ম্যাটটি জানতে হবে। এবং, এটিই উত্তরটি বলছে। যদি মনে হয় 01/01/2014, কোন মাসটি এবং কোনটি দিন? মার্কিন যুক্তরাষ্ট্রে প্রথম হবে, বাকি বিশ্বের এটি দ্বিতীয় হবে।
টিন ম্যান

অস্পষ্টতা যা আপনাকে তারিখটি বৈধকরণ থেকে বিরত রাখে তা কেবলমাত্র সেই পরিমাণে করে যে এটি আপনাকে তারিখটি বিশ্লেষণ করা থেকেও বাধা দেয়, তবে আপনি পরিচিত তথ্যের সাথে এটি বিশ্লেষণে একটি ভাল চেষ্টা করেছেন। আপনার যা যা সম্ভব আমরা যথাসম্ভব যথাযথভাবে যাচাই করার চেষ্টা করতে হবে এমন কিছু ব্যবহার করা ভাল। ডেট.পার্স এবং ডেট.স্ট্রিপটাইম যে ব্যতিক্রমগুলি ব্যবহার করে তা ব্যবহার না করে আপনি কীভাবে এটি করবেন তা ভাবতে পারেন?
সিজয়েড

"মিমি / ডিডি / ইয়েই" বা "ডিডি / মিমি / ইয়ে" ফর্ম্যাটে তারিখের পার্সিংয়ের তারিখের ফর্ম্যাটটির পূর্বসূচী প্রয়োজন । এটি ব্যতীত আমরা কোন উত্স / ব্যবহারকারীর কাছ থেকে নমুনা না নিলে তা কোনটি নির্ধারণ করতে পারি না, তারপরে উভয় ফর্ম ব্যবহার করে বিশ্লেষণ করুন এবং তারপরে কোন ফর্মটি সবচেয়ে ব্যতিক্রম উত্পন্ন করেছে এবং অন্যটি ব্যবহার করে তা দেখুন। একাধিক উত্স থেকে তারিখগুলি পার্স করার সময় এটি ভেঙে যায়, বিশেষত যখন তারা বিশ্বব্যাপী হয় বা তাদের হাতে প্রবেশ করা হয়। তারিখগুলি মোকাবেলা করার একমাত্র সঠিক উপায় হ'ল প্রবেশের অনুমতি না দেওয়া, ব্যবহারকারীদের তারিখ-বাছাইকারীদের ব্যবহার করতে বাধ্য করা, বা কেবলমাত্র আইএসও তারিখের বিন্যাসগুলিকে মঞ্জুরি দেওয়া নয়।
টিন ম্যান

26

Date.valid_date? *date_string.split('-').reverse.map(&:to_i)


দুর্দান্ত, ধন্যবাদ এটি কমপক্ষে 1.8, 2.0 এবং 2.1 এ উপলব্ধ বলে মনে হচ্ছে। মনে রাখবেন যে আপনাকে require "date"প্রথমে প্রয়োজন বা আপনি "অপরিজ্ঞাত পদ্ধতি" পেয়ে যাবেন।
হেনরিক এন

2
এই পদ্ধতিটি মিথ্যা প্রত্যাবর্তনের পরিবর্তে একটি ব্যতিক্রম 'আর্গুমেন্টইরির: আর্গুমেন্টের ভুল সংখ্যা' বাড়াতে পারে। উদাহরণস্বরূপ যদি আপনার স্ট্রিংয়ে ড্যাশগুলির পরিবর্তে স্ল্যাশ রয়েছে
ভিনসেন্টপ

2
খারাপ ফরম্যাটেড তারিখটি পরিচালনা করার জন্য আমরা এর মতো কিছু করতে পারি:Date.valid_date? *Array.new(3).zip(date_string.split('-')).transpose.last.reverse.map(&:to_i)
ভিনসেন্টপ

9

আমি 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'


3

সমস্ত তারিখের জন্য রেজেক্স চেষ্টা করুন:

/(\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

2
এই নিয়মিত প্রকাশগুলি কেবল কোনও তারিখের শব্দার্থবিজ্ঞানের যত্ন না করে কিছু স্থির ফর্ম্যাটগুলির সাথে মেলে। আপনার ম্যাচার ম্যাথগুলি 32-13-2010ভুল হিসাবে তারিখের অনুমতি দেয় ।
ইয়াগুয়ার

2
যদি কোনও নির্বিচার স্ট্রিং একটি তারিখ হিসাবে পার্স করা যায় তবে আপনি যদি মোটামুটি অনুমান চান তবে যথেষ্ট ভাল।
নীল গুডম্যান

যেখানে "মোটামুটি অনুমান" অর্থ মূল্যবান পছন্দগুলি '00/00/0000'এবং '99-99/9999'সম্ভাব্য প্রার্থীরা।
টিন ম্যান

1
কাস্টম রেজেক্স একটি খারাপ আইডিএর একটি উজ্জ্বল উদাহরণ!
টম লর্ড

3

একটি কঠোর সমাধান

আপনি যে তারিখের ফর্ম্যাটটি প্রত্যাশা করেছেন তা নির্দিষ্ট করে যদি তারিখের সঠিকতা যাচাই করা সহজ easier তবে তারপরেও রুবি আমার ব্যবহারের ক্ষেত্রে কিছুটা সহনশীল:

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

ঠিক এটাই আমি খুঁজছিলাম। ধন্যবাদ!
লুকাস ক্যাটন

এটি "2019-1-1" এর মতো মামলার ক্ষেত্রে ব্যর্থ হয় যা একটি বৈধ তারিখ তবে স্ট্রফটাইম এটিকে 2019-01-01 করে তোলে
saGii

@ এসজিজি যা নির্দিষ্ট করা ফর্ম্যাটটি ফিট করে না (iso8601 - দেখুন Date.today().iso8601); %mশূন্য প্যাডযুক্ত। আপনি যদি অন্যরকম কিছু চান তবে দেখুন রুবি
নাথান লং

2

এটি পোস্ট করা কারণ এটি পরে কারওর কাজে লাগতে পারে। এটি করার একটি "ভাল" উপায় যদি না হয় তবে কোনও চিহ্ন নেই, তবে এটি আমার পক্ষে কাজ করে এবং প্রসারিত is

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

স্ট্রিং ক্লাসের জন্য এই অ্যাড-অন আপনাকে আপনার লাইন 4-এ ডিলিমিটারগুলির তালিকা এবং তারপরে আপনার লাইনে 5 বৈধ ফর্ম্যাটগুলির তালিকা নির্দিষ্ট করতে দেয় রকেট বিজ্ঞান নয়, তবে এটি প্রসারিত করা সহজ করে তোলে এবং আপনাকে সহজভাবে স্ট্রিং পরীক্ষা করতে দেয়:

"test".is_date?
"10-12-2010".is_date?
params[:some_field].is_date?
etc.

0
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

0

আপনি নিম্নলিখিতটি চেষ্টা করতে পারেন, যা সহজ উপায়:

"31-02-2010".try(:to_date)

তবে আপনার ব্যতিক্রমটি পরিচালনা করা দরকার।


0

তারিখ.পারস এই উদাহরণগুলির জন্য উত্থাপিত ব্যতিক্রম নয়:

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

-1

পদ্ধতি:

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)}

এটি কনফিগার করলে সত্য বা মিথ্যা ফিরে আসে [: তারিখ] = "12/10 / 2012,05 / 09/1520"

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.