Qbasicnews.com
May 31, 2020, 05:01:27 PM
 Pages: 1 [2] 3
 Author Topic: Compute a person's age today based on his date of birth.  (Read 18605 times)
Neo
Na_th_an

Posts: 2150

 « Reply #15 on: June 10, 2005, 04:15:54 PM »

Sorry moneo, final update.

Code:
Private Function getPersonAge (Year As Integer, Month As Integer, Day As Integer, _
NowYear As Integer, NowMonth As Integer, NowDay As Integer) As Integer
If (NowMonth > Month) Or (NowMonth = Month And NowDay >= Day) Then getPersonAge = NowYear - Year Else getPersonAge = NowYear - Year - 1
End Function

this is the simplest (at least) functional code I could think of.

I now did it in all 3 possible ways...
- Using a loop: will return the correct results, except from leaplings
- Using average calculation: will mostly return correct results and sometimes return ages that are +1 or -1
- Using conditional checks: will probably (only tested 80000 times yet) return correct results, including leaplings.

Now I'll be quiet so you can have the time to check these 3 (I'm pretty sure the latest 3-liner update can't be shortened anymore).

I apologize for another piece of code. This is my last submission (and probably the best working one too... :roll:).
 Logged
shiftLynx
Wandering Guru

Posts: 340

 « Reply #16 on: June 10, 2005, 05:04:41 PM »

Written in FreeBASIC; should work in QBASIC.

[syntax="QBasic"]
' Current Age Calculator
' 10-Jun-2005
'
' shiftlynx
' c.g.davies@gmail.com
'

'-----------------------------------------------------------------------------
' Custom Type Declarations
'
type Date
year as integer
month as integer
day as integer
end type

'-----------------------------------------------------------------------------
' Function Declarations
'
declare sub parseDate(dateString as string, target as Date)
declare sub parseDashedDate(dateString as string, target as Date)
declare function isValidDate%(obj as Date)
declare function getDays&(obj as Date)

'-----------------------------------------------------------------------------
' Main
'
dim dateIn as Date
dim dateCurrent as Date
dim dayDifference as long
dim age as long

cls
line input "Date of Birth: ", strdate\$

' parse the date strings.
parseDate(strdate\$, dateIn)
parseDashedDate(date\$, dateCurrent)

' validate the dates.
if isValidDate%(dateIn) = 0 then
print "Invalid date entered."
end
end if

if isValidDate%(dateCurrent) = 0 then
print "Failed to parse current date."
end
end if

' calculate the day difference.
dayDifference = getDays&(dateCurrent) - getDays&(dateIn)

' make sure the date entered wasn't in the future.
if dayDifference < 0 then
print "Invalid date of birth; it hasn't happened yet."
end
end if

' calculate the number of complete years.
age = int(dayDifference / 365.25)

' output the age.
print "Age: " + ltrim\$(str\$(age))

print "Press a key to exit..."
while inkey\$ = "": wend

sub parseDate(dateString as string, target as Date)

' reset the structure.
target.day = 0
target.month = 0
target.year = 0

' check that we have a valid length (must be YYYYMMDD).
if len(dateString) <> 8 then exit sub

' extract the components.
target.year = val(mid\$(dateString, 1, 4))
target.month = val(mid\$(dateString, 5, 2))
target.day = val(mid\$(dateString, 7, 2))

end sub

sub parseDashedDate(dateString as string, target as Date)

' reset the structure.
target.day = 0
target.month = 0
target.year = 0

' just make sure that the length of the date isn't too small.
' smallest date... x/x/xxxx = 8 chars.
if len(dateString) < 8 then exit sub

' store a "working-string".
tempStr\$ = dateString

' extract the month.
slash% = instr(tempStr\$, "-")
if slash% > 0 then
target.month = val(left\$(dateString, slash% - 1))
tempStr\$ = right\$(tempStr\$, len(tempStr\$) - slash%)
else
exit sub
end if

