# Qbasicnews.com

Full Version: Write a bulletproof date validation routine.
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3 4 5 6
Quote:
Code:
`IF year / 4 = INT(year / 4) THEN`
Dark Ninja, your code for testing whether a year is a leap year is incorrect. The definition of a leap year (they added something to it, but I can't remember what) is:
Leapyear
#1. Factor of 4
#2. Not a factor of 100
#3. Rule 2 drops if year is factor of 400

So, the proper code would be:
Code:
```LeapYear = ((Year MOD 4 = 0 AND Year MOD 100 <> 0) OR (Year MOD 400 = 0)) IF LeapYear THEN blablabla```

Hope you can do something with it

EDIT:
Oh and:
Code:
`IF day < 28 OR`
Why are days lower than 28 invalid? :lol: That means your program will output 20000101 (1st Jan. 2000) as an invalid date.
Thanks, easily fixed.
Code:
```SUB DateVerify(FullDate\$) IF LEN(FullDate\$) <> 8 THEN PRINT "Invalid": END year\$ = LEFT\$(FullDate\$, 4) month\$ = MID\$(FullDate\$, 5, 2) day\$ = RIGHT\$(FullDate\$, 2) year = VAL(year\$) month = VAL(month\$) day = VAL(day\$) IF year <> INT(year) OR month <> INT(month) OR day <> INT(day) THEN PRINT "Invalid": END IF year > 3999 OR year < 1600 THEN PRINT "Invalid": END IF month < 1 OR month > 12 THEN PRINT "Invalid": END IF day > 31 THEN PRINT "Invalid": END IF month = 2 THEN   IF year / 4 = INT(year / 4)  THEN      Leap\$ = "yes"      IF year / 100 = INT(year / 100) THEN        Leap\$ = "no"        IF year / 400 = INT(year/400) THEN Leap\$ = "yes"      END IF   END IF   IF (day > 28 AND leap\$ = "no") OR (day > 29 AND leap\$ = "yes")   THEN     PRINT "Invalid": END   END IF END IF        IF month = 4 OR month = 6 OR month = 9 OR month = 11 THEN   IF day > 30 THEN PRINT "Invalid": END END IF PRINT "Valid": END END SUB```
Erm... the code looks functional, but there are still some things that could be improved

#1. I don't like my program to quit when I run your function (d'oh )

#2. It can be made much faster if you use integers.

Moneo, Meg, add comments if you wish
Quote:Erm... the code looks functional, but there are still some things that could be improved

#1. I don't like my program to quit when I run your function (d'oh )

#2. It can be made much faster if you use integers.

Moneo, Meg, add comments if you wish
Neo,
"... the code looks functional" --- you're being so kind.

About #2 above: Speed is really not an issue, but it is nice to write the speediest code you can, just as a matter of habit.

The same applies to writing tight, straight-line code with as few if's as possible. The more code your program has, and especially the more if's, then the more chances of bugs. Just like our friend DarkNinja's code; his enhanced leap year logic has so many if's, that I don't even want to bother checking it.
*****
Quote:Neo,
"... the code looks functional" --- you're being so kind.
I am always kind...

Quote:About #2 above: Speed is really not an issue, but it is nice to write the speediest code you can, just as a matter of habit.
Yeah, that is true, but I implicitly referred to Dark Ninja using strings as temporary storage (leapyear\$ = "yes", leapyear\$ = "no"). It's much less efficient than just leapyear = 0 or leapyear = -1.
It doesn't need to be ultrafast, just clean code with an acceptable algorithm.

Quote:The same applies to writing tight, straight-line code with as few if's as possible. The more code your program has, and especially the more if's, then the more chances of bugs. Just like our friend DarkNinja's code; his enhanced leap year logic has so many if's, that I don't even want to bother checking it.
I had the same thoughts.
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```
Looks good... a year later.

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

Also, hi! *hides into lonely darkness again*
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.
Quote:Looks good... a year later.

I'd dearly suggest though to reform it in the more "modern" style of coding
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
Quote: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.

*****
Pages: 1 2 3 4 5 6