Hi All,
Here is my code, I want to make sure that when its a leap year, I add one to the month of February.
%MACRO LEAPYEAR;
%IF MOD(&Year,4) = 0 AND ((MOD(&Year,100) ne 0) OR (MOD(&Year,400) = 0)) %THEN %DO;
%IF SUBSTR(&Inc_End, 5, 4) = '0228' %THEN &Inc_End = %EVAL(&Inc_End + 1);
%IF SUBSTR(&Paid_End, 5, 4) = '0228' %THEN &Paid_End = %EVAL(&Paid_End + 1);
%END;
%MEND LEAPYEAR;
%LEAPYEAR
But I keep getting this error in the log:
25 GOPTIONS ACCESSIBLE;
26 %MACRO LEAPYEAR;
27 %IF MOD(&Year,4) = 0 AND (MOD(&Year,100) ne 0 OR MOD(&Year,400) = 0) %THEN %DO;
28 %IF SUBSTR(&Inc_End, 5, 4) = '0228' %THEN &Inc_End = %EVAL(&Inc_End + 1);
29 %IF SUBSTR(&Paid_End, 5, 4) = '0228' %THEN &Paid_End = %EVAL(&Paid_End + 1);
30 %END;
31 %MEND LEAPYEAR;
32 %LEAPYEAR
SYMBOLGEN: Macro variable YEAR resolves to 2021
ERROR: Required operator not found in expression: MOD(&Year,4) = 0 AND (MOD(&Year,100) ne 0 OR MOD(&Year,400) = 0)
SYMBOLGEN: Macro variable YEAR resolves to 2021
SYMBOLGEN: Macro variable YEAR resolves to 2021
ERROR: The macro LEAPYEAR will stop executing.
Any idea why? I thought my If And statement looks okay but I must be doing something wrong!
Thanks in advance!
%IF %sysfunc(MOD(&Year,4)) = 0 AND (%sysfunc(MOD(&Year,100)) ne 0 OR %sysfunc(MOD(&Year,400)) = 0) %THEN %DO
You can't use data step functions in an %IF statement. You must enclose them in %SYSFUNC.
Of course, there is a simpler way
https://blogs.sas.com/content/sasdummy/2016/02/19/calculate-leap-year-in-sas/
which you could have found using a simple internet search for
leap year SAS
%IF %sysfunc(MOD(&Year,4)) = 0 AND (%sysfunc(MOD(&Year,100)) ne 0 OR %sysfunc(MOD(&Year,400)) = 0) %THEN %DO
You can't use data step functions in an %IF statement. You must enclose them in %SYSFUNC.
Of course, there is a simpler way
https://blogs.sas.com/content/sasdummy/2016/02/19/calculate-leap-year-in-sas/
which you could have found using a simple internet search for
leap year SAS
So the MDY() trick in the linked blog post does not work well in macro code. It generates error messages when the date is invalid.
2116 %let year=2100; 2117 %if %sysfunc(mdy(2,29,&year)) %then %do; WARNING: An argument to the function MDY 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: . ERROR: Skipping to next %END statement. 2118 %put &=year is leap year ; 2119 %end;
You could instead use INTNX() to find the last day in February for that year and then check if it is 29 or not.
%let year=2100;
%if 29=%sysfunc(intnx(month,"01FEB&year"d,0,e),day.) %then %do;
%put &=year is leap year ;
%end;
%else %do;
%put &=year is not leap year;
%end;
Or just use the DAY() function on the day before March first.
%let year=2000;
%if 29=%sysfunc(day("01MAR&year"d-1)) %then %do;
%put &=year is leap year ;
%end;
%else %do;
%put &=year is not leap year;
%end;
@Tom wrote:
So the MDY() trick in the linked blog post does not work well in macro code. It generates error messages when the date is invalid.
But in my opinion, I don't really see a need for doing this in macro code.
@PaigeMiller wrote:
@Tom wrote:
So the MDY() trick in the linked blog post does not work well in macro code. It generates error messages when the date is invalid.
But in my opinion, I don't really see a need for doing this in macro code.
I agree, but also the data step code from the blog creates >100 lines of ugly notes (about "invalid arguments" and other issues) in the log, which is not ideal. I was really surprised to see that none of the fairly obvious clean alternatives like (using @Tom's suggestion)
data leap_years;
do year=2000 to 2200;
if day(mdy(3,1,year)-1)=29 then output;
end;
run;
was proposed in the blog post (or its comments section).
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.
Ready to level-up your skills? Choose your own adventure.