BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
mhoward2
Obsidian | Level 7

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!

 

1 ACCEPTED SOLUTION

Accepted Solutions
PaigeMiller
Diamond | Level 26
%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 

 

 

--
Paige Miller

View solution in original post

5 REPLIES 5
PaigeMiller
Diamond | Level 26
%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 

 

 

--
Paige Miller
mhoward2
Obsidian | Level 7
Thank you very much! I greatly appreciate you stopping to help!
Tom
Super User Tom
Super User

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;
PaigeMiller
Diamond | Level 26

@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.

--
Paige Miller
FreelanceReinh
Jade | Level 19

@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).

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 1390 views
  • 0 likes
  • 4 in conversation