Qbasicnews.com
December 10, 2019, 07:30:55 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: Back to Qbasicnews.com | QB Online Help | FAQ | Chat | All Basic Code | QB Knowledge Base
 
   Home   Help Search Login Register  
Pages: 1 2 3 [4]
  Print  
Author Topic: Write a bulletproof date validation routine.  (Read 36105 times)
Moneo
Na_th_an
*****
Posts: 1971


« Reply #45 on: July 24, 2006, 11:28:48 PM »

Wow, almost a year and half has gone by and I never posted my own solution to this challenge.

This is very old code that I've been using for years. Try it, you'll' like it.
Code:

DEFINT A-Z

DECLARE FUNCTION   NumStrict    (Z$)
DECLARE FUNCTION   IsLeapYear%  (Z)

rem Setup days-per-month table.
DIM ZMO(1 TO 12)
DATA 31,28,31,30,31,30,31,31,30,31,30,31
FOR ZMM=1 TO 12:READ ZMO(ZMM):NEXT ZMM

REM ***********************************************************************

input "Enter date to be validated as YYYYMMDD ",z$
gosub date.check
if date.ok=0 then print "Invalid Date" else print "Date ok"
SYSTEM

REM ****************  DATE.CHECK SUBROUTINE  **************************
REM *
REM *** VALIDATE A DATE IN YYYYMMDD FORMAT.
REM *
REM *  INPUT: Z$       = Given date in format YYYYMMDD.
REM *
REM * OUTPUT: DATE.OK = -1 if input date is VALID.   (true)
REM *                    0 if input date is INVALID. (false)                  
REM *
DATE.CHECK:
  DATE.OK = 0                          'preset to false
  IF LEN(Z$)<>8 THEN RETURN
  IF NOT NUMSTRICT(Z$) THEN RETURN
  ZDD=VAL(RIGHT$(Z$,2))                'Set day              
  ZMM=VAL(MID$(Z$,5,2))                'Set month.
  ZYY=VAL(LEFT$(Z$,4))                 'Set year.
  IF ZMM<1 OR ZMM>12 OR ZDD<1 OR ZDD>31 THEN RETURN
  IF ZMO(ZMM)+1*(-(ZMM=2 AND ISLEAPYEAR(ZYY))) < ZDD THEN RETURN
  '      If expression (month=2 and is leapyear) is TRUE which is -1, then
  '      taking the negative of this issues a plus 1. Conversely, FALSE    
  '      always gives a zero. Multiplying the +1 by this result of 1 or 0
  '      will either add 1 or not to the number of days in the month.
  '      The logic wants to add 1 only when it is February and leap year.
  DATE.OK = -1        '-1=valid (true)
RETURN    

END

' ====================== ISLEAPYEAR ==========================
'         Determines if a year is a leap year or not.
' ============================================================
'
FUNCTION IsLeapYear (Z) STATIC
   ' If the year is evenly divisible by 4 and not divisible
   ' by 100, or if the year is evenly divisible by 400, then
   ' it's a leap year:
   IsLeapYear = (Z MOD 4 = 0 AND Z MOD 100 <> 0) OR (Z MOD 400 = 0)
END FUNCTION

' =================================================================

FUNCTION NumStrict (Z$)
  '
  ' *** CHECK FOR STRICTLY NUMERIC (NO NULL, NO NEGATIVE, NO DECIMAL)
  '
  NumStrict=0         'Init to False

  IF Z$="" THEN EXIT FUNCTION

  FOR X = 1 TO LEN(Z$)
      A=ASC(MID$(Z$,X,1))
      IF A<48 OR A>57 THEN EXIT FUNCTION
  NEXT X

  NumStrict = -1          'True

END FUNCTION
Logged
Neo
Na_th_an
*****
Posts: 2150



« Reply #46 on: July 26, 2006, 08:06:13 AM »

Looks good... a year later.

I'd dearly suggest though to reform it in the more "modern" style of coding Smiley

Also, hi! *hides into lonely darkness again*
Logged
yetifoot
Ancient Guru
****
Posts: 575



« Reply #47 on: July 27, 2006, 12:17:08 AM »

Sorry for being off topic, but I wonder if you are able to check your email Moneo?  I sent you some mail about a topic I thought you may be interested in.
Logged

EVEN MEN OF STEEL RUST.
Moneo
Na_th_an
*****
Posts: 1971


« Reply #48 on: July 27, 2006, 01:51:15 AM »

Quote from: "Neo"
Looks good... a year later.

I'd dearly suggest though to reform it in the more "modern" style of coding Smiley