' extract the day.
slash% = instr(tempStr\$, "-")
if slash% > 0 then
target.day = val(left\$(tempStr\$, slash% - 1))
tempStr\$ = right\$(tempStr\$, len(tempStr\$) - slash%)
else
exit sub
end if

' extract the year.
target.year = val(tempStr\$)

end sub

function isValidDate%(obj as Date)

' check for obvious errors.
if obj.day < 1 or obj.day > 31 or obj.month < 1 or obj.month > 12 or obj.year < 0 then
isValidDate% = 0
exit function
end if

' now check specific errors.
select case obj.month
case 2:
if (obj.year and 3) = 0 then
if obj.day > 29 then
isValidDate% = 0
exit function
end if
else
if obj.day > 28 then
isValidDate% = 0
exit function
end if
end if
case 4, 6, 9, 11:
if obj.day > 30 then
isValidDate% = 0
exit function
end if
end select

' looks okay.
isValidDate% = 1

end function

function getDays&(obj as Date)

dim cumulativeMonthDays(1 to 12) as long

' ensure we're dealing with a valid date.
if isValidDate%(obj) = 0 then
getDays& = -1
exit function
end if

' calculate the days from the year and the day.
days& = int(obj.year * 365.25) + obj.day

' now to process the month field...

' check if we need to account for an extra day in February.
if (obj.year and 3) = 0 then
dayCount& = 1
else
dayCount& = 0
end if

' set up the month days array.
cumulativeMonthDays(1) = 0
dayCount% = dayCount& + 31 ' jan
cumulativeMonthDays(2) = 31
dayCount& = dayCount& + 28 ' feb
cumulativeMonthDays(3) = dayCount&
dayCount& = dayCount& + 31 ' mar
cumulativeMonthDays(4) = dayCount&
dayCount& = dayCount& + 30 ' apr
cumulativeMonthDays(5) = dayCount&
dayCount& = dayCount& + 31 ' may
cumulativeMonthDays(6) = dayCount&
dayCount& = dayCount& + 30 ' jun
cumulativeMonthDays(7) = dayCount&
dayCount& = dayCount& + 31 ' jul
cumulativeMonthDays( = dayCount&
dayCount& = dayCount& + 31 ' aug
cumulativeMonthDays(9) = dayCount&
dayCount& = dayCount& + 30 ' sep
cumulativeMonthDays(10) = dayCount&
dayCount& = dayCount& + 31 ' oct
cumulativeMonthDays(11) = dayCount&
dayCount& = dayCount& + 30 ' nov
cumulativeMonthDays(12) = dayCount&

' now add the month days on to the day total.
days& = days& + cumulativeMonthDays(obj.month)

' set the return value.
getDays& = days&

end function
[/syntax]
 Logged

img]http://www.cdsoft.co.uk/misc/shiftlynx.png[/img]
Deleter
Na_th_an

Posts: 1293

 « Reply #17 on: June 10, 2005, 05:31:38 PM »

ok, extra chopped off, definition of leap year corrected and its ready to roll (I hope )
Code:
declare function maxday(month as integer, year as integer)

print "Type 'X' to exit"
do
input\$ "Birthdate (YYYYMMDD)", birth\$
if ucase\$(left\$(birth\$, 1)) = "X" then exit do
cdate\$ = date\$
cyear = val(mid\$(cdate\$, 7, 4))
cmonth = val(mid\$(cdate\$,1,2))
cday = val(mid\$(cdate\$, 4, 2))
byear = val(mid\$(birth\$, 1, 4))
bmonth = val(mid\$(birth\$, 5,2))
if bmonth < 1 or bmonth > 12 then byear = cyear+1
bday = val(mid\$(birth\$,7,2))
if bday < 1 or bday > maxday(bmonth, byear) then byear = cyear+1
age = (cyear - byear) - 1
if (bmonth <= cmonth) and (bday <= cday or bmonth < cmonth) then
age = age + 1
end if
if byear < 0 then byear = cyear+1
if age < 0 then
print "Invalid birthdate"
elseif age < 1 then
print cmonth-bmonth; " months old"
elseif age = 1 then
print age; " year old"
elseif age > 1 then
print age; " years old"
end if
loop
end

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))=-1 then tmaxday = 29
maxday=tmaxday
end function

