Old code to compute age from dates (was it Art Kendall's?)

classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Old code to compute age from dates (was it Art Kendall's?)

Marta Garcia-Granero
Hi:

This is the Stata User Formerly Known As an SPSS Macro Programmer (SUFKASP).

Since SPSS 13 I use(d) DATEDIF to compute age from two dates. Stata
users seem to keep on using the old formula:
int(StudyDate-DateOfBirth)/365.25 (since Stata stores dates as days, it
is easier than the SPSS counterpart, that required CTIME.DAYS to convert
seconds to days).

I recall that years ago we had an interesting thread concerning the
errors this method could cause in some cases. I had and slightly
improved version:

INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)

That avoided some errors, but not all of them.

There was a short syntax that computed ages correctly before SPSS 13. It
looks that I did not keep a copy of it (bad idea..) because of DATEDIF.
I would like to have it again to translate it to a Stata do file.

Does anybody keep it yet?

Thanks in advance

Marta GG (SUFKASP)

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Barnett, Adrian (DECD)
Hi Marta
About ten years ago I ran into this problem with dates, and after some web research on calendars and date calculations (especially reliant on a web page of handy hints from an SPSS-using researcher from NZ) came up with a couple of approaches :

As you discovered, the usual method falls over on anniversaries. Often this isn't a problem, but there are some purposes where it is important to be able to state whether someone is above or below a critical age in years. In my former employment preparing statistics on criminal justice, it was important to know whether offenders were to be treated as juveniles by the courts, and whether victims were in particular age brackets (for the purposes of sentencing), so avoiding being even a day out in the age calculation was critical.

do if ((STARTMTH eq ENDMTH) and (STARTDAY eq ENDDAY))
+  compute LNTHYRS = rnd((ENDDATE - STARTDAT)/(24*60*60*365.2425))
else
+  compute LNTHYRS = trunc((ENDDATE - STARTDAT)/(24*60*60*365.2425))
end if

Notes:

(1)     the correct number of days in the average year, to account for leap years, is 365.2425, not 365.25.  There are in fact fewer than one leap year every four years, because there are exceptions applied to century years such as 2000.  Using 365.25 for the number of days in a year is the system used in the superseded Julian calendar, whereas the Gregorian calendar we now use employs 365.2425.
(2)     you can substitute 86400 (the number of seconds in a year) for the 24*60*60 calculation, to make it more efficient.
(3)     if you don't want to bother with the conversion into days of the time difference between the dates, you can use the CTIME.DAYS function, applied to each of the two dates, and omit the 24*60*60 calculation.

The first part of the statement above handles the special case of anniversaries, where the result in years, prior to rounding, will be almost exactly the correct number of years, but slightly smaller.  Rounding it to the nearest year gives the correct answer.  For example if the two dates were January 1st 1900 and January 1st 1901, the difference in years, prior to rounding, is 0.9993361.. Rounded to the nearest year, it gives the correct answer of one year, whilst if you truncate it, you get the incorrect answer of zero.
Dates which are not anniversaries are handled by the second part of the conditional, which gives the correct result.


A second method

There is another way of performing the calculation.  It is no shorter than the above one, in terms of lines of code, but it may appeal to some because it works in the same way as we do in everyday life when working out how many years there are between two dates.

It works by finding out first if the second date (the end date) is later in the year than (or on the same day as) the first date.  If it is, you can just subtract the first year from the second year and the answer is the number of years between them.  If it is earlier, you take one off the difference.

As in the previous example, the code below assumes you have variables representing the month and day part of the dates concerned.

do if ((ENDMTH ge STARTMTH) and (ENDDAY ge STARTDAY))
+  compute LNTHYRS = ENDYR - STARTYR
else
+  compute LNTHYRS = ENDYR - STARTYR -1
end if

Note: (1) if you don't want to bother with storing the year, day and month portions of a date you can use the XDATE.YEAR, XDATE.MDAY and XDATE.MONTH functions, applied to the relevant date variables.
(2) Another way of doing the check on whether the second date is earlier or later in the year than the first is to combine the month and day like this :

compute STRT = (100*STARTMTH) + STARTDAY
compute END  = (100*ENDMTH) + ENDDAY

Whichever date is later in the year will produce the bigger number.  Thus, for example, the 29th of June becomes 629 and the 30th becomes 630.  So in the example above, the first line would become :

do if (END ge START)

Note how the comparison of the two dates is a test of whether the end date is greater than or equal to the start, thus allowing for anniversaries, which have to be accommodated in much the same way as in the original method.

It's a long time since I wrote the above notes, so I hope I haven't made any silly blunders in there. I hope this helps

Regards,

Adrian


Adrian Barnett
Project Officer
Educational Measurement and Analysis
Data and Information Systems
Department for Education and Child Development

"Children and young people are at the centre of everything we do"

-----Original Message-----
From: SPSSX(r) Discussion [mailto:[hidden email]] On Behalf Of Marta García-Granero
Sent: Thursday, 6 December 2012 1:29 AM
To: [hidden email]
Subject: Old code to compute age from dates (was it Art Kendall's?)

Hi:

This is the Stata User Formerly Known As an SPSS Macro Programmer (SUFKASP).

Since SPSS 13 I use(d) DATEDIF to compute age from two dates. Stata users seem to keep on using the old formula:
int(StudyDate-DateOfBirth)/365.25 (since Stata stores dates as days, it is easier than the SPSS counterpart, that required CTIME.DAYS to convert seconds to days).

I recall that years ago we had an interesting thread concerning the errors this method could cause in some cases. I had and slightly improved version:

INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)

That avoided some errors, but not all of them.

There was a short syntax that computed ages correctly before SPSS 13. It looks that I did not keep a copy of it (bad idea..) because of DATEDIF.
I would like to have it again to translate it to a Stata do file.

Does anybody keep it yet?

Thanks in advance

Marta GG (SUFKASP)

=====================
To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Richard Ristow
In reply to this post by Marta Garcia-Granero
Hi, Marta!

At 09:58 AM 12/5/2012, Marta García-Granero wrote:

>Since SPSS 13 I use(d) DATEDIF to compute age
>from two dates. Stata users seem to keep on using the old formula:
>int(StudyDate-DateOfBirth)/365.25 (since Stata
>stores dates as days, it is easier than the SPSS
>counterpart, that required CTIME.DAYS to convert seconds to days).
>
>I had a slightly improved version:
>
>INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)
>
>That avoided some errors, but not all of them.

Since you were using DATEDIFF, it sounds like
you're looking for the civil definition of 'age':
Age increases by one year at the beginning of the
birth date, each year. By that definition,
'years' aren't of uniform length, so the best
uniform-length formula (the one you have above) isn't perfect.

It's very difficult unless STATA can extract
calendar year, month, and day from a date in its
format -- but it probably can. Here's old-school
SPSS, which I *think* is right, and which should translate into STATA:

COMPUTE    AgeYears = XDATE.YEAR(StudyDate)-XDATE.YEAR(DateOfBirth).
DO IF   XDATE.MONTH(StudyDate) LT XDATE.MONTH(DateOfBirth).
.  COMPUTE AgeYears = AgeYears - 1.
ELSE IF XDATE.MONTH(StudyDate) EQ XDATE.MONTH(DateOfBirth).
.  IF   XDATE.MDAY(StudyDate)  LT XDATE.MDAY(DateOfBirth)
            AgeYears = AgeYears - 1.
END IF.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Art Kendall
In reply to this post by Marta Garcia-Granero
new file.
* this program compares different ways of finding the age on an admission date.
*note that cases  2, and 6 have the correct age when the first method is used.
data list list / birthdat(adate10)  admission(adate10) wanted (f3).
begin data.
  4/10/1931 4/10/2002 71
  4/10/1933 4/10/2002 69
  4/10/1932 4/7/2002   69
 4/10/1932 4/8/2002   69
 4/10/1932 4/9/2002   69
 4/10/1932 4/10/2002 70
 4/10/1932 4/11/2002 70
 4/10/1932 4/12/2002 70
 4/10/1932 4/13/2002 70
