I like the recursive solution of Amir very much. Very elegant! But I have two comments. I think the last working dat BEFORE the 26th should be the 19th, not the 26th. To accomplish that I moved the subtraction to the start of the macro. The treatment of the switch between human readable date and SAS internal data values and back could be more user friendly. I changed Amir's code to the following, where I use the CATX trick a second time. If you need the SAS data value as the result of macro you should of course remove the sysfunc(putn(...)) call at the end of the macro. (And I left out the 21st and 22nd of the list of dates, as they will be skipped anyway as weekend days.) /* set up list of holidays in a macro variable */
%let holidates=20dec13,23dec13,24dec13,25dec13;
/* and change the list of dates to a list of sas date values */
%let holidays=%sysfunc(catx(%str( ),"%sysfunc(catx("d%str(,)",&holidates))"d));
%put holidays=&holidays;
/* define macro using recursion */
%macro last_working_day(check_day);
%let check_num=%sysfunc(inputn(&check_day,anydtdte7.));
%let check_num =%eval(&check_num-1);
%if %index(&holidays,&check_num) or %index(17,%sysfunc(weekday(&check_num))) %then
%last_working_day(%sysfunc(putn(&check_num,date.)));
%else
%sysfunc(putn(&check_num,nldate.));
%mend last_working_day;
%put holidays=&holidays;
/* test dates */
%put last working day before 24dec13 is %last_working_day(24dec13);
%put last working day before 25dec13 is %last_working_day(25dec13);
%put last working day before 26dec13 is %last_working_day(26dec13);
%put last working day before 27dec13 is %last_working_day(27dec13);
Frank
... View more