Question | Answer |
---|---|
I have pairs of SAS date and time variables in a table, but I want to calculate the differences between them. Is there an easy way to do this? | You can use the DHMS() function to combine SAS date and time variables into a SAS datetime variable. Note that SAS time variables actually contain the number of seconds elapsed since midnight, so you don't need to split up the time into hours, minutes and seconds first for DHMS(). The INTCK() function can then be used to calculate the difference between the 2 SAS datetime values:
DATA _null_; INFORMAT date1 date2 DATE9. time1 time2 TIME5. unit $10.; FORMAT dt1 dt2 DATETIME.; INPUT date1 time1 date2 time2 unit; dt1=DHMS(date1,0,0,time1); dt2=DHMS(date2,0,0,time2); difference=INTCK(unit,dt1,dt2); PUT unit= dt1= dt2= difference=; DATALINES; 21mar2003 21:05 22mar2003 00:30 SECOND 21mar2003 21:05 22mar2003 00:30 MINUTE 21mar2003 21:05 22mar2003 00:30 HOUR 21mar2003 21:05 24mar2003 10:25 DTDAY 21mar2003 21:05 22may2003 10:25 DTWEEK 21mar2003 21:05 22oct2004 10:25 DTMONTH 21mar2003 21:05 22jan2009 10:25 DTYEAR ; RUN;Warning: INTCK() returns the number of unit boundaries crossed, e.g. for HOUR, 21:59 to 22:01 = 1, but 21:01 to 21:59 = 0, because the former example crosses 22:00, but the latter has both values within the same hour. |
How can I calculate the week of the year from a SAS date? | You can simulate a WEEK function by using the SAS functions INTCK and INTNX, e.g.:
DATA getweek; datevar=TODAY(); week=INTCK('WEEK', INTNX('YEAR',datevar,0), datevar)+1; RUN; |
I have a SAS table containing historical information in a single record:
id startdate1 enddate1 startdate2 enddate2 001 01Jan2000 15Apr2002 28Jun2000 16Sep2001 002 01Feb2000 07Feb2002 19Jul2000 04Oct2000How do I convert this data to multiple monthly summary records between the startdate1 and enddate1 values, and include extra information from startdate2 and enddate2. |
It is not possible to directly use monthly dates in DO...END loops, as each months haa a varying number of days. However, you can still generate successive months by using the number of months relative to the
startdate1 value using the INTCK and INTNX functions. The additional information can be calculated by comparing the values of the 1st day of the same month for each date:
DATA monthly (KEEP=id date month flag2); SET history; month_count=INTCK('MONTH',startdate1,enddate1); startmonth2=INTNX('MONTH',startdate2,0); endmonth2=INTNX('MONTH',enddate2,0); DO month=0 TO month_count; date=INTNX('MONTH',startdate1,month); IF startmonth2 LE date LE endmonth2 THEN flag2=1; ELSE flag2=0; OUTPUT; END; FORMAT date MONYY7.; RUN; |
I want to select the previous 5 weekdays using an IN clause containing Julian date values, but I am forced to hardcode the values:
IF procdate IN (1997204,1997205, 1997206,1997209, 1997210) THEN DO; ......etc Is there a way to automate this? |
Probably the easiest way is to generate the previous weekdays, and then store the Julian date values in a SAS macro variable, e.g.:
DATA _null_; LENGTH datestr $42; datestr='('; DO d=(TODAY()-1) TO (TODAY()-7); IF (1 LT WEEKDAY(d) LT 7) THEN datestr=TRIM(datestr) !! PUT(d,JULIAN7.) !! ','; END; SUBSTR(datestr,LEN(TRIM(datestr)),1)=')'; CALL SYMPUT('datestr',TRIM(datestr)); STOP; RUN; The macro variable can then be used to replace your list of dates, e.g.: IF procdate IN &datestr THEN DO; ......etc |
When I use INTCK('YEAR',birthday,TODAY()) to calculate someone's age it doesn't always give the correct answer. Am I doing something wrong? | You should avoid using the INTCK function with 'YEAR' to calculate age, as it returns the number of times January 1st occurs between the 2 dates. Using 'MONTH' instead of 'YEAR' will give the number of 1st of the month days between the 2 dates, but this can be adjusted by comparing the day of the month of each date, e.g.:
DATA getage; birthday='25Dec1972'd; datevar=TODAY(); /* Divide months by 12 to get years */ age=INT(INTCK('MONTH',birthday,datevar)/12); /* Adjust age if the 2 dates have the same month */ /* and the birthday is still to come in this month */ IF MONTH(birthday)=MONTH(datevar) THEN age=age-(DAY(birthday)>DAY(datevar)); RUN; |