# calculate days of a month

I would like to see the shortest expression to calculate the days (or the last day) of a month in any language.

Considering y as the number of year and m as month.

Basic rules

• without date / time functions.
• considering leap years.
• there is not other rule.
-

## C, 4033 31 characters

Reduced length in three ways:
1. Replaced `m%2^m>7` with `m^m>7`. The first is 0/1 in 30/31 day months, the second is even/odd. But the high bits don't matter, because their all set in 30 anyway (months with 30/31 days look like a really good idea now).
2. Used mob's idea (`y%(y%100?4:400)` as a leap year test)
3. Used `<1` instead of `!` saves parenthesis.
4. `y%(y%100?4:400)` -> `y%(y%25?4:16)` - works the same.

``````m-2?30|m^m>7:28|y%(y%25?4:16)<1
``````
-
`...:28+!(y%(y%100?4:400))` shaves 3 more – mob Sep 13 '12 at 22:19
Thanks @mob, I'm taking it a bit further, will update soon. – ugoren Sep 14 '12 at 7:30
If you're going to use `y%16`, why not `y%8`? – mob Sep 14 '12 at 16:00
In fact, `(y%50?4:8)` or `(y%25?4:8)` work as well. – mob Sep 14 '12 at 16:11
Thanks @mob, `%16` works. `%8` fails on 2200. I thought about `&15`, which isn't good, and somehow missed the equivalent `%16` – ugoren Sep 14 '12 at 17:58
show 1 more comment

## C, 47 45 characters

``````30+(m>7^m&1)-(m^2?0:2-!(y%100||(y/=100),y%4))
``````

Taken from an answer to an earlier question where I borrowed a couple of tricks from another user. Returns the length of month `m` in year `y` for the Gregorian calendar. ugoren's answer to the same question is shorter and may give a shorter answer to this question.

With thanks to mob for his leap year calculation.

-
Here's another trick: use the expression `!(y%100||(y/=100),y%4)` – mob Sep 13 '12 at 15:28
@mob Wow. It's taken me a good fifteen minutes to figure out how that works (I even checked it on ideone to make sure it did). Clever. – Gareth Sep 13 '12 at 15:54
Figured out a better one: `!(y%(y%100?4:400))` – mob Sep 13 '12 at 16:18
@mob I think I'll leave mine as it is now - there's no way I'll catch up with ugoren's answer. – Gareth Sep 14 '12 at 8:22

``````(62648012>>m*2&3)+28+(m==2&&y%4==0)
``````

http://stackoverflow.com/questions/2675720/calculate-days-of-month/11675530#11675530

So, the simplest form will work until 2100... but to prevents the 2100 bug :) I've copied the Matt solution to leap year:

``````(62648012>>m*2&3)+28+(m==2&&(y%4==0&&(y%100!=0||y%400==0)))
``````
-
I'm not familiar with the language you are using so I may be incorrect, but I don't think you account for integer multiples of 100 (not leap years unless they are also integer multiples of 400) en.wikipedia.org/wiki/Leap_year#Gregorian_calendar for example: 2100 is not a leap year – Matt Sep 12 '12 at 12:06
You are right! I will fix it. thanks. – olivecoder Sep 12 '12 at 14:06

# Python 6461 59

``````(62648012>>m*2&3)+28+(m==2and y%4==0*(y%100>0 or y%400==0))
``````

Based on olivecoder's solution, but accounting for multiples of 100.

-

## VBA, 84

``````28+Val(Mid("303232332323",M,1))-(M=2 And Y Mod 4=0 And (Y Mod 100>0 Or Y Mod 400=0))
``````
-

# Python 50 5457

``````29+{2:y%(y%25and 4or 16)and-1}.get(m,(1&m^m>>3)+1)
``````

with inspiration from mob, and the interesting fact, that a dict saves 1 byte in contrast to m==2and(..)or(...)

-

# Mathematica 97 91 83 82 78 76

A bit long, but gets the job done.

d = y ~ Divisible ~ # & ; 30 + { 1 , Boole [ d @ 400 ∨ ( d @ 4 ∧ ¬ d @ 100 ) ] - 2 , 1 , 0 , 1 , 0 , 1 , 1 , 0 , 1 , 0 , 1 } [ [ m ] ]
-

### VB.net (89 81c)

shame about the date function restriction as VB.net at only (21c)

``````Date.DaysInMonth(y,m)
``````

may have won one for a change. DAMN YOU!

So current best is 89c

{0,31,28,31,30,31,30,31,31,30,31,30,31}(m)+(If( m=2 AndAlso (y Mod 4)=0 AndAlso (y Mod 400)>0,1,0)

``````{0,31,28,31,30,31,30,31,31,30,31,30,31}(m)+(If( m=2 And (y Mod 4)=0 And (y Mod 400)>0,1,0)
``````
-
if we ignore the restriction on YDM, then I can beat that with Excel at only 19 characters with `=DAY(DATE(y,m+1,0))` :) – Sean Cheshire Sep 17 '12 at 19:49
Importing the Namespace System.Date would mean you can remove the first 5 chars, so that brings it down to 16c – Adam Speight Sep 17 '12 at 21:26