end data.
numeric age_recommended age_wizard age_by_365.25 age_jdate (f3).
* recommended method  see if birthday in current year has occurred yet.
* Rich Ristow posted a more concise way to do this method.
compute bmo = xdate.month(birthdat).
compute bdom = xdate.mday(birthdat).
compute byr =   xdate.year(birthdat).
compute amo = xdate.month(admission).
compute adom = xdate.mday(admission).
compute ayr =   xdate.year(admission).
compute nearbirt = date.mdy(bmo,bdom,ayr).
do if nearbirt le admission.
compute age_recommended = ayr-byr.
else if nearbirt gt admission.
compute age_recommended = ayr-byr-1.
end if.
formats nearbirt (adate10) age_recommended (f3).
* Date and Time Wizard: age_wizard.
COMPUTE age_wizard = DATEDIF(admission, birthdat, "years").
VARIABLE LABEL age_wizard "age using the wizard".
VARIABLE LEVEL age_wizard (SCALE).
FORMATS age_wizard (F5.0).
VARIABLE WIDTH age_wizard(5).
*method by dividing by average days in year.
COMPUTE age_by_365.25 = trunc(CTIME.DAYS(admission - birthdat)  / 365.25) .
*   jdate method  from earlier responder.
compute age_jdate = xdate.year(admission) - xdate.year(birthdat)
              - ( xdate.jdate(birthdat) gt xdate.jdate(admission) ).
compute age_jdate = xdate.year(admission) - xdate.year(birthdat)
              - ( xdate.jdate(birthdat) gt xdate.jdate(admission) ).
compute jadm = xdate.jdate(admission) .
compute jborn = xdate.jdate(birthdat) .
formats age_jdate jborn jadm(f3).
numeric line (f2).
compute case = $casenum.
list /variables = case admission birthdat wanted age_recommended
 age_wizard age_by_365.25 age_jdate.

Art Kendall
Social Research Consultants
On 12/5/2012 9:58 AM, Marta García-Granero wrote:
Hi:

This is the Stata User Formerly Known As an SPSS Macro Programmer (SUFKASP).

Since SPSS 13 I use(d) DATEDIF to compute age from two dates. Stata
users seem to keep on using the old formula:
int(StudyDate-DateOfBirth)/365.25 (since Stata stores dates as days, it
is easier than the SPSS counterpart, that required CTIME.DAYS to convert
seconds to days).

I recall that years ago we had an interesting thread concerning the
errors this method could cause in some cases. I had and slightly
improved version:

INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)

That avoided some errors, but not all of them.

There was a short syntax that computed ages correctly before SPSS 13. It
looks that I did not keep a copy of it (bad idea..) because of DATEDIF.
I would like to have it again to translate it to a Stata do file.

Does anybody keep it yet?

Thanks in advance

Marta GG (SUFKASP)

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD


===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD
Art Kendall
Social Research Consultants
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Bruce Weaver
Administrator
In reply to this post by Richard Ristow
Nice old-school code, Richard.  Back in the day, I bet people frequently stuck that in a macro.  E.g.,


DEFINE !GetCivilAge (AgeVar = !tokens(1) / Date1 = !tokens(1) / Date2 = !tokens(1))

COMPUTE !AgeVar = XDATE.YEAR(!Date2)-XDATE.YEAR(!Date1).
DO IF XDATE.MONTH(!Date2) LT XDATE.MONTH(!Date1).
.  COMPUTE !AgeVar = !AgeVar - 1.
ELSE IF XDATE.MONTH(!Date2) EQ XDATE.MONTH(!Date1).
.  IF XDATE.MDAY(!Date2)  LT XDATE.MDAY(!Date1)
      !AgeVar = !AgeVar - 1.
END IF.
EXECUTE.

!ENDDEFINE.

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

!GetCivilAge AgeVar = Age1 Date1 = DOB Date2 = StudyDate.

* Now compute civil age via DateDiff.
compute Age2 = DateDiff(StudyDate,DOB,"years").
formats Age1 Age2 (f5.0).
LIST.

OUTPUT:
 
        DOB   StudyDate  Age1  Age2
 
07-MAR-1960 06-MAR-2012    51    51
07-MAR-1960 07-MAR-2012    52    52
07-MAR-1960 08-MAR-2012    52    52
07-MAR-1960 06-DEC-2012    52    52

And to anticipate, the question, no, 7-Mar-1960 is not my DOB.  ;-)


Richard Ristow wrote
Hi, Marta!

At 09:58 AM 12/5/2012, Marta García-Granero wrote:

>Since SPSS 13 I use(d) DATEDIF to compute age
>from two dates. Stata users seem to keep on using the old formula:
>int(StudyDate-DateOfBirth)/365.25 (since Stata
>stores dates as days, it is easier than the SPSS
>counterpart, that required CTIME.DAYS to convert seconds to days).
>
>I had a slightly improved version:
>
>INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)
>
>That avoided some errors, but not all of them.

Since you were using DATEDIFF, it sounds like
you're looking for the civil definition of 'age':
Age increases by one year at the beginning of the
birth date, each year. By that definition,
'years' aren't of uniform length, so the best
uniform-length formula (the one you have above) isn't perfect.

It's very difficult unless STATA can extract
calendar year, month, and day from a date in its
format -- but it probably can. Here's old-school
SPSS, which I *think* is right, and which should translate into STATA:

COMPUTE    AgeYears = XDATE.YEAR(StudyDate)-XDATE.YEAR(DateOfBirth).
DO IF   XDATE.MONTH(StudyDate) LT XDATE.MONTH(DateOfBirth).
.  COMPUTE AgeYears = AgeYears - 1.
ELSE IF XDATE.MONTH(StudyDate) EQ XDATE.MONTH(DateOfBirth).
.  IF   XDATE.MDAY(StudyDate)  LT XDATE.MDAY(DateOfBirth)
            AgeYears = AgeYears - 1.
END IF.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
--
Bruce Weaver
bweaver@lakeheadu.ca
http://sites.google.com/a/lakeheadu.ca/bweaver/

"When all else fails, RTFM."

PLEASE NOTE THE FOLLOWING: 
1. My Hotmail account is not monitored regularly. To send me an e-mail, please use the address shown above.
2. The SPSSX Discussion forum on Nabble is no longer linked to the SPSSX-L listserv administered by UGA (https://listserv.uga.edu/).
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

David Marso
Administrator
Nice macro Bruce except I would pull the EXE from the macro.
This might also be one of the rare defensible uses of positional arguments.
Could also compact the logic as follows (untested)

DEFINE !GetCivilAge (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2).
IF XDATE.MONTH(!3) LT XDATE.MONTH(!2) !1= !1- 1.
IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2) AND XDATE.MDAY(!2)  LT XDATE.MDAY(!2) !1= !1- 1.
!ENDDEFINE.
!GetCivilAge Age1  DOB StudyDate.

