BookmarkSubscribeRSS Feed
Travis
Calcite | Level 5

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

EdwIDckdateflag
1

2013-12-18

0

12013-12-241
12013-12-311
12014-01-080
2 REPLIES 2
Reeza
Super User

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.

Tom
Super User Tom
Super User

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;

sas-innovate-2024.png

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.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 2 replies
  • 1733 views
  • 3 likes
  • 3 in conversation