I am trying to create last date of the month using sas macro. I set year-month yyyymm and would like to get last date of the month. For example if the year is 2015 and month is January, then I would like the SAS date macro variable to be the sas date number equivalent of ‘31Jan2015’d
%LET YYYYMM = 201501;
%LET SASDATE = %EVAL(%SYSFUNC(INTNX('MONTH',%SYSFUNC(MDY(%SYSFUNC(MOD(&YYYYMM,100)),1,%SYSFUNC(ROUND(%EVAL(&YYYYMM/100))))),1))-1);
%PUT &SASDATE;
But I am getting the following error in the log. Can you please help? Thank you.
23 GOPTIONS ACCESSIBLE; 24 %LET YYYYMM = 201501; 25 %LET SASDATE = 25 ! %EVAL(%SYSFUNC(INTNX('MONTH',%SYSFUNC(MDY(%SYSFUNC(MOD(&YYYYMM,100)),1,%SYSFUNC(ROUND(%EVAL(&YYYYMM/100))))),1))-1); WARNING: Argument 1 to function INTNX referenced by the %SYSFUNC or %QSYSFUNC macro function is out of range. NOTE: Mathematical operations could not be performed during %SYSFUNC function execution. The result of the operations have been set to a missing value. ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: .-1 26 %PUT &SASDATE;
OK, removing the quotes around 'MONTH' solves your problem
%LET YYYYMM = 201501;
%LET SASDATE = %EVAL(%SYSFUNC(INTNX(MONTH,%SYSFUNC(MDY(%SYSFUNC(MOD(&YYYYMM,100)),1,%SYSFUNC(ROUND(%EVAL(&YYYYMM/100))))),1))-1);
%PUT &SASDATE;
Please note: You do not require quotes or in other words literal tokens for the macro processor to do text processing
Ah yes, doing it this way requires multiple %sysfunc nested within each other, it's a nightmare.
Instead do it in a data step, no more %sysfunc needed, makes your life a whole lot easier, or at least easier to debug.
For example:
data _null_;
date_desired = .... your code here .... ;
call symputx( 'sasdate',date_desired);
run;
I can't agree more with @PaigeMiller My eyes and head hurt to review the syntax
OK, removing the quotes around 'MONTH' solves your problem
%LET YYYYMM = 201501;
%LET SASDATE = %EVAL(%SYSFUNC(INTNX(MONTH,%SYSFUNC(MDY(%SYSFUNC(MOD(&YYYYMM,100)),1,%SYSFUNC(ROUND(%EVAL(&YYYYMM/100))))),1))-1);
%PUT &SASDATE;
Please note: You do not require quotes or in other words literal tokens for the macro processor to do text processing
@pradark1 No problem, I will have to eat lots of carrots and vitamin A supplements for my eyes to stay alert for such nested syntax. lol
Just be aware, when you are dealing with macro processor, be alert with use of literal tokens 'blahblahblah' or "blahblahblah" . Until your program is executed by macro processor before the resolved text moves to the compiler for datastep execution, we play only with text and temporary conversion of text to numbers.
Knowledge of tokenisation is most important to make the distinction what happens in the input stack. In my opinion, nobody has mastered this concept to the extent of Ian Whitlock the genius. I am fortunate to even read his paper. Have a good day!
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.