How do I account for leap year in a formula?

Reply
Frequent Contributor
Posts: 75

How do I account for leap year in a formula?

Hi,

 

I got the below code from someone else. It is supposed to account for leap year. So during a

 

1) leap year: 183<=A<366

2) non-leap year: 183<= A<365

 

 

%LET Year=

183<= A < 365+(4*INT(&Year/4)=&Year)

 

Can someone explain to me what this does -- (4*INT(&Year/4)=&Year)?

 

As far as I know  INT truncates a number to its integer.

 

Thank you

Trusted Advisor
Posts: 1,789

Re: How do I account for leap year in a formula?

Instead of writing code (or using somebody else's code) to determine time intervals, you use the built-in SAS functions, which already account for leap years and for un-equal number of days in a month, and all other quirks of the modern calendar.

 

The functions are INTNX and INTCK, look them up, use them.

Regular Contributor
Posts: 161

Re: How do I account for leap year in a formula?

[ Edited ]

Here is a simple check that might be easy to understand.  Good luck to you...!!!

 

Data check_year;
     do year_value = 2000 to  2016;
        length leap $3;
        leap='no';
        If mod(year_value,4)=0 then leap='YES'; 
        If mod(year_value,100)=0 and 
            mod(year_value,400) ne 0 
        then leap='NO'; 
        output;
     end;
Run;
proc print noobs; var year_value leap;
run;

Here is the result of the code for your reference: 

 


year_value	leap
2000	YES
2001	no
2002	no
2003	no
2004	YES
2005	no
2006	no
2007	no
2008	YES
2009	no
2010	no
2011	no
2012	YES
2013	no
2014	no
2015	no
2016	YES

 

Here is some more literature from where I got the calc.... 

http://support.sas.com/kb/44/233.html

 

Kannan Deivasigamani
Super User
Super User
Posts: 6,845

Re: How do I account for leap year in a formula?

You probably do not want to use this trick.  First it does not take into account the rules for centuries. Years that are divisible by 100 but not divisible by 400 are NOT leap years. You can probably figure out a way to use the built in date manipulation functions to do what you want.  For example to find the number of days in a year you could do:

 

%let days_in_year = %sysevalf("01JAN%eval(&year+1)"d - "01JAN&YEAR"d) ;

 

But to the specific question of how to interpret the expression:

 

(4*INT(&Year/4)=&Year)

The function call INT(&YEAR/4) will divide the year value by 4 and keep only the integer part of the result.  If you then multiple by 4 you will only get the same number back when the year was exactly divisible by 4.  So this will be true when YEAR is a multiple of 4.  SAS returns 1 for true and 0 for false when evaluating a logical expression in an equation.  You could do the same thing a little clearer using the MOD() function.  

 

(0=MOD(&YEAR,4))

 

But there are other issues with this %LET statement.

First it is generating the SAS code to call the INT() function instead of evaluating the expression itself.  For example try this code:

    %let year=2015 ;
    %let year=183<= A < 365+(4*INT(&year/4)=&year) ;
    %put &year ;

The result is that YEAR contains the expression:  183<= A < 365+(4*INT(2015/4)=2015)

That means that if you use this macro variable in a data step expression the INT() function is re-run each time through the data step.

 

Second it is probably not good practice to store it back into the same macro varaible that previously just had the digit string for the year.

 

 

 

Super User
Posts: 5,365

Re: How do I account for leap year in a formula?

As a macro language statement, this does nothing useful.  Macro language evaluates comparisons from left to right.  So the first evaluation is:

 

183 <= A

 

This is not a reference to a variable named "A", it is just the letter "A".  So the comparison will be either true or false depending on your operating system (ASCII vs. EBCDIC).  True comparisons return a 1, and false comparisons return a zero.  So midway through the comparisons, macro language is looking at:

 

1 < 365 + (4*INT(&Year/4)=&Year)

 

This comparison will always be true, and will therefore return a 1.  So the result of your original statement should always be assigning &YEAR a value of 1 (possibly adding + (4*INT(&Year/4)=&Year) aftwards ... I'm not able to verify that right now).

 

I vote for the recommendation to examine INTNX.  Properly used in a DATA step, it can return, for example, a SAS date equivalent to the same day of the year, X years in the future.

 

Good luck.

Respected Advisor
Posts: 4,132

Re: How do I account for leap year in a formula?

@Astounding

I believe you've missed that the expression doesn't get evaluated on SAS macro level. It's simply populating a macro variable which I assume is then used in a data step where the expression evaluates on SAS Base language level.

Respected Advisor
Posts: 4,132

Re: How do I account for leap year in a formula?

As @PaigeMiller already wrote: SAS provides a whole set of calendar functions which do all the magic for you. No need to try and code this.

 

I suggest you ask the person who provided this code what it's supposed to do - and then re-write the intended logic using SAS calendar functions.

Ask a Question
Discussion stats
  • 6 replies
  • 771 views
  • 1 like
  • 6 in conversation