Hi Everyone,
I am attempting to write a macro to check whether my date variable (created in a previous data step) is within plus/minus 3 days of a group of US holidays. I cannot get the macro processor to recognize my date variable as a DATE, so that I can then add/subtract additional days from this date value, and use the HOLIDAY function to see if these dates are equivalent.
I have nested the macro within my DATA STEP because this is one of several checks that I want to perform on these date values within the same data step.
I've tried using SYMPUT to convert my data step date variable (CKDATE) into a macro variable (&CKDATE), then use %SYSFUNC-INTNX to add days to the existing date in order to perform the comparison. Alternatively, I've tried using %LET and %EVAL to increment days to my existing date variable (CKDATE). In each case, however, my date variable is not being interpreted as a numeric date.
Any suggestions would be most helpful.
Thank You!
** Method 1 - SYMPUT to convert CKDATE to &CKDATE
- %SYSFUNC-INTX to advance &CKDATE;
data test;
retain ckdate; * retain date;
ckdate_temp = ckdate; * previous pay date;
set weekly;
by EdwID;
length flag_desc $ 100 holiday $ 20; * reason for flag / keyword for HOLIDAY function;
format flag_date YYMMDD10.; * flag date;
if first.EdwID then ckdate_temp = ckdate;
%macro holidays(short,long); * looping flagged dates, check if within 3 days of holiday;
if flag = 1 then do;
%do i = -3 %to 3; * day counter;
call symput('ckdate',ckdate); * convert date to macro variable;
%let date = %sysfunc(intnx(day,&ckdate,&i),yymmdd10); * add 1-3 days to date;
if &date = holiday(&short,year(&ckdate)) then do; * check if = holiday;
flag_desc = &long; * if yes, flag reason = "HOLIDAY NAME";
flag_date = &ckdate; * Create seperate column for FLAG DATE;
end;
%end;
%mend;
%holidays('christmas','Christmas');
%holidays('newyear','New Years');
%holidays('mlk','MLK Day');
run;
** Method 2 - Use %LET-%EVAL to add days to my existing DATE variable;
data test;
retain ckdate; * retain date;
ckdate_temp = ckdate; * previous pay date;
set weekly;
by EdwID;
length flag_desc $ 100 holiday $ 20; * reason for flag / keyword for HOLIDAY function;
format flag_date YYMMDD10.; * flag date;
if first.EdwID then ckdate_temp = ckdate;
%macro holidays(short,long); * looping flagged dates, check if within 3 days of holiday;
if flag = 1 then do;
%do i = -3 %to 3; * day counter;
%let date = %eval(ckdate+&i); * Add counter to date variable;
if &date = holiday(&short,year(ckdate)) then do; * check if = holiday;
flag_desc = &long; * if yes, flag reason = "HOLIDAY NAME";
flag_date = ckdate; * Create seperate column for FLAG DATE;
end;
%end;
%mend;
%holidays('christmas','Christmas');
%holidays('newyear','New Years');
%holidays('mlk','MLK Day');
run;
sample of weekly.sas7bdat
EdwID | ckdate | flag |
---|---|---|
1 | 2013-12-18 | 0 |
1 | 2013-12-24 | 1 |
1 | 2013-12-31 | 1 |
1 | 2014-01-08 | 0 |
At first (not careful glance) it seems like you're mixing macro and data step code.
I don't think I've ever seen a macro defined inside a data step. I know you can't call a macro inside the data step like that.
I also don't think you need a macro for this. Consider posting some sample data and expected output instead.
Macro code is used to generate code that is then passed to regular SAS to be interpretted and run.
Turn on MPRINT and you will see the code that your macro calls are generating.
You probably just want to code a normal DO loop.
So the body of your macro could be the some thing like this with the text in red being the parts you might want to replace with macro parameters.
if flag = 1 then do;
do date=chkdate-3 to chkdate+3 ;
if date = holiday('christmas',year(ckdate)) then do;
flag_desc = 'Christmas';
flag_date = ckdate ;
end;
end;
end;
I wasn't sure if you want to set FLAG_DATE to the original CHKDATE variable or to the derived holiday date that will be in the DATE variable.
Actually it is probably even easier to just check if the date is within 3 days of the holiday.
if -3 <= (chkdate - holiday('christmas',year(ckdate)) <= 3 then do;
Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.
Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.