Reputation: 57
I want to make sure that the only input from user is 8 numbers ( input will be by default integer ).
My goal is to make sure that user is inputting date in format: yyyymmdd .
If he won't input this format I want to use loop to make input once again until he will put correct format ( yyyymmdd ).
My current loop does not validate the date, it passes every input.
txt=gets
re1='((?:(?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3}))(?:[0]?[1-9]|[1][012])(?:(?:[0-2]?\\d{1})|(?:[3][01]{1})))(?![\\d])' # YYYYMMDD 1
re=(re1)
m=Regexp.new(re,Regexp::IGNORECASE);
while m.match(txt)
txt=gets
end
Upvotes: 1
Views: 1825
Reputation: 103844
Try something along these lines:
require 'date'
d=nil
loop do
puts 'Enter date YYYYMMDD'
st = gets.chomp
if st.match('^(\d\d\d\d)(\d\d)(\d\d)$')
begin
d=Date.strptime("#{$1}/#{$2}/#{$3}", '%Y/%m/%d')
break
rescue ArgumentError
puts 'BAD DATE!'
end
end
end
puts d
But personally, I would change the regex so the user can enter a date line these:
2014/2/2
2015 12 25
1999-2-02
The regex for that is:
^\D*(\d\d\d\d)\D+(\d\d?)\D+(\d\d?)\D*$
Then a delimiter is required between that elements of the date. Any non-digit will do.
Updated code:
require 'date'
d=nil
loop do
puts 'Enter date YYYY-MM-DD'
st = gets.chomp
if st.match('^\D*(\d\d\d\d)\D+(\d\d?)\D+(\d\d?)\D*$')
begin
d=Date.strptime("#{$1}/#{$2}/#{$3}", '%Y/%m/%d')
break
rescue ArgumentError
puts 'BAD DATE!'
end
end
end
puts d
Upvotes: 1
Reputation: 19221
Here is a usable Regexp:
regexp = /([0-9]+{4})((0[1-9]+)|(1[0-2]+))(([0-2]+[0-9]+)|(3[0-1]+))/
m = regexp.match '19990531'
m[1] #=> 1999, year
m[2] #=> 05, month
m[5] #=> 31, day
I would probably accept the solution suggested by @alfasin, it make sense and allows for different formats...
...BUT, you should be aware that different locales enter the date in different ways and that using the Date.parse
method might produce unexpected results. for instance, 1.2 is February 1st in the EU, while it is January 2nd in the USA...
Upvotes: 0