Date & time validation

N

Ne Scripter

Hi all,

I am looking for an easy way to validate date and time values in a
script I have written.

The script takes values from a large file containing various data sets,
some dates and some times. I need to validate these dates and time
values once I have loaded them into a variable and I was thinking of
doing this through an a date check and time check object for example:

date1 = field[2]
date1 = dateCheck(date1) if date1 != ""

date2 = field[23]
date2 = dateCheck(date2) if date2 != ""

time = field[24]
time = timeCheck(time) if time != ""

def dateCheck(dateData)
I need some code to check what ever is in this string and check for a
valid date of yyyy/mm/dd. The data being checked can be anything, so
I need to know does it match the date format of yyyy/mm/dd, if so return
true otherwise return an empty string
end


def timeCheck(timeData)
similar idea with the time I need to check the data is hh:mm:ss
otherwise return an empty string.
end


Any ideas on how to do this? I was looking a the docs for date and I am
struggling to make head way at this stage.

Thanks in advance!
 
R

Robert Klemme

2009/9/1 Ne Scripter said:
Hi all,

I am looking for an easy way to validate date and time values in a
script I have written.

The script takes values from a large file containing various data sets,
some dates and some times. I need to validate these dates and time
values once I have loaded them into a variable and I was thinking of
doing this through an a date check and time check object for example:

date1 =3D field[2]
date1 =3D dateCheck(date1) if date1 !=3D ""

date2 =3D field[23]
date2 =3D dateCheck(date2) if date2 !=3D ""

time =3D field[24]
time =3D timeCheck(time) if time !=3D ""

def dateCheck(dateData)
=A0I need some code to check what ever is in this string and check for a
valid =A0 =A0date of yyyy/mm/dd. The data being checked can be anything, = so
I need to know does it match the date format of yyyy/mm/dd, if so return
true otherwise return an empty string
end


def timeCheck(timeData)
=A0similar idea with the time I need to check the data is hh:mm:ss
otherwise return an empty string.
end


Any ideas on how to do this? I was looking a the docs for date and I am
struggling to make head way at this stage.

Thanks in advance!

Just parse it into a Time instance:

15:32:29 ~$ irb19 -r time
Ruby version 1.9.1
irb(main):001:0> Time.parse '2009/01/02'
=3D> 2009-01-02 00:00:00 +0100
irb(main):002:0> Time.parse '2009/20/02'
ArgumentError: argument out of range
from /opt/lib/ruby19/1.9.1/time.rb:202:in `local'
from /opt/lib/ruby19/1.9.1/time.rb:202:in `make_time'
from /opt/lib/ruby19/1.9.1/time.rb:261:in `parse'
from (irb):2
from /opt/bin/irb19:12:in `<main>'
irb(main):003:0>

Cheers

robert


--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
N

Ne Scripter

Robert,

I understand what you are doing here and I have looked at using this
already however if I have a string 2009/09/01 12:22:36 it will be
returned as true because the date format is correct, the string above
will in fact be invalid because only a field consisting of yyyy/mm/dd is
valid.

Many thanks

Stuart

Robert said:
2009/9/1 Ne Scripter said:
date1 = field[2]
valid � �date of yyyy/mm/dd. The data being checked can be anything, so

Any ideas on how to do this? I was looking a the docs for date and I am
struggling to make head way at this stage.

Thanks in advance!

Just parse it into a Time instance:

15:32:29 ~$ irb19 -r time
Ruby version 1.9.1
irb(main):001:0> Time.parse '2009/01/02'
=> 2009-01-02 00:00:00 +0100
irb(main):002:0> Time.parse '2009/20/02'
ArgumentError: argument out of range
from /opt/lib/ruby19/1.9.1/time.rb:202:in `local'
from /opt/lib/ruby19/1.9.1/time.rb:202:in `make_time'
from /opt/lib/ruby19/1.9.1/time.rb:261:in `parse'
from (irb):2
from /opt/bin/irb19:12:in `<main>'
irb(main):003:0>

Cheers

robert
 
M

Max Williams

You could run it through a rough regex match first and then Date parse
it using strptime.

date = (string =~ /^\d{4}\/\d{2}\/\d{2}$/) &&
(Date.strptime(string,"%Y/%m/%d"))
 
