Compute the difference between two days. Another date-manipulating problem :P

Task


  Write a program or a function that calculates the difference between two dates given by a user.


Input &amp; Output

Similar to the previous one, inputs are two YYYYMMDDs, separated by a space , a comma ,, or a minus sign -.

Example of input values:

20100101-20010911
20110620-20121223
19000101 20101010
33330101,19960229
00010101 99991231


Output is an integer, which is difference between two dates, in days.

For example, input 20110101-20100101 yields 365, and 33320229 17000101 yields 596124.

You may test results at here at here. (See rintaun's comments below.) If two dates are same, the program should returns 0, if the date is valid (see Score).

Restriction

Of course, you must not use any kinds of function/class/... which are related to timestamp or date, and you should use Gregorian calender.

Score

If your code doesn't keep the restriction, then score = -∞.

Default bonus is 1.


If your code works regardless of order of inputs (for example, 20100101,20110101 returns 365 or -365), bonus+=1.
If your code can handle year 0, bonus+=0.5.
If your code recognizes invalid month(between 1~12)/date(between 1~31), like 20109901 or 34720132, and prints E (&amp; terminates the program or returns something like 0), bonus+=1.
Regardless of above rule, if your code recognizes invalid dates, like 20100230, 20100229, or 20111131, and prints E (&amp; terminates the program or returns something like 0), bonus+=1.
Regardless of above two rules, if your code recognizes invalid input string, like 20100101|20100202 or 2010010120100202, and prints E (&amp; terminates the program or returns something like 0), bonus+=1.


score = floor(-4.2*code.length/bonus). Code with highest score wins. If two top codes have same score, then codes with highest bonus wins. If two top codes have both same score and bonus, then codes with highest votes wins.

(Due: When there's more than 5 codes which has more than (or equal) +1 votes.)
Perl 5.14, score = -162
-163 -181 -196 -214 -167 -213 -234

code.length = 211: 208 source characters + 3 for running perl with the -p option
bonus = 5.5: default, order, year 0, never-valid month/day, invalid date, wholly-invalid input

Code
$_=eval(join'-',map{($y,$m,$d)=/(....)(..)(..)/;die&quot;E\n&quot;if!($m*$d)||$m&gt;12||$d&gt;30+($m&amp;1^$m&gt;7)-($m==2)*(2-!($y=~s/00$//r%4));$y-=($m&lt;3)-400;$d+int(($m+9)%12*30.6+.4)+int(365.2425*$y)}/^(\d{8})[ ,-](\d{8})$/)//E

Calculates a modified Julian day number for each date (ignoring the epoch-related adjustments to save code length) and subtracts the two. (ref. &quot;Julian Day&quot; at Wikipedia).

requires perl 5.14+ for the /r option on the substitutions
month-length calculation to get the invalid date bonus: the 30+($m&amp;1^$m&gt;7) part gives the length of any month but February; the rest adjusts for February in an ordinary or leap year

Assumptions

&quot;use Gregorian calendar&quot; means the proleptic Gregorian calendar for dates before whichever Julian to Gregorian transition we're using.  That is, don't subtract 11 days for intervals that cross, for example, the 3 Sep 1752 - 14 Sep 1752 British transition.
&quot;handle year 0&quot; means, for example, 00000101-00010101 should give 366, as 0 is an integral multiple of 400, and so year 0 is a leap year.