1
votes

below is my little problem to create a macro and passing in a date variable. Without using the date variable, it works with results as below.

%macro x();
%let i=-1;
%let dts = %sysfunc(today());
%put &dts; /*ok*/
%let yymm1 = %sysfunc(intnx(MONTH,&dts,&i));
%put &yymm1; /*ok*/

%let mth_beg = %sysfunc(intnx(MONTH,&dts,&i,B),date9.);
%let mth_end = %sysfunc(intnx(MONTH,&dts,&i,E),date9.);
%put &mth_beg &mth_end; /*01JAN2018 31JAN2018*/
/*** proc sql code below ** */
%mend;
%x();

log: 21231 21185 01JAN2018 31JAN2018

Now I create a macro around it and got the following error:

%macro x(dts1);

%let i=-1;
/*%let dts = %sysfunc(today());*/
%let dts = %sysfunc(&dts1);
%put &dts; /*ok*/
%let yymm1 = %sysfunc(intnx(MONTH,&dts,&i));
%put &yymm1; /*ok*/

%let mth_beg = %sysfunc(intnx(MONTH,&dts,&i,B),date9.);
%let mth_end = %sysfunc(intnx(MONTH,&dts,&i,E),date9.);
%put &mth_beg &mth_end; /*01JAN2018 31JAN2018*/
/*** proc sql code below ** */
%mend;
%x(16JAN2018);

ERROR: Function name missing in %SYSFUNC or %QSYSFUNC macro function reference. JAN2018) ERROR: Expected close parenthesis after macro function invocation not found. )) ERROR: Expected close parenthesis after macro function invocation not found. ERROR: Expected close parenthesis after macro function invocation not found. ,B),date9.) ,E),date9.)

I am not sure how to let SAS treat the date passed in as a recognized date. I know i probably used the sysfunc(&dts) wrongly or the date passed in need to adhere to certain format. i just want the date to replace today(). Can you help? I am a SAS newbie.

thanks

3
What values do you want to pass into your macro when you call it? Do you want to pass in character strings that look to you like a date 16FEB2018? Or do you want to pass in a valid SAS date, such as a date literal "16FEB2018"d, or a simple number of days since 01JAN1960? - Tom
I am flexible cos I am the one who decide the passing. Cos I will be doing this e.g. %x(16Feb2018); %x(16Jan2018);..Etc basically I am passing in monthly data points to run monthly reports. So as long sas accept my values. - Mangowithice
So if you pass in values like 16FEB2018 and you want to use it as an actual date you will need to convert it to a date literal in the body of the macro. "&mvar"d - Tom
Thanks it works. But I would like to know the difference btw %let dts = %sysfunc(today()); and %let dts = "%dts1"d (i.e . "16jan2018"d. Both steps point to below step. %let yymm1 = %sysfunc(intnx(MONTH,&dts,&i)); Assuming today is 16jan2018, I know %let dts = %sysfunc(today()); resolves to SAS integer value. But "16jan2018"D is not the SAS integer right? I just am not sure why the difference in treatment. - Mangowithice
See answer below. You can represent the same date as either an integer or a date literal. Just make sure you know what you are doing. - Tom

3 Answers

0
votes

Wrap the date in " and end with a d. That will tell SAS to convert the string to a date:

%macro x(dts1);

%let i=-1;
/*%let dts = %sysfunc(today());*/
%let dts = "&dts1"d; /*Change here!*/
%put &dts; /*ok*/
%let yymm1 = %sysfunc(intnx(MONTH,&dts,&i));
%put &yymm1; /*ok*/

%let mth_beg = %sysfunc(intnx(MONTH,&dts,&i,B),date9.);
%let mth_end = %sysfunc(intnx(MONTH,&dts,&i,E),date9.);
%put &mth_beg &mth_end; /*01JAN2018 31JAN2018*/
/*** proc sql code below ** */
%mend;
%x(16JAN2018);
0
votes

change %let dts = %sysfunc(&dts1); to

%let dts = %sysfunc(inputn(&dts1,date9. ));
0
votes

SAS stores dates as the number of days since 01JAN1960. So if you do not attach a date format to the date value it will just look like an integer.

%let today=%sysfunc(today());

You can then use that integer anywhere you would use a date value.

%let next_month=%sysfunc(intnx(month,&today,1,b));

You can also represent dates by using a date literal. To make a date literal you represent the date value using something the DATE informat can read (like 16FEB2018, 16feb18, 16-FEB-2018, etc.) enclosed in quotes with the letter d appended.

%let today="%sysfunc(today(),date9)"d ;
%let date_string=13FEB2018;
%let date_value="&date_string"d ;

So date literals will work in SAS code and when you use the %sysfunc() macro function to call a SAS function (like INTNX) and they will work in the %sysevalf() macro function. But the %eval() macro function will not recognize date literals. So you will need to use %sysevalf() if you want use arithmetic or comparisons of date literals in macro logic.

%if %sysevalf(&today > '01JAN2018'd) %then ....
%let tomorrow=%sysevalf(&today +1);