B

Brian Candler

Max said:
date = (string =~ /^\d{4}\/\d{2}\/\d{2}$/) &&

Beware: use

date = (string =~ /\A\d{4}\/\d{2}\/\d{2}\z/) ...

or else malicious inputs may be able to bypass your validation. (They
might not be able to bypass Date.strptime in this particular instance,
but still you ought to validate correctly)
 
R

Robert Klemme

2009/9/1 Brian Candler said:
Beware: use

date = (string =~ /\A\d{4}\/\d{2}\/\d{2}\z/) ...

or else malicious inputs may be able to bypass your validation. (They
might not be able to bypass Date.strptime in this particular instance,
but still you ought to validate correctly)

Then you can do:

16:48:53 ~$ irb19 -r date
Ruby version 1.9.1
irb(main):001:0> %w{2009/10/11 2009/10/44}.each do |s|
irb(main):002:1* p s
irb(main):003:1> date = %r{\A(\d{4})/(\d{2})/(\d{2})\z} =~ s &&
Date.new($1.to_i, $2.to_i, $3.to_i)
irb(main):004:1> end
"2009/10/11"
"2009/10/44"
ArgumentError: invalid date
from /opt/lib/ruby19/1.9.1/date.rb:809:in `civil'
from (irb):6:in `block in irb_binding'
from (irb):4:in `each'
from (irb):4
from /opt/bin/irb19:12:in `<main>'
irb(main):005:0>

Cheers

robert
 
N

Ne Scripter

Thanks all for the responses. I am still hitting a bit of a block with
this, initially I want to check if a date matches this criteria, then if
not do some of the processes that have been suggested.

I need to say
if date = yyyy/mm/dd
puts date
else
validate date
end

How would I do this? Sorry for so many questions, I am struggling to get
my head around the date libraries

Many thanks
 
N

Ne Scripter

Just an update of where I am. This is what I have

if date =~ (/\d{4}\/\d{2}\/\d{2}/)
puts date
else
date = (Date.strptime(date, "%Y/%m/%d"))
end

This works to an extent but does not deal with a string which contains a
valid date but still invalid data like so

2009/09/07 12:12:12

This would be passed as valid when it is not only a string containing
yyyy/mm/dd.

Any ideas?

Thanks a lot
 
7

7stud --

Ne said:
Just an update of where I am. This is what I have

if date =~ (/\d{4}\/\d{2}\/\d{2}/)
puts date
else
date = (Date.strptime(date, "%Y/%m/%d"))
end

This works to an extent but does not deal with a string which contains a
valid date but still invalid data like so

2009/09/07 12:12:12

This would be passed as valid when it is not only a string containing
yyyy/mm/dd.

Any ideas?

Thanks a lot

Look at the regex's in all the following examples. How do they differ
from your regex?

..
 
G

G_ F_

Ne said:
Just an update of where I am. This is what I have

if date =~ (/\d{4}\/\d{2}\/\d{2}/)
puts date
else
date = (Date.strptime(date, "%Y/%m/%d"))
end

This works to an extent but does not deal with a string which contains a
valid date but still invalid data like so

2009/09/07 12:12:12

This would be passed as valid when it is not only a string containing
yyyy/mm/dd.

Ok, to summarize to see if I've got it right:

blah 2009/09/07 blah # <-- is what we want to accept
blah 2009/09/07 12:00:00 blah # <-- is what we want to reject

%r#\d{4}/\d{2}/\d{2}# matches a date but gives a false positive for
dates followed by time.

You could filter out lines that have date followed by time using
something like:

next if %r#\d{4}/\d{2}/\d{2}\s+\d{2}:\d{2}:\d{2}#

then capture any that make it past that test with a regular date regex.

Or, you can combine the test and capture in one regex pattern using
look-ahead...

%r#(\d{4}/\d{2}/\d{2})\s+(?!\d{2}:\d{2}:\d{2})# =~ 'blah 2009/01/01
blah' # => 5
%r#(\d{4}/\d{2}/\d{2})\s+(?!\d{2}:\d{2}:\d{2})# =~ 'blah 2009/01/01
12:00:00 blah' # => nil

The first line successfully matches "text date text".
The second line rejects "text date time text".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top