Or to get uberweird (again untested):
DEFINE !GetCivilAge2 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2)
                   -(XDATE.MONTH(!3) LT XDATE.MONTH(!2))
                   -((XDATE.MONTH(!3) EQ XDATE.MONTH(!2)) AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
!ENDDEFINE.
!GetCivilAge2 Age1  DOB StudyDate.

==
Bruce Weaver wrote
Nice old-school code, Richard.  Back in the day, I bet people frequently stuck that in a macro.  E.g.,


DEFINE !GetCivilAge (AgeVar = !tokens(1) / Date1 = !tokens(1) / Date2 = !tokens(1))

COMPUTE !AgeVar = XDATE.YEAR(!Date2)-XDATE.YEAR(!Date1).
DO IF XDATE.MONTH(!Date2) LT XDATE.MONTH(!Date1).
.  COMPUTE !AgeVar = !AgeVar - 1.
ELSE IF XDATE.MONTH(!Date2) EQ XDATE.MONTH(!Date1).
.  IF XDATE.MDAY(!Date2)  LT XDATE.MDAY(!Date1)
      !AgeVar = !AgeVar - 1.
END IF.
EXECUTE.

!ENDDEFINE.

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

!GetCivilAge AgeVar = Age1 Date1 = DOB Date2 = StudyDate.

* Now compute civil age via DateDiff.
compute Age2 = DateDiff(StudyDate,DOB,"years").
formats Age1 Age2 (f5.0).
LIST.

OUTPUT:
 
        DOB   StudyDate  Age1  Age2
 
07-MAR-1960 06-MAR-2012    51    51
07-MAR-1960 07-MAR-2012    52    52
07-MAR-1960 08-MAR-2012    52    52
07-MAR-1960 06-DEC-2012    52    52

And to anticipate, the question, no, 7-Mar-1960 is not my DOB.  ;-)


Richard Ristow wrote
Hi, Marta!

At 09:58 AM 12/5/2012, Marta García-Granero wrote:

>Since SPSS 13 I use(d) DATEDIF to compute age
>from two dates. Stata users seem to keep on using the old formula:
>int(StudyDate-DateOfBirth)/365.25 (since Stata
>stores dates as days, it is easier than the SPSS
>counterpart, that required CTIME.DAYS to convert seconds to days).
>
>I had a slightly improved version:
>
>INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)
>
>That avoided some errors, but not all of them.

Since you were using DATEDIFF, it sounds like
you're looking for the civil definition of 'age':
Age increases by one year at the beginning of the
birth date, each year. By that definition,
'years' aren't of uniform length, so the best
uniform-length formula (the one you have above) isn't perfect.

It's very difficult unless STATA can extract
calendar year, month, and day from a date in its
format -- but it probably can. Here's old-school
SPSS, which I *think* is right, and which should translate into STATA:

COMPUTE    AgeYears = XDATE.YEAR(StudyDate)-XDATE.YEAR(DateOfBirth).
DO IF   XDATE.MONTH(StudyDate) LT XDATE.MONTH(DateOfBirth).
.  COMPUTE AgeYears = AgeYears - 1.
ELSE IF XDATE.MONTH(StudyDate) EQ XDATE.MONTH(DateOfBirth).
.  IF   XDATE.MDAY(StudyDate)  LT XDATE.MDAY(DateOfBirth)
            AgeYears = AgeYears - 1.
END IF.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
---
"Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis."
Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?"
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Bruce Weaver
Administrator
David, good idea to use positional arguments -- that makes the macro call simpler.  Something is going awry in your two untested modifications of it though.  Age0 below is from my original macro (using Richard's code, and modified to use positional arguments), Age1 and Age2 are from your two untested macros, and Age3 is computed using DateDiff.

Here's the output:

        DOB   StudyDate  Age0  Age1  Age2  Age3
 
07-MAR-1960 06-MAR-2012    51    52    52    51
07-MAR-1960 07-MAR-2012    52    52    52    52
07-MAR-1960 08-MAR-2012    52    52    52    52
07-MAR-1960 06-DEC-2012    52    52    52    52

And here's the syntax that generated it:

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

DEFINE !GetCivilAge (!POS = !tokens(1) / !POS = !tokens(1) / !POS = !tokens(1))

* Richard Ristow's old-school code from SPSSX-L: See the thread called
* "Old code to compute age from dates (was it Art Kendall's?)" .

COMPUTE !1 = XDATE.YEAR(!3)-XDATE.YEAR(!2).
DO IF XDATE.MONTH(!3) LT XDATE.MONTH(!2).
.  COMPUTE !1 = !1 - 1.
ELSE IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2).
.  IF XDATE.MDAY(!3)  LT XDATE.MDAY(!2)
      !1 = !1 - 1.
END IF.
!ENDDEFINE.


DEFINE !GetCivilAge1 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2).
IF XDATE.MONTH(!3) LT XDATE.MONTH(!2) !1= !1- 1.
IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2) AND XDATE.MDAY(!2)  LT XDATE.MDAY(!2) !1= !1- 1.
!ENDDEFINE.

DEFINE !GetCivilAge2 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2)
                   -(XDATE.MONTH(!3) LT XDATE.MONTH(!2))
                   -((XDATE.MONTH(!3) EQ XDATE.MONTH(!2)) AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
!ENDDEFINE.

!GetCivilAge  Age0  DOB StudyDate.
!GetCivilAge1 Age1  DOB StudyDate.
!GetCivilAge2 Age2  DOB StudyDate.
compute Age3 = DateDiff(StudyDate,DOB,"years").
formats Age0 Age1 Age2 Age3 (f5.0).
LIST.



David Marso wrote
Nice macro Bruce except I would pull the EXE from the macro.
This might also be one of the rare defensible uses of positional arguments.
Could also compact the logic as follows (untested)

DEFINE !GetCivilAge (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2).
IF XDATE.MONTH(!3) LT XDATE.MONTH(!2) !1= !1- 1.
IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2) AND XDATE.MDAY(!2)  LT XDATE.MDAY(!2) !1= !1- 1.
!ENDDEFINE.
!GetCivilAge Age1  DOB StudyDate.

Or to get uberweird (again untested):
DEFINE !GetCivilAge2 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2)
                   -(XDATE.MONTH(!3) LT XDATE.MONTH(!2))
                   -((XDATE.MONTH(!3) EQ XDATE.MONTH(!2)) AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
!ENDDEFINE.
!GetCivilAge2 Age1  DOB StudyDate.

==
Bruce Weaver wrote
Nice old-school code, Richard.  Back in the day, I bet people frequently stuck that in a macro.  E.g.,


DEFINE !GetCivilAge (AgeVar = !tokens(1) / Date1 = !tokens(1) / Date2 = !tokens(1))

COMPUTE !AgeVar = XDATE.YEAR(!Date2)-XDATE.YEAR(!Date1).
DO IF XDATE.MONTH(!Date2) LT XDATE.MONTH(!Date1).
.  COMPUTE !AgeVar = !AgeVar - 1.
ELSE IF XDATE.MONTH(!Date2) EQ XDATE.MONTH(!Date1).
.  IF XDATE.MDAY(!Date2)  LT XDATE.MDAY(!Date1)
      !AgeVar = !AgeVar - 1.
END IF.
EXECUTE.

!ENDDEFINE.

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

!GetCivilAge AgeVar = Age1 Date1 = DOB Date2 = StudyDate.

* Now compute civil age via DateDiff.
compute Age2 = DateDiff(StudyDate,DOB,"years").
formats Age1 Age2 (f5.0).
LIST.

OUTPUT:
 
        DOB   StudyDate  Age1  Age2
 
07-MAR-1960 06-MAR-2012    51    51
07-MAR-1960 07-MAR-2012    52    52
07-MAR-1960 08-MAR-2012    52    52
07-MAR-1960 06-DEC-2012    52    52

And to anticipate, the question, no, 7-Mar-1960 is not my DOB.  ;-)


Richard Ristow wrote
Hi, Marta!

At 09:58 AM 12/5/2012, Marta García-Granero wrote:

>Since SPSS 13 I use(d) DATEDIF to compute age
>from two dates. Stata users seem to keep on using the old formula:
>int(StudyDate-DateOfBirth)/365.25 (since Stata
>stores dates as days, it is easier than the SPSS
>counterpart, that required CTIME.DAYS to convert seconds to days).
>
>I had a slightly improved version:
>
>INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)
>
>That avoided some errors, but not all of them.

