Hi Kathleen,
This raises some questions for me:
02/01/1968 - 03/01/1968 = 0 years, 1 month, 0 days (seems obvious)
but then there's this:
02/29/1968 - 03/31/1968 = 0 years, 1 month, 0 days OR 0 years, 1 month, 2 days?
02/01/1967 - 02/01/1968 = 1 year, 0 months, 0 days (again, seems obvious)
but then there's:
02/28/1967 - 02/29/1968 = 1 year, 0 months, 0 days OR 1 year, 0 months, 1 day?
02/29/1968 - 02/28/1969 = 1 year, 0 months, 0 days OR 0 years, 11 months, 28 days?
If you think, "I won't worry about this, I'll only look at whole years and whole months and then gather up the stray days," in other words: days from the start date to the end of that month + whole years and whole months + days from the first of the end month to the end date. But doing that can lead to more days than any given month could have:
02/10/1967 - 03/20/1969 = 18 days + 2 years and 0 months + 20 days ... or 2 years and 38 days!
In the above example, you might say "I'll just go from 10th to 10th to 10th, and then pick up any days left over!" In other words go from 02/10 to 03/10 to 04/10 to etc, to get 2 years, 1 month and 10 days.
What if we reverse the DDs: 02/20/1967 - 03/10/1969 = 2/20 to 3/20 to 4/20 to etc = 2 years and 18 days. That seems reasonable.
What about 01/30/1967 - 02/28/1969? 1/30/67 - 2/28/67 - 3/30/67 - ... - 1/30/69 - 2/28/69, so 2 years and 1 month? (The question is the day from 1/30/1967 to 1/31/1967, but it seems reasonable to leave it out.)
What about 01/28/1967 - 02/29/1968? 1 year, 1 month, 1 day? I guess that seems reasonable.
What about the above examples where the start date is the end of the month? I think that's a special case where you have to go from end of month to end of month, not exact dates. (We already kind of did that for Jan 30th to Feb 28th, etc. I'm just suggesting that if you start at the end of February then you go to the end of each other month before gathering up the stray days.)
So if you don't have a problem with 1/30/1967 - 2/28/1969 being 2 years and 1 month, then that seems like the way to go. If you do have a problem with it, then there will always potentially be wonkiness with start dates 29th, 30th or 31st.
Assuming you can live with that, this is a quick stab at an algorithm. It could definitely be made more efficient.
PROGRAM DIFF.DATE
*
D1 = '2/1/1968'
D2 = '3/1/1968'
GOSUB CALC.IT
*
D1 = '2/29/1968'
D2 = '3/31/1968'
GOSUB CALC.IT
*
D1 = '2/1/1967'
D2 = '2/1/1968'
GOSUB CALC.IT
*
D1 = '2/28/1967'
D2 = '2/29/1968'
GOSUB CALC.IT
*
D1 = '2/29/1968'
D2 = '2/28/1969'
GOSUB CALC.IT
*
D1 = '2/10/1967'
D2 = '3/20/1969'
GOSUB CALC.IT
*
D1 = '1/30/1967'
D2 = '2/28/1969'
GOSUB CALC.IT
*
D1 = '2/12/1967'
D2 = '10/18/1968'
GOSUB CALC.IT
*
D1 = '8/26/1967'
D2 = '9/27/2021'
GOSUB CALC.IT
*
D1 = '10/28/1967'
D2 = '9/27/2021'
GOSUB CALC.IT
BOTTOM:
STOP
CALC.IT:
D1I = ICONV(D1,'D')
D2I = ICONV(D2,'D')
*
IF D2I <= D1I THEN
YDIFF = 0
MDIFF = 0
DDIFF = 0
GOTO EXIT.CALC.IT
END
*
PRINT OCONV(D1I,'D4/'):" - ":OCONV(D2I,'D4/')
*
* are we starting on the last day of the month?
IF (OCONV(D1I,'D M[2]') # OCONV(D1I+1,'D M[2]')) THEN
* yes! advance both dates by 1 day
D1I += 1
D2I += 1
END
*
D1O = OCONV(D1I,'D4/')
D2O = OCONV(D2I,'D4/')
MM1 = D1O['/',1,1]; MM2 = D2O['/',1,1]
DD1 = D1O['/',2,1]
YYYY1 = D1O['/',3,1]; YYYY2 = D2O['/',3,1]
*
IF YYYY1 < YYYY2 THEN
YYYY3 = YYYY1
LOOP
DD3 = DD1
Y.TRY.AGAIN:
D3I = ICONV(MM1:'/':DD3:'/':(YYYY3 + 1),'D')
IF STATUS() THEN
DD3 -= 1
GOTO Y.TRY.AGAIN
END
TEST = D2I - D3I
WHILE TEST >= 0 DO
YYYY3 += 1
REPEAT
END ELSE
YYYY3 = YYYY1
END
YDIFF = YYYY3 - YYYY1
*
IF YYYY3 < YYYY2 OR MM1 < MM2 THEN
MDIFF = 0
MM3 = MM1; TEMP = DD1
LOOP
DD3 = DD1
M.TRY.AGAIN:
IF MM3 = 12 THEN
D3O = '01/':DD3:'/':(YYYY3 + 1)
END ELSE
D3O = (MM3 + 1):'/':DD3:'/':YYYY3
END
D3I = ICONV(D3O,'D')
IF STATUS() THEN
DD3 -= 1
GOTO M.TRY.AGAIN
END
TEST = D2I - D3I
WHILE TEST >= 0 DO
MM3 = D3O['/',1,1]
TEMP = D3O['/',2,1]
YYYY3 = D3O['/',3,1]
MDIFF += 1
REPEAT
DD3 = TEMP
END ELSE
DD3 = DD1
MM3 = MM1
MDIFF = 0
END
*
DDIFF = 0
D3I = ICONV(MM3:'/':DD3:'/':YYYY3,'D')
DDIFF = D2I - D3I
*
EXIT.CALC.IT:
PRINT "YDIFF = ":YDIFF
PRINT "MDIFF = ":MDIFF
PRINT "DDIFF = ":DDIFF
PRINT " "
RETURN
*
END
If that works for you, feel free to carve out the "CALC.IT" part and work it into a subroutine.
Thanks,
------------------------------
Tyrel Marak
Technical Support Manager
Aptron Corporation
Florham Park NJ United States
------------------------------
Original Message:
Sent: 09-24-2021 14:04
From: Kathleen Hambrick
Subject: AGE CALCULATION
Seems so simple but, i'm trying to get ones exact age, on any given day, using their internal birthday. If I do the obvious, subtract internal birthdate from current date and divide by 36525, I get the accurate year but months and days comes out as a fraction of a year...
Anyone have an easy calc for this?
Thanks
------------------------------
Kathleen Hambrick
PROGRAMMER
William C Earhart Co Inc
Portland OR United States
------------------------------