edit: added if statment to make sure year was greater than or equal to 0
 Logged

Neo
Na_th_an

Posts: 2150

 « Reply #18 on: June 10, 2005, 07:22:01 PM »

Okay, as everyone is posting new updates, I put my latest updates together in one file, ready for execution.

Code:
Option Static
Option Explicit

Declare Function convertDate (Dat As String, YY As Integer, MM As Integer, DD As Integer) As Byte
Declare Function isValidDate (Year As Integer, Month As Integer, Day As Integer) As Byte
Declare Function isLeapYear (Year As Integer) As Byte
Declare Function getPersonAge (Year As Integer, Month As Integer, Day As Integer, _
NowYear As Integer, NowMonth As Integer, NowDay As Integer) As Integer

'@ Ask the user for input YYYYMMDD and check if it's valid
Dim Datum As String, isOk As Byte
Dim Year As Integer, Month As Integer, Day As Integer
Do
Input "Enter a valid birthday in format YYYYMMDD: ", Datum
isOk = convertDate(Datum, Year, Month, Day)
If Not( isOk ) Then Print "Invalid entry"
Loop Until isOk

'@ Get the current Date (format MM-DD-YYYY)
Dim CurrYear As Integer, CurrMonth As Integer, CurrDay As Integer
If convertDate(Date\$, CurrYear, CurrMonth, CurrDay) = 0 Then Print "Current date is invalid": End

'@ Get persons age and print it
Dim rAge As Integer
rAge = getPersonAge(Year, Month, Day, CurrYear, CurrMonth, CurrDay)
If rAge > 0 Then
Print "Persons age: "; rAge
Else
If Year > CurrYear Or (Year = CurrYear And Month > CurrMonth) Or (Year = CurrYear And Month = CurrMonth And Day > CurrDay) Then
Print "This person is yet to be born"
Else
Print "Persons age: "; rAge
End If
End If

Sleep
End

Private Function convertDate (Dat As String, YY As Integer, MM As Integer, DD As Integer) As Byte
Dim NumberStr As String , i As Integer
NumberStr = "0123456789"
If Len(Dat) <> 8 And Len(Dat) <> 10 Then
convertDate = 0: Exit Function
ElseIf Len(Dat) = 8 Then
For i = 0 To 7
If Instr(NumberStr, Mid\$(Dat, i + 1, 1)) = 0 Then convertDate = 0: Exit Function
Next i
YY = Val(Left\$(Dat, 4))
MM = Val(Mid\$(Dat, 5, 2))
DD = Val(Right\$(Dat, 2))
convertDate = isValidDate(YY, MM, DD)
ElseIf Len(Dat) = 10 Then
For i = 0 To 9
If i = 2 Or i = 5 Then
If Mid\$(Dat, i + 1, 1) <> "-" Then convertDate = 0: Exit Function
Else
If Instr(NumberStr, Mid\$(Dat, i + 1, 1)) = 0 Then convertDate = 0: Exit Function
End If
Next i
YY = Val(Right\$(Dat, 4))
MM = Val(Left\$(Dat, 2))
DD = Val(Mid\$(Dat, 4, 2))
convertDate = isValidDate(YY, MM, DD)
End If
End Function

Private Function getPersonAge (Year As Integer, Month As Integer, Day As Integer, _
NowYear As Integer, NowMonth As Integer, NowDay As Integer) As Integer
If (NowMonth > Month) Or (NowMonth = Month And NowDay >= Day) Then getPersonAge = NowYear - Year Else getPersonAge = NowYear - Year - 1
End Function

Private Function isValidDate (Year As Integer, Month As Integer, Day As Integer) As Byte
'@ Checks if a year is a valid year
If Year < 0 Then isValidDate = 0: Exit Function
If Month < 1 Then isValidDate = 0: Exit Function
If Day < 1 Then isValidDate = 0: Exit Function