Since you were using DATEDIFF, it sounds like
you're looking for the civil definition of 'age':
Age increases by one year at the beginning of the
birth date, each year. By that definition,
'years' aren't of uniform length, so the best
uniform-length formula (the one you have above) isn't perfect.

It's very difficult unless STATA can extract
calendar year, month, and day from a date in its
format -- but it probably can. Here's old-school
SPSS, which I *think* is right, and which should translate into STATA:

COMPUTE    AgeYears = XDATE.YEAR(StudyDate)-XDATE.YEAR(DateOfBirth).
DO IF   XDATE.MONTH(StudyDate) LT XDATE.MONTH(DateOfBirth).
.  COMPUTE AgeYears = AgeYears - 1.
ELSE IF XDATE.MONTH(StudyDate) EQ XDATE.MONTH(DateOfBirth).
.  IF   XDATE.MDAY(StudyDate)  LT XDATE.MDAY(DateOfBirth)
            AgeYears = AgeYears - 1.
END IF.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
--
Bruce Weaver
bweaver@lakeheadu.ca
http://sites.google.com/a/lakeheadu.ca/bweaver/

"When all else fails, RTFM."

PLEASE NOTE THE FOLLOWING: 
1. My Hotmail account is not monitored regularly. To send me an e-mail, please use the address shown above.
2. The SPSSX Discussion forum on Nabble is no longer linked to the SPSSX-L listserv administered by UGA (https://listserv.uga.edu/).
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

David Marso
Administrator
Doh Brainfart:
AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
I Blame it on the cocktails!!! ;-)))
let's try ;-)
--
AND (XDATE.MDAY(!3)  LT XDATE.MDAY(!2))) .
-----
Here is another flavor using !POS which also communicates some semantic intent wrt what is what ;-)
--
DEFINE CivilAge (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)
                   -(XDATE.MONTH(!T) LT XDATE.MONTH(!H))
                   -((XDATE.MONTH(!T) EQ XDATE.MONTH(!H)) AND (XDATE.MDAY(!T)  LT XDATE.MDAY(!H))) .

!ENDDEFINE.

CivilAge age1 =(dob studydat).

Meanwhile, everyone including myself seems to have forgotten about our dear friend XDATE.JDAY
Drum Roll....
--
DEFINE CivilAg2 (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)-(XDATE.JDAY(!T) LT XDATE.JDAY(!H)).
!ENDDEFINE.

CivilAg2 age2 =(dob studydat).

        DOB    STUDYDAT     AGE1     AGE2

07-MAR-1960 06-MAR-2012    51.00    51.00
07-MAR-1960 07-MAR-2012    52.00    52.00
07-MAR-1960 08-MAR-2012    52.00    52.00
07-MAR-1960 06-DEC-2012    52.00    52.00


Number of cases read:  4    Number of cases listed:  4


Bruce Weaver wrote
David, good idea to use positional arguments -- that makes the macro call simpler.  Something is going awry in your two untested modifications of it though.  Age0 below is from my original macro (using Richard's code, and modified to use positional arguments), Age1 and Age2 are from your two untested macros, and Age3 is computed using DateDiff.

Here's the output:

        DOB   StudyDate  Age0  Age1  Age2  Age3
 
07-MAR-1960 06-MAR-2012    51    52    52    51
07-MAR-1960 07-MAR-2012    52    52    52    52
07-MAR-1960 08-MAR-2012    52    52    52    52
07-MAR-1960 06-DEC-2012    52    52    52    52

And here's the syntax that generated it:

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

DEFINE !GetCivilAge (!POS = !tokens(1) / !POS = !tokens(1) / !POS = !tokens(1))

* Richard Ristow's old-school code from SPSSX-L: See the thread called
* "Old code to compute age from dates (was it Art Kendall's?)" .

COMPUTE !1 = XDATE.YEAR(!3)-XDATE.YEAR(!2).
DO IF XDATE.MONTH(!3) LT XDATE.MONTH(!2).
.  COMPUTE !1 = !1 - 1.
ELSE IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2).
.  IF XDATE.MDAY(!3)  LT XDATE.MDAY(!2)
      !1 = !1 - 1.
END IF.
!ENDDEFINE.


DEFINE !GetCivilAge1 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2).
IF XDATE.MONTH(!3) LT XDATE.MONTH(!2) !1= !1- 1.
IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2) AND XDATE.MDAY(!2)  LT XDATE.MDAY(!2) !1= !1- 1.
!ENDDEFINE.

DEFINE !GetCivilAge2 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2)
                   -(XDATE.MONTH(!3) LT XDATE.MONTH(!2))
                   -((XDATE.MONTH(!3) EQ XDATE.MONTH(!2)) AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
!ENDDEFINE.

!GetCivilAge  Age0  DOB StudyDate.
!GetCivilAge1 Age1  DOB StudyDate.
!GetCivilAge2 Age2  DOB StudyDate.
compute Age3 = DateDiff(StudyDate,DOB,"years").
formats Age0 Age1 Age2 Age3 (f5.0).
LIST.



David Marso wrote
Nice macro Bruce except I would pull the EXE from the macro.
This might also be one of the rare defensible uses of positional arguments.
Could also compact the logic as follows (untested)

DEFINE !GetCivilAge (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2).
IF XDATE.MONTH(!3) LT XDATE.MONTH(!2) !1= !1- 1.
IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2) AND XDATE.MDAY(!2)  LT XDATE.MDAY(!2) !1= !1- 1.
!ENDDEFINE.
!GetCivilAge Age1  DOB StudyDate.

Or to get uberweird (again untested):
DEFINE !GetCivilAge2 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2)
                   -(XDATE.MONTH(!3) LT XDATE.MONTH(!2))
                   -((XDATE.MONTH(!3) EQ XDATE.MONTH(!2)) AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
!ENDDEFINE.
!GetCivilAge2 Age1  DOB StudyDate.

==
Bruce Weaver wrote
Nice old-school code, Richard.  Back in the day, I bet people frequently stuck that in a macro.  E.g.,


DEFINE !GetCivilAge (AgeVar = !tokens(1) / Date1 = !tokens(1) / Date2 = !tokens(1))

COMPUTE !AgeVar = XDATE.YEAR(!Date2)-XDATE.YEAR(!Date1).
DO IF XDATE.MONTH(!Date2) LT XDATE.MONTH(!Date1).
.  COMPUTE !AgeVar = !AgeVar - 1.
ELSE IF XDATE.MONTH(!Date2) EQ XDATE.MONTH(!Date1).
.  IF XDATE.MDAY(!Date2)  LT XDATE.MDAY(!Date1)
      !AgeVar = !AgeVar - 1.
END IF.
EXECUTE.

!ENDDEFINE.

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

!GetCivilAge AgeVar = Age1 Date1 = DOB Date2 = StudyDate.

* Now compute civil age via DateDiff.
compute Age2 = DateDiff(StudyDate,DOB,"years").
formats Age1 Age2 (f5.0).
LIST.

OUTPUT:
 
        DOB   StudyDate  Age1  Age2
 
07-MAR-1960 06-MAR-2012    51    51
07-MAR-1960 07-MAR-2012    52    52
07-MAR-1960 08-MAR-2012    52    52
07-MAR-1960 06-DEC-2012    52    52

And to anticipate, the question, no, 7-Mar-1960 is not my DOB.  ;-)


Richard Ristow wrote
Hi, Marta!

At 09:58 AM 12/5/2012, Marta García-Granero wrote:

>Since SPSS 13 I use(d) DATEDIF to compute age
>from two dates. Stata users seem to keep on using the old formula:
>int(StudyDate-DateOfBirth)/365.25 (since Stata
>stores dates as days, it is easier than the SPSS
>counterpart, that required CTIME.DAYS to convert seconds to days).
>
>I had a slightly improved version:
>
>INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)
>
>That avoided some errors, but not all of them.

