Qbasicnews.com February 23, 2020, 02:03:39 AM  Pages: 1 2 Author Topic: Compute a person's age today based on his date of birth.  (Read 18278 times)
Moneo
Na_th_an     Posts: 1971 « Reply #30 on: June 13, 2005, 12:52:38 AM »

Deleter,

I ran the same test as before, and it works fine now. Congratulations. However, your code for the "maxday" function looks a little shakey, and I suspect it would not work for any dates.
Code:

function maxday(month as integer, year as integer)
tmaxday = 30
if (month/2 <> int(month/2) and month < 8) or (month>7 and month/2 = int(month/2)) then tmaxday=31
if month=2 and ((year mod 4 <> 0) or (year mod 100 = 0)) then tmaxday=28
if (((month=2 and year mod 4 = 0) and year mod 100 <> 0) or (year mod 400 = 0 and month=2))=-1 then tmaxday = 29
maxday=tmaxday
end function

The second if "if month=2 and ...." does not have the test for mod 400. I'm not sure it needs it, but it's worth taking a look at it.

The third if "if (((month=2 and year ..." does not say "and month=2" for the mod 100 test. Again, I'm not sure it needs it, but take a look.

EDIT: Somehow I got the wrong impression from looking at your code 'cause it looks different. However, I just tested it again using birthdays from the year 1 to the year 2501 with a current date of 12/31/2501, and it works fine. Sorry for under-estimating your code. Good job!

BTW, I also ran Neo's version with the same dates, and his runs fine also.
***** Logged
Deleter
Na_th_an     Posts: 1293   « Reply #31 on: June 17, 2005, 03:29:02 PM »

the parentheses combined with the AND statements make it a bit confusing. The way that works, the second and doesnt need if month=2, because the first parameter entered requres it. And, the second and doesnt need the 400 check, because the third IF does the check for 400, therefore overriding whatever decision the second if makes. logic, what fun  Logged

Moneo
Na_th_an     Posts: 1971 « Reply #32 on: June 20, 2005, 02:56:10 PM »

Enough time has been given to ShiftLynx to fix his entry, and for any others to submit solutions. So, this brings this challenge to a close.

The only solutions that worked were those of Deleter and Neo. During the testing phase, they each enhanced their solutions to a point where even the most stringent testing would not make them fail.

I have to acknowledge both their efforts, and see no other way than to consider them both as equal winners of this challenge. Congratulations Deleter and Neo, and thanks for participating in the challenge and sharing your programming know-how with others.

BTW, here's my own solution for the challenge's problem. You will note that 99% of the program is getting and validating the dates. The actual computation of the age turns out to be 2 lines of code.
Code:

DEFINT A-Z

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

rem Setup days-per-month table.
DIM ZMO(1 TO 12) AS INTEGER
DATA 31,28,31,30,31,30,31,31,30,31,30,31

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

cdate\$=date\$  'Get current system date as mm-dd-yyyy
if left\$(time\$,2)="00" then cdate\$=date\$  'make sure date didn't just roll over
rem System date is assumed to be valid.
cyear = val(mid\$(cdate\$,7,4))
cmmdd\$=left\$(cdate\$,2)+mid\$(cdate\$,4,2)
cymd\$=mid\$(cdate\$,7,4)+cmmdd\$

input "Enter Person's Date of Birth as YYYYMMDD ", birth\$
z\$=birth\$:gosub date.check
if date.ok=0 or birth\$>cymd\$ then print "Invalid Birth Date=";birth\$:system
byear  = val(mid\$(birth\$,1,4))
bmmdd\$ = mid\$(birth\$,5,4)

rem Compute the person's age in years.
age=cyear-byear
if bmmdd\$ > cmmdd\$ then age=age-1
print "The person's age today is ";age
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 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

REM *****   F U N C T I O N S   *****

' ====================== 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\$)

REM *
REM *** CHECK FOR STRICTLY NUMERIC (NO NULL, NO NEGATIVE, NO DECIMAL)
REM *

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
 Pages: 1 2