1

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

5
  • 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? Commented Feb 15, 2018 at 21:32
  • 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. Commented Feb 16, 2018 at 2:06
  • 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 Commented Feb 16, 2018 at 3:53
  • 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. Commented Feb 16, 2018 at 15:07
  • 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. Commented Feb 16, 2018 at 19:17

3 Answers 3

0

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);
Sign up to request clarification or add additional context in comments.

2 Comments

It works . May I know if %sysfunc(today()) and "18jan2018"d are the same? I tot the former is an sas integer (number of days since 1960) , is the latter also the same ?
Correct, assuming today() is the 18th of Jan, 2018. ;-) All dates in SAS are integers as you describe.
0

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

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

3 Comments

Or even anydtdte. for maximum compatibility!
For %sysfunc(inputn(&dts1,date9. Does it matter what format I set to , I.e. other format instead of data9.?
yes, you need to use format accordingly as your macro variable . please use %let dts = %sysfunc(inputn(&dts1,anydtdte. )); for almost any date as suggested by user667849
0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.