Since you were using DATEDIFF, it sounds like
you're looking for the civil definition of 'age':
Age increases by one year at the beginning of the
birth date, each year. By that definition,
'years' aren't of uniform length, so the best
uniform-length formula (the one you have above) isn't perfect.

It's very difficult unless STATA can extract
calendar year, month, and day from a date in its
format -- but it probably can. Here's old-school
SPSS, which I *think* is right, and which should translate into STATA:

COMPUTE    AgeYears = XDATE.YEAR(StudyDate)-XDATE.YEAR(DateOfBirth).
DO IF   XDATE.MONTH(StudyDate) LT XDATE.MONTH(DateOfBirth).
.  COMPUTE AgeYears = AgeYears - 1.
ELSE IF XDATE.MONTH(StudyDate) EQ XDATE.MONTH(DateOfBirth).
.  IF   XDATE.MDAY(StudyDate)  LT XDATE.MDAY(DateOfBirth)
            AgeYears = AgeYears - 1.
END IF.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
---
"Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis."
Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?"
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Bruce Weaver
Administrator
Nice use of XDATE.JDAY, David!  From the FM (for those who can't be bothered to look it up):

XDATE.JDAY(datevalue). Numeric. Returns the day of the year (an integer between 1 and 366) from a numeric value that represents a date. The argument can be a number, a date format variable, or an expression that resolves to a date.

Getting back to the reason for Marta's original post (i.e., computing civil age in Stata), it looks like the "jtoe" function can be used to extract the day of the year in Stata.

  http://www.stata.com/products/stb/journals/stb14.pdf

;-)


David Marso wrote
Doh Brainfart:
AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
I Blame it on the cocktails!!! ;-)))
let's try ;-)
--
AND (XDATE.MDAY(!3)  LT XDATE.MDAY(!2))) .
-----
Here is another flavor using !POS which also communicates some semantic intent wrt what is what ;-)
--
DEFINE CivilAge (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)
                   -(XDATE.MONTH(!T) LT XDATE.MONTH(!H))
                   -((XDATE.MONTH(!T) EQ XDATE.MONTH(!H)) AND (XDATE.MDAY(!T)  LT XDATE.MDAY(!H))) .

!ENDDEFINE.

CivilAge age1 =(dob studydat).

Meanwhile, everyone including myself seems to have forgotten about our dear friend XDATE.JDAY
Drum Roll....
--
DEFINE CivilAg2 (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)-(XDATE.JDAY(!T) LT XDATE.JDAY(!H)).
!ENDDEFINE.

CivilAg2 age2 =(dob studydat).

        DOB    STUDYDAT     AGE1     AGE2

07-MAR-1960 06-MAR-2012    51.00    51.00
07-MAR-1960 07-MAR-2012    52.00    52.00
07-MAR-1960 08-MAR-2012    52.00    52.00
07-MAR-1960 06-DEC-2012    52.00    52.00


Number of cases read:  4    Number of cases listed:  4


Bruce Weaver wrote
David, good idea to use positional arguments -- that makes the macro call simpler.  Something is going awry in your two untested modifications of it though.  Age0 below is from my original macro (using Richard's code, and modified to use positional arguments), Age1 and Age2 are from your two untested macros, and Age3 is computed using DateDiff.

Here's the output:

        DOB   StudyDate  Age0  Age1  Age2  Age3
 
07-MAR-1960 06-MAR-2012    51    52    52    51
07-MAR-1960 07-MAR-2012    52    52    52    52
07-MAR-1960 08-MAR-2012    52    52    52    52
07-MAR-1960 06-DEC-2012    52    52    52    52

And here's the syntax that generated it:

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

DEFINE !GetCivilAge (!POS = !tokens(1) / !POS = !tokens(1) / !POS = !tokens(1))

* Richard Ristow's old-school code from SPSSX-L: See the thread called
* "Old code to compute age from dates (was it Art Kendall's?)" .

COMPUTE !1 = XDATE.YEAR(!3)-XDATE.YEAR(!2).
DO IF XDATE.MONTH(!3) LT XDATE.MONTH(!2).
.  COMPUTE !1 = !1 - 1.
ELSE IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2).
.  IF XDATE.MDAY(!3)  LT XDATE.MDAY(!2)
      !1 = !1 - 1.
END IF.
!ENDDEFINE.


DEFINE !GetCivilAge1 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2).
IF XDATE.MONTH(!3) LT XDATE.MONTH(!2) !1= !1- 1.
IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2) AND XDATE.MDAY(!2)  LT XDATE.MDAY(!2) !1= !1- 1.
!ENDDEFINE.

DEFINE !GetCivilAge2 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2)
                   -(XDATE.MONTH(!3) LT XDATE.MONTH(!2))
                   -((XDATE.MONTH(!3) EQ XDATE.MONTH(!2)) AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
!ENDDEFINE.

!GetCivilAge  Age0  DOB StudyDate.
!GetCivilAge1 Age1  DOB StudyDate.
!GetCivilAge2 Age2  DOB StudyDate.
compute Age3 = DateDiff(StudyDate,DOB,"years").
formats Age0 Age1 Age2 Age3 (f5.0).
LIST.



David Marso wrote
Nice macro Bruce except I would pull the EXE from the macro.
This might also be one of the rare defensible uses of positional arguments.
Could also compact the logic as follows (untested)

DEFINE !GetCivilAge (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2).
IF XDATE.MONTH(!3) LT XDATE.MONTH(!2) !1= !1- 1.
IF XDATE.MONTH(!3) EQ XDATE.MONTH(!2) AND XDATE.MDAY(!2)  LT XDATE.MDAY(!2) !1= !1- 1.
!ENDDEFINE.
!GetCivilAge Age1  DOB StudyDate.

Or to get uberweird (again untested):
DEFINE !GetCivilAge2 (!POS= !tokens(1) / !POS= !tokens(1) / !POS= !tokens(1))
COMPUTE !1= XDATE.YEAR(!3)-XDATE.YEAR(!2)
                   -(XDATE.MONTH(!3) LT XDATE.MONTH(!2))
                   -((XDATE.MONTH(!3) EQ XDATE.MONTH(!2)) AND (XDATE.MDAY(!2)  LT XDATE.MDAY(!2))) .
!ENDDEFINE.
!GetCivilAge2 Age1  DOB StudyDate.

==
Bruce Weaver wrote
Nice old-school code, Richard.  Back in the day, I bet people frequently stuck that in a macro.  E.g.,


DEFINE !GetCivilAge (AgeVar = !tokens(1) / Date1 = !tokens(1) / Date2 = !tokens(1))

COMPUTE !AgeVar = XDATE.YEAR(!Date2)-XDATE.YEAR(!Date1).
DO IF XDATE.MONTH(!Date2) LT XDATE.MONTH(!Date1).
.  COMPUTE !AgeVar = !AgeVar - 1.
ELSE IF XDATE.MONTH(!Date2) EQ XDATE.MONTH(!Date1).
.  IF XDATE.MDAY(!Date2)  LT XDATE.MDAY(!Date1)
      !AgeVar = !AgeVar - 1.
END IF.
EXECUTE.

!ENDDEFINE.

data list list / DOB StudyDate (2date11).
begin data
7-Mar-1960 6-Mar-2012
7-Mar-1960 7-Mar-2012
7-Mar-1960 8-Mar-2012
7-Mar-1960 6-Dec-2012
end data.

!GetCivilAge AgeVar = Age1 Date1 = DOB Date2 = StudyDate.

* Now compute civil age via DateDiff.
compute Age2 = DateDiff(StudyDate,DOB,"years").
formats Age1 Age2 (f5.0).
LIST.

OUTPUT:
 
        DOB   StudyDate  Age1  Age2
 
07-MAR-1960 06-MAR-2012    51    51
07-MAR-1960 07-MAR-2012    52    52
07-MAR-1960 08-MAR-2012    52    52
07-MAR-1960 06-DEC-2012    52    52

And to anticipate, the question, no, 7-Mar-1960 is not my DOB.  ;-)