If Month > 12 Then isValidDate = 0: Exit Function

Dim MaxDay As Integer
Select Case Month
Case 1, 3, 5, 7, 8, 10, 12 : MaxDay = 31
Case 4, 6, 9, 11: MaxDay = 30
Case 2: MaxDay = 28 + Abs(isLeapYear(Year))
End Select

If Day > MaxDay Then isValidDate = 0: Exit Function

isValidDate = -1
End Function

Private Function isLeapYear (Year As Integer) As Byte
isLeapYear = ((Year MOD 4 = 0) AND (Year MOD 100 <> 0)) OR (Year MOD 400 = 0)
End Function

And shiftLynx... also for you holds the same as I said to Deleter a while ago
Quote from: "WikiPedia"
The Gregorian calendar adds an extra day to February, making it 29 days long, in years where the quotient has no remainder when divided by 4, excluding years where the quotient has no remainder when divided by 100, but including years where the quotient has no remainder when divided by 400.
 Logged
shiftLynx
Wandering Guru

Posts: 340

 « Reply #19 on: June 10, 2005, 07:42:11 PM »

[syntax="QBasic"]
' Current Age Calculator
' 10-Jun-2005
'
' shiftlynx
' c.g.davies@gmail.com
'
' Changes:
'   [10-Jun-2005]       Fixed leap-year calculation algorithm... turns out
'                       to be a bit more complicated then just "mod 4".
'

'-----------------------------------------------------------------------------
' Custom Type Declarations
'
type Date
year as integer
month as integer
day as integer
end type

'-----------------------------------------------------------------------------
' Function Declarations
'
declare sub parseDate(dateString as string, target as Date)
declare sub parseDashedDate(dateString as string, target as Date)
declare function isValidDate%(obj as Date)
declare function getDays&(obj as Date)
declare function isLeapYear%(year as integer)

'-----------------------------------------------------------------------------
' Main
'
dim dateIn as Date
dim dateCurrent as Date
dim dayDifference as long
dim age as long

cls
line input "Date of Birth: ", strdate\$

' parse the date strings.
parseDate(strdate\$, dateIn)
parseDashedDate(date\$, dateCurrent)

' validate the dates.
if isValidDate%(dateIn) = 0 then
print "Invalid date entered."
end
end if

if isValidDate%(dateCurrent) = 0 then
print "Failed to parse current date."
end
end if

' calculate the day difference.
dayDifference = getDays&(dateCurrent) - getDays&(dateIn)

' make sure the date entered wasn't in the future.
if dayDifference < 0 then
print "Invalid date of birth; it hasn't happened yet."
end
end if

' calculate the number of complete years.
age = int(dayDifference / 365.25)

' output the age.
print "Age: " + ltrim\$(str\$(age))

print "Press a key to exit..."
while inkey\$ = "": wend

sub parseDate(dateString as string, target as Date)

' reset the structure.
target.day = 0
target.month = 0
target.year = 0

' check that we have a valid length (must be YYYYMMDD).
if len(dateString) <> 8 then exit sub

' extract the components.
target.year = val(mid\$(dateString, 1, 4))
target.month = val(mid\$(dateString, 5, 2))
target.day = val(mid\$(dateString, 7, 2))

end sub

sub parseDashedDate(dateString as string, target as Date)

' reset the structure.
target.day = 0
target.month = 0
target.year = 0

' just make sure that the length of the date isn't too small.
' smallest date... x/x/xxxx = 8 chars.
if len(dateString) < 8 then exit sub

' store a "working-string".
tempStr\$ = dateString

' extract the month.
slash% = instr(tempStr\$, "-")
if slash% > 0 then
target.month = val(left\$(dateString, slash% - 1))
tempStr\$ = right\$(tempStr\$, len(tempStr\$) - slash%)
else
exit sub
end if