Ok, give me a rundown on what is considered modern style code.

Hope you don't ask for colors 'cause I don't have that kind of editor, nor do I use any IDE.

Hi, back at you,
Moneo
Logged
Moneo
Na_th_an
*****
Posts: 1971


« Reply #49 on: July 27, 2006, 01:53:50 AM »

Quote from: "yetifoot"
Sorry for being off topic, but I wonder if you are able to check your email Moneo?  I sent you some mail about a topic I thought you may be interested in.

Sorry, got my email on another machine. Will check it tomorrow, and get back to you.

*****
Logged
yetifoot
Ancient Guru
****
Posts: 575



« Reply #50 on: July 27, 2006, 02:52:31 AM »

Moneo: The date routine has one minor flaw, that other posters in the thread checked for.

I would check for Len(Z$) <> 8 first, because this would indicate a bad date.

One entry that passes your check is 200002228 even though it is 9 chars.

Otherwise, great job.

I would probably do this for the day and month check, it appears more logical to me, it took me a while to figure yours out.

Code:
IF ZMM < 1 OR ZMM > 12 THEN RETURN
IF ZDD < 1 OR ZDD > (ZMO(ZMM) - ((ZMM = 2) AND ISLEAPYEAR(ZYY))) THEN RETURN
Logged

EVEN MEN OF STEEL RUST.
Moneo
Na_th_an
*****
Posts: 1971


« Reply #51 on: July 28, 2006, 12:07:18 AM »

Quote from: "yetifoot"
Moneo: The date routine has one minor flaw, that other posters in the thread checked for.

I would check for Len(Z$) <> 8 first, because this would indicate a bad date.

One entry that passes your check is 200002228 even though it is 9 chars.

Otherwise, great job.

I would probably do this for the day and month check, it appears more logical to me, it took me a while to figure yours out.

Code:
IF ZMM < 1 OR ZMM > 12 THEN RETURN
IF ZDD < 1 OR ZDD > (ZMO(ZMM) - ((ZMM = 2) AND ISLEAPYEAR(ZYY))) THEN RETURN

You're very observant, Yetifoot.

I fixed the code above to add the check for len(Z$)<>8.
Sorry, the program of mine, that I lifted this code from, had already checked this, and my poor testing of this new program didn't reveal the error. Thanks.

Yeah, the code regarding February and leapyear is too hairy. That's why it needed 5 lines of comments to explain. You're right. It's unnecessarily complex. I thought it was cute at the time, back in 1994, when I was enamored with bitwise logic. I won't bother to change it now, because it does work. But feel free to make a change to simplify it.

Regards and thanks..... Moneo
Logged
yetifoot
Ancient Guru
****
Posts: 575



« Reply #52 on: July 28, 2006, 03:52:41 PM »

I prefered your method of hard coding the number of days per month, whilst i enjoyed the other posts methods of determing the number of days in a month (complicated, but interesting), I agree with the idea of keeping it fairly understandable when possible.

I like the IsLeapYear function also, I guess at first i would have been tempted to write a multiline IF..THEN based code, but it really is not necessary as shown in yours.  Earlier in the thread you said you felt your IsLeapYear was overcomplicated, but i disagree, i felt it was still very understandable.
Logged

EVEN MEN OF STEEL RUST.
Moneo
Na_th_an
*****
Posts: 1971


« Reply #53 on: July 28, 2006, 08:11:34 PM »

Quote from: "yetifoot"
I prefered your method of hard coding the number of days per month, whilst i enjoyed the other posts methods of determing the number of days in a month (complicated, but interesting), I agree with the idea of keeping it fairly understandable when possible.

I like the IsLeapYear function also, I guess at first i would have been tempted to write a multiline IF..THEN based code, but it really is not necessary as shown in yours.  Earlier in the thread you said you felt your IsLeapYear was overcomplicated, but i disagree, i felt it was still very understandable.

Yeti, thanks for you constructive comments. I think we are now pretty much in agreement on all the coding issues of this task.

I hope we have impressed on others the need of having such a date validation routine tested and ready to be used in any program which receives a date as input from the user or even as input from another file.
Most programs don't contain good date validation logic simply because the programmer doesn't want to take the time to do it and test it while writing the main program. Often, the same happen with other validations like numeric amounts, numerics with decimals, validating codes, zipcodes, phone numbers, name and address fields, etc. These can be a pain in the butt if you don't have the logic ready-made, so they usually go unchecked --- "garbage in, garbage out."

Regards..... Moneo
Logged
Pages: 1 2 3 [4]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!