Calculate the day number of the year

Seems like we do not have this one yet, so here we go:

The Challenge

Write a program or function that takes a date as input and outputs the day number of the year. You may not use any builtins for that!

Rules

• As usual you may write a full program or a function.
• The format of the input is up to you, but it has to contain a year, a month and a day. Make clear which one your solution uses!
• No date-related builtins allowed! You gotta do the work by yourself. Builtins which are not related to date operations are fine.
• Base for the calcultion is the gregorian calendar.
• You have to take account of leap-years.
• You only need to handle years in the range [1, 9999]
• Standard loopholes are forbidden.
• Lowest byte count wins!

Testcases

Input format here is YYYY/MM/DD

2016/07/05 -> 187
2000/03/28 -> 88
0666/06/06 -> 157
6789/10/11 -> 284
0004/04/04 -> 95
1337/07/13 -> 194


Happy Coding!

• Can we use builtins for days since a certain date? What about for whether a year is a leap year? Jan 28 '16 at 22:19
• @Thomas No date-related builtins allowed. Gonna clarify that in the challenge, thanks for the comment! :) Jan 28 '16 at 22:22
• @DenkerAffe Why did you forbid all built-ins? Jul 17 '16 at 18:07

JavaScript ES6, 81 69 bytes

(y,m,d)=>d+parseInt("03479cehkmpr"[--m],36)+m*28-(y%(y%25?4:16)&&m>1)


Assuming months are 1-based, otherwise I could save 2 bytes.

Edit: Saved 12 bytes using @user81655's tip.

C, 9610289 61 bytes

g(y,m,d){printf("%d",m/2*31+--m/2*30-(y%(y%25?4:16)?2:1)+d);}


Python 3, 152148 150 bytes

m,d,y=map(int,input().split());n=[0,31,(59,60)[(y%4==0 and y%100!=0)or y%400==0]]
for i in range(m):n+=[n[-1]+(31,30)[i in[1,3,6,8]]]
print(n[-4]+d)


Takes dates in the format "M D YYYY".

• You should use Python 2, unless you need specific features from Python 3. Because then you don't need brackets in your prints which allows you to save one byte by wrinting your print as print n[m-1]+d Jan 29 '16 at 9:37
• In the first line, you could write y%4==0and y%100!=0, I think Jul 16 '16 at 8:38

Pyth, 31 bytes

+s<X1+L28jC"3»î"4!%|F_jQ*TT4tEE


Thanks to @Dennis and @Jakube for the leap year portion. Input is YYYY, MM, DD on separate lines.

+                          add [day] to
s <                      sum of first [month]-1 values in the list
1                  the second element (January)...
+L                 \
28              |
j               }   lengths of all the months
C "3»î"       |
4             /
! %                ... if the year is a leap year; that is, 4 divides...
|F _ j         fold logical OR over reversed
Q       the year
*TT     converted to base 100
4
t E                 [month]-1
E                       [day]


Python 2, 100 82 bytes

A Python port of @Neil's answer:

lambda d,m,y:d+int("03479cehkmpr"[m-1],36)+(m-1)*28-(y%(4if y%25 else 16)and m>2)


As with the previous answer, adding 17 bytes (99 bytes total) will yield a full program:

print(lambda d,m,y:d+int("03479cehkmpr"[m-1],36)+(m-1)*28-(y%(4if y%25 else 16)and m>2))(*input())


As an anonymous lambda:

lambda d,m,y:d+sum(31-(n in(3,5,8,10))for n in range(m-1))-(3if y%4 or(y%400!=0and y%100==0)else 2)


Can be converted to a named lambda for a 2 byte penalty. Alternatively, a full program (taking input in the format D,M,Y) can be achieved for 117 bytes:

print(lambda d,m,y:d+sum(31-(n in(3,5,8,10))for n in range(m-1))-(3if y%4 or(y%400!=0and y%100==0)else 2))(*input())

• A few small golfs gets 76 bytes Jun 12 '19 at 17:07

Python 3, 125 bytes

print((lambda d,m,y:sum([3,not(y%400 and not y%100 or y%4),3,2,3,2,3,3,2,3,2,3][:m-1])+m*28-28+d)(*map(int,input().split())))


An another approach to this problem. The code takes advantages of the Python's boolean algebra execution priorities and since not is the last operation, conversion to boolean is automatic. When summation is done, the boolean is treated as 1 or 0. Input format is "YY MM DDDD" string. Input system inspired by @SteveEckert's similar one.

Another form as a function, 91 bytes

def f(d,m,y):return sum([3,not(y%400 and not y%100 or y%4),3,2,3,2,3,3,2,3,2,3][:m])+m*28+d


In this case input is three integers, the month being between 0-11. This would work in Python 2 also.

Excel, 106 bytes

=AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100))))+30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1


Takes input in three cells A1 = Year, B1 = Month, C1 = Day.

AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100))))


1 if LeapYear, else 0

30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1


Multiple of 30, CHOOSE for additional days, plus days in month

Evolution:

=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+CHOOSE(B1,0,31,59,90,120,151,181,212,243,273,304,334,365)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+CHOOSE(B1-1,31,59,90,120,151,181,212,243,273,304,334,365)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+30*(B1-1)+CHOOSE(B1,0,1,-1,0,0,1,1,2,3,3,4,4,5)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+30*B1-30+CHOOSE(B1,0,1,-1,0,0,1,1,2,3,3,4,4,5)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1
=AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100))))+30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1