Richard Ristow wrote
Hi, Marta!

At 09:58 AM 12/5/2012, Marta García-Granero wrote:

>Since SPSS 13 I use(d) DATEDIF to compute age
>from two dates. Stata users seem to keep on using the old formula:
>int(StudyDate-DateOfBirth)/365.25 (since Stata
>stores dates as days, it is easier than the SPSS
>counterpart, that required CTIME.DAYS to convert seconds to days).
>
>I had a slightly improved version:
>
>INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)
>
>That avoided some errors, but not all of them.

Since you were using DATEDIFF, it sounds like
you're looking for the civil definition of 'age':
Age increases by one year at the beginning of the
birth date, each year. By that definition,
'years' aren't of uniform length, so the best
uniform-length formula (the one you have above) isn't perfect.

It's very difficult unless STATA can extract
calendar year, month, and day from a date in its
format -- but it probably can. Here's old-school
SPSS, which I *think* is right, and which should translate into STATA:

COMPUTE    AgeYears = XDATE.YEAR(StudyDate)-XDATE.YEAR(DateOfBirth).
DO IF   XDATE.MONTH(StudyDate) LT XDATE.MONTH(DateOfBirth).
.  COMPUTE AgeYears = AgeYears - 1.
ELSE IF XDATE.MONTH(StudyDate) EQ XDATE.MONTH(DateOfBirth).
.  IF   XDATE.MDAY(StudyDate)  LT XDATE.MDAY(DateOfBirth)
            AgeYears = AgeYears - 1.
END IF.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
--
Bruce Weaver
bweaver@lakeheadu.ca
http://sites.google.com/a/lakeheadu.ca/bweaver/

"When all else fails, RTFM."

PLEASE NOTE THE FOLLOWING: 
1. My Hotmail account is not monitored regularly. To send me an e-mail, please use the address shown above.
2. The SPSSX Discussion forum on Nabble is no longer linked to the SPSSX-L listserv administered by UGA (https://listserv.uga.edu/).
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Richard Ristow
In reply to this post by David Marso
At 09:35 AM 12/7/2012, David Marso wrote:

>Everyone including myself seems to have forgotten about our dear
>friend XDATE.JDAY:
>--
>DEFINE CivilAg2 (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
>!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
>COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)-(XDATE.JDAY(!T) LT
>XDATE.JDAY(!H)).
>!ENDDEFINE.

Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

David Marso
Administrator
Oh CRAP!
OTOH: CEFGW except for the LCB
--
"Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years."
Richard Ristow wrote
At 09:35 AM 12/7/2012, David Marso wrote:

>Everyone including myself seems to have forgotten about our dear
>friend XDATE.JDAY:
>--
>DEFINE CivilAg2 (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
>!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
>COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)-(XDATE.JDAY(!T) LT
>XDATE.JDAY(!H)).
>!ENDDEFINE.

Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
---
"Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis."
Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?"
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Richard Ristow
At 03:24 PM 12/7/2012, David Marso wrote:

>Oh CRAP!
>OTOH: CEFGW except for the LCB

All right, I'll bite -- could you expand "CEFGW" and "LCB"? (I'm not
aware of any FM (or AM, or NetRadio) I could consult for the information.)

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Art Kendall
In reply to this post by David Marso
 the example syntax I posted showed that the different methods gave different results.

To see the problem with the jdate approach eyeball the variable called "wanted" and the variable called "age_jdate" for  case #6

Art Kendall
Social Research Consultants
On 12/7/2012 3:24 PM, David Marso wrote:
Oh CRAP!
OTOH: CEFGW except for the LCB
--
"Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years."

Richard Ristow wrote
At 09:35 AM 12/7/2012, David Marso wrote:

Everyone including myself seems to have forgotten about our dear
friend XDATE.JDAY:
--
DEFINE CivilAg2 (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)-(XDATE.JDAY(!T) LT
XDATE.JDAY(!H)).
!ENDDEFINE.
Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years.

=====================
To manage your subscription to SPSSX-L, send a message to

      
[hidden email]

      
 (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD




-----
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
--
View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Old-code-to-compute-age-from-dates-was-it-Art-Kendall-s-tp5716678p5716778.html
Sent from the SPSSX Discussion mailing list archive at Nabble.com.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD


===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD
Art Kendall
Social Research Consultants
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

David Marso
Administrator
In reply to this post by Richard Ristow
CEFGW =Close enough for government work.
LCB = Liquor control board ;=)

Richard Ristow wrote
At 03:24 PM 12/7/2012, David Marso wrote:

>Oh CRAP!
>OTOH: CEFGW except for the LCB

All right, I'll bite -- could you expand "CEFGW" and "LCB"? (I'm not
aware of any FM (or AM, or NetRadio) I could consult for the information.)

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
---
"Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis."
Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?"
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Art Kendall
In reply to this post by Art Kendall
this is a hopefully more readable version of the comparison of age calculation methods.

I first cobbled the syntax for the comparison of age finding methods before datediff was available.
I only had age_recommended age_wizard age_by_365.25 age_jdate in the original.

Can anybody come up with data examples of
 birthdate admission and wanted
 age that get wrong ages from datediff?
I thought there were problems using datediff but cannot think of my off the top of my head.
If the datediff function has had any changes between versions I am running SPSS 21 64-bit.

new file.
* this program compares different ways of finding the age on an admission date.
* note which cases  have the computed age the same as the wanted age.
* wanted ages were found by mental math you may want to try a few more pairs of dates.
* Rich Ristow noted birthdays based on jdate from March on will be off during leap years.
data list list / Birthdate(adate10)  admission(adate10) wanted (f3).
begin data.
   4/10/1931 4/10/2002 71
   4/10/1933 4/10/2002 69
   4/10/1932 4/07/2002 69
   4/10/1932 4/08/2002 69
   4/10/1932 4/09/2002 69
   4/10/1932 4/10/2002 70
   4/10/1932 4/11/2002 70
   4/10/1932 4/12/2002 70
   4/10/1932 4/13/2002 70
   3/01/1932 3/01/2003 71
   3/01/1932 3/01/2004 72
   3/01/1933 3/01/2003 70
   3/01/1933 3/01/2004 71
   3/01/1933 2/29/2004 70
end data.
numeric age_recommended age_datediff age_by_365.25 age_jdate (f3).
* recommended method is to  see if birthday in current year has occurred yet.
*.
compute Birth_month        = xdate.month(Birthdate).
compute Birth_day_of_month = xdate.mday(Birthdate).
compute Birth_year         = xdate.year(Birthdate).
compute Admit_month        = xdate.month(admission).
compute Admit_day_of_month = xdate.mday(admission).
compute Admit_year         = xdate.year(admission).
*-----.
*recommended method of computing age.
*note the presence of Admit_year in the next statement.
compute admit_year_birthday = date.mdy(Birth_month,Birth_day_of_month,Admit_year).
do if admit_year_birthday le admission.
   compute age_recommended = Admit_year - Birth_year.
else if admit_year_birthday gt admission.
   compute age_recommended = Admit_year - Birth_year - 1.
end if.
formats admit_year_birthday (adate10) age_recommended (f3).
*------.
* method using  datediff: age_datediff.
COMPUTE age_datediff = DATEDIF(admission, Birthdate, "years").
VARIABLE LABEL age_datediff "age using the datediff function".
FORMATS age_datediff (F3).
*------.
*method by dividing elapsed days by average days in year.
COMPUTE age_by_365.25 = trunc(CTIME.DAYS(admission - Birthdate)  / 365.25) .
*   jdate method  from earlier responder.
compute age_jdate = xdate.year(admission) - xdate.year(Birthdate)
   - ( xdate.jdate(Birthdate) gt xdate.jdate(admission) ).