' extract the day.
slash% = instr(tempStr\$, "-")
if slash% > 0 then
target.day = val(left\$(tempStr\$, slash% - 1))
tempStr\$ = right\$(tempStr\$, len(tempStr\$) - slash%)
else
exit sub
end if

' extract the year.
target.year = val(tempStr\$)

end sub

function isValidDate%(obj as Date)

' check for obvious errors.
if obj.day < 1 or obj.day > 31 or obj.month < 1 or obj.month > 12 or obj.year < 0 then
isValidDate% = 0
exit function
end if

' now check specific errors.
select case obj.month
case 2:
if isLeapYear%(obj.year) = 1 then
if obj.day > 29 then
isValidDate% = 0
exit function
end if
else
if obj.day > 28 then
isValidDate% = 0
exit function
end if
end if
case 4, 6, 9, 11:
if obj.day > 30 then
isValidDate% = 0
exit function
end if
end select

' looks okay.
isValidDate% = 1

end function

function getDays&(obj as Date)

dim cumulativeMonthDays(1 to 12) as long

' ensure we're dealing with a valid date.
if isValidDate%(obj) = 0 then
getDays& = -1
exit function
end if

' calculate the days from the year and the day.
days& = int(obj.year * 365.25) + obj.day

' now to process the month field...

' check if we need to account for an extra day in February.
if isLeapYear%(obj.year) = 1 then
dayCount& = 1
else
dayCount& = 0
end if

' set up the month days array.
cumulativeMonthDays(1) = 0
dayCount% = dayCount& + 31 ' jan
cumulativeMonthDays(2) = 31
dayCount& = dayCount& + 28 ' feb
cumulativeMonthDays(3) = dayCount&
dayCount& = dayCount& + 31 ' mar
cumulativeMonthDays(4) = dayCount&
dayCount& = dayCount& + 30 ' apr
cumulativeMonthDays(5) = dayCount&
dayCount& = dayCount& + 31 ' may
cumulativeMonthDays(6) = dayCount&
dayCount& = dayCount& + 30 ' jun
cumulativeMonthDays(7) = dayCount&
dayCount& = dayCount& + 31 ' jul
cumulativeMonthDays( = dayCount&
dayCount& = dayCount& + 31 ' aug
cumulativeMonthDays(9) = dayCount&
dayCount& = dayCount& + 30 ' sep
cumulativeMonthDays(10) = dayCount&
dayCount& = dayCount& + 31 ' oct
cumulativeMonthDays(11) = dayCount&
dayCount& = dayCount& + 30 ' nov
cumulativeMonthDays(12) = dayCount&

' now add the month days on to the day total.
days& = days& + cumulativeMonthDays(obj.month)

' set the return value.
getDays& = days&

end function

function isLeapYear%(year as integer)
modFour% = year and 3
modOneHundred% = year mod 100
modFourHundred% = year mod 400

if modFour% = 0 then
if (modOneHundred% = 0) and (modFourHundred% <> 0) then
isLeapYear% = 0
exit function
end if

isLeapYear% = 1
exit function
end if

isLeapYear% = 0
exit function

end function
[/syntax]
 Logged

img]http://www.cdsoft.co.uk/misc/shiftlynx.png[/img]
Moneo
Na_th_an

Posts: 1971

 « Reply #20 on: June 10, 2005, 11:07:23 PM »

Neo and Deleter,

Check me out on the following:

I think the logic that both of you have at the end of the program where you finally compute the person's age, is a bit complicated. It has too many IF's.

They way I see it is as follows:

* We have done all the validations already, including that the date of birth is not in the future.

* Create a 4 byte variable called BMMDD\$ which contains the month and day of the birth date.

* Create another 4 byte variable called CMMDD\$ from the current date.

* We should already have a numeric variable called BYEAR for the year of the date of birth, and one called CYEAR for the year from the current date.

* Now we're ready to compute the AGE:
Code:

AGE = CYEAR - BYEAR
IF BMMDD\$ < CMMDD\$ THEN AGE = AGE - 1

