Date: Fri, 1 Aug 2003 17:42:25 -0400
Reply-To: Richard Ristow <email@example.com>
Sender: "SPSSX(r) Discussion" <SPSSX-L@LISTSERV.UGA.EDU>
From: Richard Ristow <firstname.lastname@example.org>
Subject: Re: working with dates
Content-Type: text/plain; charset="iso-8859-1"; format=flowed
At 04:29 PM 8/1/2003 +0000, Dagmar Amtmann wrote:
>This is a really basic question. [...] I need to figure out how many
>years, months, and days elapsed between two dates. When I use the
>compute command the output provides numbers, but I can't figure out
>how to make them into something interpretable, such as months or
>years. Thanks for your help. Dagmar
It's a basic question, but it comes up often, and there are some
subtleties to the answer. The problem is that a 'day' is a defined unit
of time(*), but 'year' and 'month' are not. (Months vary much more than
years, of course: from 28 to 31 days, rather than from 365 to 366 days.)
Here, I assume
1. The beginning and ending date are variables STRT_DT and END_DT respectively
2. Both are SPSS date variables, created with the SPSS functions
provided for the purpose (*not* including YRMODA, which creates an
older, now-obsolete form).
A. DAYS between two dates is unambiguous:
. COMPUTE DYS_BTWN = CTIME.DAYS(END_DT-STRT_DT).
B. For many purposes, approximate, uniform-length years or months will do:
. COMPUTE YRS_BTWN = DYS_BTWN/365.25.
. COMPUTE MTH_BTWN = DYS_BTWN/30.5. /* 30.44 is closer */
(Of course, you can substitute the CTIME.DAYS expression from A. for
"DYS_BTWN", and save using an extra variable.)
C. For CALENDAR years, months, and days in an interval, you have to use
calendar-date functions. Logic has been posted a number of times on
this list; see, for example, "Small off-topic (or not?): What strategy
is better?", by Marta Garcia-Granero (Asesoría Bioestadística
<bioestadistica@ERESMAS.NET>), Wed, 30 Jul 2003 12:58:28 +0200.
Here's another style. (I'm modifying my own code, from posting "Re:
Calculating age to given calendar date", Wed, 25 Jun 2003 14:21:55 -0400.)
CAREFUL: Calculation of years and months in the interval is pretty
straightforward. Calculation of days is obscure, and a little arbitrary. It is
+ the difference between the starting and ending day-of-month, IF that
is zero or positive;
+ otherwise, the days between the ending date, and the starting
day-of-month in the month preceding the ending date. (I.e., add 28, 29,
30, or 31 to the negative number of days calculated above, depending on
what month the ending date falls in.)
WARNING: I don't think this code will work if the ending date is
actually earlier than the starting date. Make sure that's impossible,
or check it.
/* First, calculate RAW years, months, and days, ignoring */
/* whether the ending date is earlier in the year, or the */
/* month, than the starting date */
. COMPUTE YRS_BTWN = XDATE.YEAR(END_DT) - XDATE.YEAR(STRT_DT).
. COMPUTE MTH_BTWN = XDATE.MONTH(END_DT) - XDATE.MONTH(STRT_DT).
. COMPUTE DYS_BTWN = XDATE.MDAY(END_DT) - XDATE.MDAY(STRT_DT).
/* Second, correct "months" and "days" in interval, if */
/* starting day-of-month is less than ending day-of-month. */
/* (See earlier note on "days" calculation.) */
. DO IF (DYS_BTWN < 0).
. COMPUTE MTH_BTWN = MTH_BTWN - 1.
/* Here's the "days" code -- the most obscure part */
. COMPUTE #END_YR = XDATE.YEAR(END_DT).
. COMPUTE #END_MO = XDATE.MONTH(END_DT).
. COMPUTE #STRT_MD = XDATE.MDAY(STRT_DT).
. DO IF (#END_MO > 1).
. COMPUTE #BACK1MO = DATE.DMY(#STRT_MD,#END_MO-1, #END_YR).
. COMPUTE #BACK1MO = DATE.DMY(#STRT_MD,#END_MO+11,#END_YR-1).
. END IF.
. COMPUTE DYS_BTWN = CDATE.DAYS(END_DT - #BACK1MO).
. END IF.
/* Third, correct "months" and "years" in interval, if */
/* ending day is earlier in year than starting day. */
/* Because of the previous correction, the "months" */
/* in interval will be negative if */
/* . The ending month is earlier in the year than than the */
/* starting month, OR */
/* . The two months are the same, and the ending day is */
/* earlier in the month than the starting day. */
. DO IF (MTH_BTWN < 0).
. COMPUTE YRS_BTWN = YRS_BTWN - 1.
. COMPUTE MTH_BTWN = MTH_BTWN + 12.
. END IF.
(*) For social-science purposes, one can ignore that an astronomical
day is now a little longer than 86,400 standard seconds. <:,)