compute jdate_admission = xdate.jdate(admission) .
compute jdate_born = xdate.jdate(Birthdate) .
formats age_jdate jdate_born jdate_admission(f3).
numeric case(f2).
compute case = $casenum.
list /variables = case  Birthdate admission wanted age_recommended
   age_datediff age_by_365.25 age_jdate.


Art Kendall
Social Research Consultants
On 12/7/2012 4:14 PM, Art Kendall wrote:
 the example syntax I posted showed that the different methods gave different results.

To see the problem with the jdate approach eyeball the variable called "wanted" and the variable called "age_jdate" for  case #6

Art Kendall
Social Research Consultants
On 12/7/2012 3:24 PM, David Marso wrote:
Oh CRAP!
OTOH: CEFGW except for the LCB
--
"Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years."

Richard Ristow wrote
At 09:35 AM 12/7/2012, David Marso wrote:

Everyone including myself seems to have forgotten about our dear
friend XDATE.JDAY:
--
DEFINE CivilAg2 (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)-(XDATE.JDAY(!T) LT
XDATE.JDAY(!H)).
!ENDDEFINE.
Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email]
 (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD



-----
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
--
View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Old-code-to-compute-age-from-dates-was-it-Art-Kendall-s-tp5716678p5716778.html
Sent from the SPSSX Discussion mailing list archive at Nabble.com.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD


===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD
Art Kendall
Social Research Consultants
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Salbod
In reply to this post by David Marso
CRAP?

-----Original Message-----
From: SPSSX(r) Discussion [mailto:[hidden email]] On Behalf Of David Marso
Sent: Friday, December 07, 2012 6:23 PM
To: [hidden email]
Subject: Re: Old code to compute age from dates (was it Art Kendall's?)

CEFGW =Close enough for government work.
LCB = Liquor control board ;=)


Richard Ristow wrote

> At 03:24 PM 12/7/2012, David Marso wrote:
>
>>Oh CRAP!
>>OTOH: CEFGW except for the LCB
>
> All right, I'll bite -- could you expand "CEFGW" and "LCB"? (I'm not
> aware of any FM (or AM, or NetRadio) I could consult for the
> information.)
>
> =====================
> To manage your subscription to SPSSX-L, send a message to

> LISTSERV@.UGA

>  (not to SPSSX-L), with no body text except the command. To leave the
> list, send the command SIGNOFF SPSSX-L For a list of commands to
> manage subscriptions, send the command INFO REFCARD





-----
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
--
View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Old-code-to-compute-age-from-dates-was-it-Art-Kendall-s-tp5716678p5716787.html
Sent from the SPSSX Discussion mailing list archive at Nabble.com.

=====================
To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Art Kendall
In reply to this post by Art Kendall
to wrap this up.  the 'recommended method' works as a way to translate to other software/languages.

If I did this correctly, the datediff method matches my old recommended method.
input program.
   loop year = 1899 to 2059 by 1.
      compute bornmar1 = date.mdy(3,1,year).
      compute admitbefore  = date.mdy(2,28,year+1).
      compute admitonafter = date.mdy(3, 1,year+1).
      compute jdate_born = xdate.jdate(bornmar1).
      compute jdate_admitonafter = xdate.jdate(admitonafter).
      *-----.
      *recommended age is 1 if birthday on after admit else 0 .
      COMPUTE age_datediffbefore = DATEDIFf(admitbefore, bornmar1, "years").
      COMPUTE age_datediffonafter = DATEDIFf(admitonafter, bornmar1, "years").
      do if age_datediffbefore ne 0 or age_datediffonafter ne 1.
         print / year age_datediffbefore age_datediffonafter.
      end if.
      end case.
   end loop.
   end file.
end input program.
execute.

Art Kendall
Social Research Consultants
On 12/8/2012 8:39 AM, Art Kendall wrote:
this is a hopefully more readable version of the comparison of age calculation methods.

I first cobbled the syntax for the comparison of age finding methods before datediff was available.
I only had age_recommended age_wizard age_by_365.25 age_jdate in the original.

Can anybody come up with data examples of
 birthdate admission and wanted
 age that get wrong ages from datediff?
I thought there were problems using datediff but cannot think of my off the top of my head.
If the datediff function has had any changes between versions I am running SPSS 21 64-bit.

new file.
* this program compares different ways of finding the age on an admission date.
* note which cases  have the computed age the same as the wanted age.
* wanted ages were found by mental math you may want to try a few more pairs of dates.
* Rich Ristow noted birthdays based on jdate from March on will be off during leap years.
data list list / Birthdate(adate10)  admission(adate10) wanted (f3).
begin data.
   4/10/1931 4/10/2002 71
   4/10/1933 4/10/2002 69
   4/10/1932 4/07/2002 69
   4/10/1932 4/08/2002 69
   4/10/1932 4/09/2002 69
   4/10/1932 4/10/2002 70
   4/10/1932 4/11/2002 70
   4/10/1932 4/12/2002 70
   4/10/1932 4/13/2002 70
   3/01/1932 3/01/2003 71
   3/01/1932 3/01/2004 72
   3/01/1933 3/01/2003 70
   3/01/1933 3/01/2004 71
   3/01/1933 2/29/2004 70
end data.
numeric age_recommended age_datediff age_by_365.25 age_jdate (f3).
* recommended method is to  see if birthday in current year has occurred yet.
*.
compute Birth_month        = xdate.month(Birthdate).
compute Birth_day_of_month = xdate.mday(Birthdate).
compute Birth_year         = xdate.year(Birthdate).
compute Admit_month        = xdate.month(admission).
compute Admit_day_of_month = xdate.mday(admission).
compute Admit_year         = xdate.year(admission).
*-----.
*recommended method of computing age.
*note the presence of Admit_year in the next statement.
compute admit_year_birthday = date.mdy(Birth_month,Birth_day_of_month,Admit_year).
do if admit_year_birthday le admission.
   compute age_recommended = Admit_year - Birth_year.
else if admit_year_birthday gt admission.
   compute age_recommended = Admit_year - Birth_year - 1.
end if.
formats admit_year_birthday (adate10) age_recommended (f3).
*------.
* method using  datediff: age_datediff.
COMPUTE age_datediff = DATEDIF(admission, Birthdate, "years").
VARIABLE LABEL age_datediff "age using the datediff function".
FORMATS age_datediff (F3).
*------.
*method by dividing elapsed days by average days in year.
COMPUTE age_by_365.25 = trunc(CTIME.DAYS(admission - Birthdate)  / 365.25) .
*   jdate method  from earlier responder.
compute age_jdate = xdate.year(admission) - xdate.year(Birthdate)
   - ( xdate.jdate(Birthdate) gt xdate.jdate(admission) ).
compute jdate_admission = xdate.jdate(admission) .
compute jdate_born = xdate.jdate(Birthdate) .
formats age_jdate jdate_born jdate_admission(f3).
numeric case(f2).
compute case = $casenum.
list /variables = case  Birthdate admission wanted age_recommended
   age_datediff age_by_365.25 age_jdate.


Art Kendall
Social Research Consultants
On 12/7/2012 4:14 PM, Art Kendall wrote:
 the example syntax I posted showed that the different methods gave different results.

To see the problem with the jdate approach eyeball the variable called "wanted" and the variable called "age_jdate" for  case #6

Art Kendall
Social Research Consultants
On 12/7/2012 3:24 PM, David Marso wrote:
Oh CRAP!
OTOH: CEFGW except for the LCB
--
"Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years."