You guys have been testing this problem much more than I, so tell me, will the above work? If not, why?

Thanks.
*****
 Logged
Moneo
Na_th_an

Posts: 1971

 « Reply #21 on: June 10, 2005, 11:11:33 PM »

ShiftLynx,

Your solution looks quite complicate, but nevertheless I'll give it a shot as soon as I finish writing the test program.
*****
 Logged
Deleter
Na_th_an

Posts: 1293

 « Reply #22 on: June 11, 2005, 12:55:37 AM »

well, I suppose that'd work, but technically, after validation, I am only using 2 more checks than you, all iside one IF statement, and I am too tired to rewrite the program right now because I just finished writing 2.6K words on an AI article.
 Logged

Neo
Na_th_an

Posts: 2150

 « Reply #23 on: June 11, 2005, 06:25:23 AM »

Hello Moneo,

Quote from: "Moneo"
I think the logic that both of you have at the end of the program where you finally compute the person's age, is a bit complicated. It has too many IF's.

I don't believe so. It only contains 1 IF, and 3 lines.
Here is the part of my code that calculates a persons age:
Code:
Private Function getPersonAge (Year As Integer, Month As Integer, Day As Integer, _
NowYear As Integer, NowMonth As Integer, NowDay As Integer) As Integer
If (NowMonth > Month) Or (NowMonth = Month And NowDay >= Day) Then getPersonAge = NowYear - Year Else getPersonAge = NowYear - Year - 1
End Function

Quote from: "Moneo"
* We have done all the validations already, including that the date of birth is not in the future.

Yes. Which is why the age calculation can be done in 1 line (see function above).

Quote from: "Moneo"
* Create a 4 byte variable called BMMDD\$ which contains the month and day of the birth date.

* Create another 4 byte variable called CMMDD\$ from the current date.

* We should already have a numeric variable called BYEAR for the year of the date of birth, and one called CYEAR for the year from the current date.

* Now we're ready to compute the AGE:
Code:

AGE = CYEAR - BYEAR
IF BMMDD\$ < CMMDD\$ THEN AGE = AGE - 1

You guys have been testing this problem much more than I, so tell me, will the above work? If not, why?

The code you provided will not work, as it would return an age too high if the birthday hasn't passed yet, and an age too low if the birthday already passed. This flaw will be fixed if the < is turned into a >.
Your code is the same as mine in general, only you need more lines for converting the dates to the appropriate string format.

