# Date.gregorian\_leap? code

**URL:** <https://www.ruby-forum.com/t/date-gregorian-leap-code/180682>\
**Category:** Ruby\
**Created:** [December 25, 2009, 7:51pm UTC](https://www.ruby-forum.com/t/date-gregorian-leap-code/180682 "2009-12-25T19:51:24Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![colinbm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e9c0ed/32.png) [@colinbm](https://www.ruby-forum.com/u/colinbm)\
**Post date:** [December 25, 2009, 7:51pm UTC](https://www.ruby-forum.com/t/date-gregorian-leap-code/180682/1 "2009-12-25T19:51:24Z")

</div>

from date.rb

# Is a year a leap year in the Gregorian calendar?

# All years divisible by 4 are leap years in the Gregorian calendar,

# except for years divisible by 100 and not by 400.

def self.gregorian\_leap? (y) y % 4 == 0 && y % 100 != 0 || y % 400 ==  
0 end

Because of the precedence of && and || this is presumably parsed as  
( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0  
and I’m trying to think of reasons why it is coded as it is instead of,  
say:  
y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 )

Any suggestions?

---

<div class="post-metadata">

**Author:** ![colinbm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e9c0ed/32.png) [@colinbm](https://www.ruby-forum.com/u/colinbm)\
**Post date:** [December 25, 2009, 7:55pm UTC](https://www.ruby-forum.com/t/date-gregorian-leap-code/180682/2 "2009-12-25T19:55:31Z")

</div>

On Dec 23, 2:42 pm, Colin B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> from date.rb
> 
> # Is a year a leap year in the Gregorian calendar?
> 
> # All years divisible by 4 are leap years in the Gregorian calendar,
> 
> # except for years divisible by 100 and not by 400.
> 
> def self.gregorian\_leap? (y) y % 4 == 0 && y % 100 != 0 || y % 400 == 0 end
> 
> Because of the precedence of && and || this is presumably parsed as  
> ( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0  
> and I’m trying to think of reasons why it is coded as it is instead of, say:  
> y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 )

I suppose because either one works:

irb\> LEAP = [1796, 1804, 1896, 1904, 1992, 1996, 2000, 2004, 2008]  
irb\> NOLEAP = [1799, 1800, 1801, 1802, 1803, 1805, 1899, 1900, 1901]  
irb\> def test\_leap  
irb\> LEAP.each{ |y| puts “BAD! #{y} must leap” unless yield y }  
irb\> NOLEAP.each{ |y| puts “BAD! #{y} musn’t leap” if yield y }  
irb\> end  
irb\> test\_leap{ |y| y % 4 == 0 && y % 100 != 0 || y % 400 == 0 }  
irb\> test\_leap{ |y| ( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0 }  
irb\> test\_leap{ |y| y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 ) }

---

<div class="post-metadata">

**Author:** ![colinbm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e9c0ed/32.png) [@colinbm](https://www.ruby-forum.com/u/colinbm)\
**Post date:** [December 25, 2009, 9:13pm UTC](https://www.ruby-forum.com/t/date-gregorian-leap-code/180682/3 "2009-12-25T21:13:59Z")

</div>

On Thu, Dec 24, 2009 at 3:20 AM, Phrogz [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Dec 23, 2:42 pm, Colin B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Because of the precedence of && and || this is presumably parsed as  
> > ( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0  
> > and I’m trying to think of reasons why it is coded as it is instead of, say:  
> > y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 )
> 
> I suppose because either one works: …

It’s true that both variations give the same result. But using y = 2003:  
y % 4 == 0 && y % 100 != 0 || y % 400 == 0  
evaluates y % 4 == 0 as false and then (as far as I can see)  
also evaluates y % 400 == 0 as false,  
and what I’m not seeing is why one might do that:  
if something isn’t exactly divisible by 4 it won’t be divisible by 400.  
Hence my bracketed suggestion which stops at y% 4 == 0  
for years which aren’t divisible by 4.

The code in date.rb isn’t wrong, because it gives the correct answers,  
and won’t take much extra processing time to (from my point  
of view) “unnecessarily” evaluate y% 400 == 0 even if y % 4 != 0,  
so this is admittedly a (very?) minor point, but it’s bugging me  
that I can’t think of a reason why one wouldn’t put the brackets in  
to avoid evaluating y % 400 == 0 in cases where the calculation  
already knows that y% 4 != 0

---

<div class="post-metadata">

**Author:** ![colinbm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e9c0ed/32.png) [@colinbm](https://www.ruby-forum.com/u/colinbm)\
**Post date:** [December 25, 2009, 11:08pm UTC](https://www.ruby-forum.com/t/date-gregorian-leap-code/180682/4 "2009-12-25T23:08:42Z")

</div>

On Thu, Dec 24, 2009 at 5:25 AM, Colin B.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> y % 4 == 0 && y % 100 != 0 || y % 400 == 0  
> so this is admittedly a (very?) minor point, but it’s bugging me  
> that I can’t think of a reason why one wouldn’t put the brackets in  
> to avoid evaluating y % 400 == 0 in cases where the calculation  
> already knows that y% 4 != 0

&& and || are both short-circuiting, so

x && y  
will immediately return x if x is falsy (nil or false), will not  
evaluate y at all in this case.

x || y  
will immediately return x if x is trutth (anything other than nil or  
false) and will not evaluate y at all in this case.

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Twitter: [http://twitter.com/RickDeNatale](http://twitter.com/RickDeNatale)  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [Rick DeNatale - Developer - IBM | LinkedIn](http://www.linkedin.com/in/rickdenatale)