Richard Ristow wrote
At 09:35 AM 12/7/2012, David Marso wrote:

Everyone including myself seems to have forgotten about our dear
friend XDATE.JDAY:
--
DEFINE CivilAg2 (!POS= !Charend("=") / !POS= !ENCLOSE("(",")")).
!LET !H=!HEAD(!2) !LET !T=!TAIL(!2)
COMPUTE !1= XDATE.YEAR(!T)-XDATE.YEAR(!H)-(XDATE.JDAY(!T) LT
XDATE.JDAY(!H)).
!ENDDEFINE.
Actually, that one was proposed. It's a good solution, with one small
glitch: if the birthdate is in March or later, the JDAY of the
birthdate will differ by one day between leap years and non-leap years.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email]
 (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD


-----
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
--
View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Old-code-to-compute-age-from-dates-was-it-Art-Kendall-s-tp5716678p5716778.html
Sent from the SPSSX Discussion mailing list archive at Nabble.com.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD


===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD
Art Kendall
Social Research Consultants
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

David Marso
Administrator
In reply to this post by Salbod

I tried to come up with something clever...
Coulda Read Art's Post ;-))
--
Salbod wrote
CRAP?

-----Original Message-----
From: SPSSX(r) Discussion [mailto:[hidden email]] On Behalf Of David Marso
Sent: Friday, December 07, 2012 6:23 PM
To: [hidden email]
Subject: Re: Old code to compute age from dates (was it Art Kendall's?)

CEFGW =Close enough for government work.
LCB = Liquor control board ;=)


Richard Ristow wrote
> At 03:24 PM 12/7/2012, David Marso wrote:
>
>>Oh CRAP!
>>OTOH: CEFGW except for the LCB
>
> All right, I'll bite -- could you expand "CEFGW" and "LCB"? (I'm not
> aware of any FM (or AM, or NetRadio) I could consult for the
> information.)
>
> =====================
> To manage your subscription to SPSSX-L, send a message to

> LISTSERV@.UGA

>  (not to SPSSX-L), with no body text except the command. To leave the
> list, send the command SIGNOFF SPSSX-L For a list of commands to
> manage subscriptions, send the command INFO REFCARD





-----
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
--
View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Old-code-to-compute-age-from-dates-was-it-Art-Kendall-s-tp5716678p5716787.html
Sent from the SPSSX Discussion mailing list archive at Nabble.com.

=====================
To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me.
---
"Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis."
Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?"
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Roberts, Michael-2
In reply to this post by Marta Garcia-Granero
Not sure whether this is what you wanted, but it is old and I believe by RRistow.

/* Calculate age (in years and fraction of years) on June 30,2000.*/
COMPUTE age=CTIME.DAYS(DATE.DMY(30,6,2000)-dob)/365.25.
EXECUTE.

Data were in the following format:

1940-10-09 2000-10-09 1980-01-07 2000-10-10
1952-10-01 2000-10-09 1980-01-07 2000-10-10

Or alternatively:

COMPUTE Age=DATEDIFF($TIME, BirthDate, 'years'). (not sure who the author was on this one! Sorry!)

Hope it helps.

Mike




-----Original Message-----
From: SPSSX(r) Discussion [mailto:[hidden email]] On Behalf Of Marta García-Granero
Sent: Wednesday, December 05, 2012 9:59 AM
To: [hidden email]
Subject: Old code to compute age from dates (was it Art Kendall's?)

Hi:

This is the Stata User Formerly Known As an SPSS Macro Programmer (SUFKASP).

Since SPSS 13 I use(d) DATEDIF to compute age from two dates. Stata users seem to keep on using the old formula:
int(StudyDate-DateOfBirth)/365.25 (since Stata stores dates as days, it is easier than the SPSS counterpart, that required CTIME.DAYS to convert seconds to days).

I recall that years ago we had an interesting thread concerning the errors this method could cause in some cases. I had and slightly improved version:

INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)

That avoided some errors, but not all of them.

There was a short syntax that computed ages correctly before SPSS 13. It looks that I did not keep a copy of it (bad idea..) because of DATEDIF.
I would like to have it again to translate it to a Stata do file.

Does anybody keep it yet?

Thanks in advance

Marta GG (SUFKASP)

=====================
To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Old code to compute age from dates (was it Art Kendall's?)

Bruce Weaver
Administrator
Michael, you must have missed Richard's post earlier in this thread where he gave this method:

COMPUTE    AgeYears = XDATE.YEAR(StudyDate)-XDATE.YEAR(DateOfBirth).
DO IF   XDATE.MONTH(StudyDate) LT XDATE.MONTH(DateOfBirth).
.  COMPUTE AgeYears = AgeYears - 1.
ELSE IF XDATE.MONTH(StudyDate) EQ XDATE.MONTH(DateOfBirth).
.  IF   XDATE.MDAY(StudyDate)  LT XDATE.MDAY(DateOfBirth)
            AgeYears = AgeYears - 1.
END IF.

There were several other posts after that.  You can see the entire thread here:

http://spssx-discussion.1045642.n5.nabble.com/Old-code-to-compute-age-from-dates-was-it-Art-Kendall-s-td5716678.html

Notice Adrian's point about dividing by 365.2425 rather than 365.25 (if one is taking that approach):

(1) the correct number of days in the average year, to account for leap years, is 365.2425, not 365.25.  There are in fact fewer than one leap year every four years, because there are exceptions applied to century years such as 2000.  Using 365.25 for the number of days in a year is the system used in the superseded Julian calendar, whereas the Gregorian calendar we now use employs 365.2425.

HTH.


Roberts, Michael-2 wrote
Not sure whether this is what you wanted, but it is old and I believe by RRistow.

/* Calculate age (in years and fraction of years) on June 30,2000.*/
COMPUTE age=CTIME.DAYS(DATE.DMY(30,6,2000)-dob)/365.25.
EXECUTE.

Data were in the following format:

1940-10-09 2000-10-09 1980-01-07 2000-10-10
1952-10-01 2000-10-09 1980-01-07 2000-10-10

Or alternatively:

COMPUTE Age=DATEDIFF($TIME, BirthDate, 'years'). (not sure who the author was on this one! Sorry!)

Hope it helps.

Mike




-----Original Message-----
From: SPSSX(r) Discussion [mailto:[hidden email]] On Behalf Of Marta García-Granero
Sent: Wednesday, December 05, 2012 9:59 AM
To: [hidden email]
Subject: Old code to compute age from dates (was it Art Kendall's?)

Hi:

This is the Stata User Formerly Known As an SPSS Macro Programmer (SUFKASP).

Since SPSS 13 I use(d) DATEDIF to compute age from two dates. Stata users seem to keep on using the old formula:
int(StudyDate-DateOfBirth)/365.25 (since Stata stores dates as days, it is easier than the SPSS counterpart, that required CTIME.DAYS to convert seconds to days).

I recall that years ago we had an interesting thread concerning the errors this method could cause in some cases. I had and slightly improved version:

INT(CTIME.DAYS(1+StudyDate-DateOfBirth)/365.25)

That avoided some errors, but not all of them.

There was a short syntax that computed ages correctly before SPSS 13. It looks that I did not keep a copy of it (bad idea..) because of DATEDIF.
I would like to have it again to translate it to a Stata do file.

Does anybody keep it yet?

Thanks in advance

Marta GG (SUFKASP)

=====================
To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
--
Bruce Weaver
bweaver@lakeheadu.ca
http://sites.google.com/a/lakeheadu.ca/bweaver/

"When all else fails, RTFM."

PLEASE NOTE THE FOLLOWING: 
1. My Hotmail account is not monitored regularly. To send me an e-mail, please use the address shown above.
2. The SPSSX Discussion forum on Nabble is no longer linked to the SPSSX-L listserv administered by UGA (https://listserv.uga.edu/).
12