Thanks for checking. (Although it seems you didn't test the code I supplied you with the last time, which is also displayed in this post of mine).
 Logged
Moneo
Na_th_an

Posts: 1971

 « Reply #24 on: June 11, 2005, 02:26:29 PM »

(see next edited post.................)
 Logged
Moneo
Na_th_an

Posts: 1971

 « Reply #25 on: June 11, 2005, 02:51:23 PM »

Quote from: "Moneo"
Quote from: "Neo"
...
The code you provided will not work, as it would return an age too high if the birthday hasn't passed yet, and an age too low if the birthday already passed. This flaw will be fixed if the < is turned into a >.

Neo,
You're absolutely right. The compare should be:
Code:

IF BMMDD\$  > CMMDD\$ THEN AGE = AGE - 1

A comment should be added saying: "At this point, the current year is included in the AGE. If the birthday has not happened yet in the current year, then adjust the AGE down by one year so as to exclude the current year from the age. By the same token, if the  birthday has passed, or we are exactly on it, then the age is correct as is."

Neo, now that you've debugged my logic, I'm going to use this in the test program. Let's see whaat happens when we run your solution and also Deleter's in a test of about 100 years worth of birthdays.
*****
 Logged
Moneo
Na_th_an

Posts: 1971

 « Reply #26 on: June 11, 2005, 04:21:12 PM »

Deleter,

I tested yours first since, of the final versions, yours was posted first.

The test program runs through every day from 19000101 to 20051231.

The answer of AGE which you compute is compared to the one I compute. They all match except a few shown below.

The first column is the Current Date used.
The second column is the Birth Date being processed.
The third coumn is the AGE that I compute.
The fourth column is the AGE you compute.

Only records with differences in AGE are displayed.
Code:

CurDate=06-11-2005  BirDate= 2000 0130   5              -1
CurDate=06-11-2005  BirDate= 2000 0131   5              -1
CurDate=06-11-2005  BirDate= 2000 0330   5              -1
CurDate=06-11-2005  BirDate= 2000 0331   5              -1
CurDate=06-11-2005  BirDate= 2000 0430   5              -1
CurDate=06-11-2005  BirDate= 2000 0530   5              -1
CurDate=06-11-2005  BirDate= 2000 0531   5              -1
CurDate=06-11-2005  BirDate= 2000 0630   4              -2
CurDate=06-11-2005  BirDate= 2000 0730   4              -2
CurDate=06-11-2005  BirDate= 2000 0731   4              -2
CurDate=06-11-2005  BirDate= 2000 0830   4              -2
CurDate=06-11-2005  BirDate= 2000 0831   4              -2
CurDate=06-11-2005  BirDate= 2000 0930   4              -2
CurDate=06-11-2005  BirDate= 2000 1030   4              -2
CurDate=06-11-2005  BirDate= 2000 1031   4              -2
CurDate=06-11-2005  BirDate= 2000 1130   4              -2
CurDate=06-11-2005  BirDate= 2000 1230   4              -2
CurDate=06-11-2005  BirDate= 2000 1231   4              -2

As you can see, only a few failed, and they're all in the year 2000, which was a leapyear. Check it out and submit a fix.
*****
 Logged
Moneo
Na_th_an

Posts: 1971

 « Reply #27 on: June 11, 2005, 04:51:04 PM »

Neo,

I ran a test from 19000101 to 20051231 with  current date of 20051231, and you solution ran perfectly. Congratulations!

After I test Lynx's entry, a winner will be announced.
*****
 Logged
Moneo
Na_th_an

Posts: 1971

 « Reply #28 on: June 11, 2005, 09:33:17 PM »

SHIFTLYNX,

I did some initial tests today June 11th on your code of June 10th, I found the following anomalies:

1) With a date of birth of 20040611 it issues an age of 0, which should be 1.

2) With a date of birth of 20040610 it also issues an age of 0, which should be 1.

However, with a date of birth of 20040609 it issues years of 1, which is correct.

I suspect that the problem is your use of 365.25 average days in your calculations. But, test it yourself.

I'll wait a few days for your revised solution.
*****
 Logged
Deleter
Na_th_an

Posts: 1293

 « Reply #29 on: June 12, 2005, 10:03:22 PM »

ok, the error was in the check for the leap year every 400 that overrides the 100 rule. Fixed code:
Code:
declare function maxday(month as integer, year as integer)

print "Type 'X' to exit"
do
input\$ "Birthdate (YYYYMMDD)", birth\$
if ucase\$(left\$(birth\$, 1)) = "X" then exit do
cdate\$ = date\$
cyear = val(mid\$(cdate\$, 7, 4))
cmonth = val(mid\$(cdate\$,1,2))
cday = val(mid\$(cdate\$, 4, 2))
byear = val(mid\$(birth\$, 1, 4))
bmonth = val(mid\$(birth\$, 5,2))
if bmonth < 1 or bmonth > 12 then byear = cyear+1
bday = val(mid\$(birth\$,7,2))
if bday < 1 or bday > maxday(bmonth, byear) then byear = cyear+1
age = (cyear - byear) - 1
if (bmonth <= cmonth) and (bday <= cday or bmonth < cmonth) then
age = age + 1
end if
if byear < 0 then byear = cyear+1
if age < 0 then
print "Invalid birthdate"
elseif age < 1 then
print cmonth-bmonth; " months old"
elseif age = 1 then
print age; " year old"
elseif age > 1 then
print age; " years old"
end if
loop
end

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
 Logged

 Pages: 1 [2] 3