http://download.oracle.com/javase/7/docs/technotes/guides/la...
http://download.oracle.com/javase/7/docs/technotes/guides/la...
In a prev job, I saw this block of code -
-------
public int getDaysInMonth( String month ) {
if( month.equalsIgnoreCase("january")) return 31;
else if( month.equalsIgnoreCase("february")) return 28;
else if( month.equalsIgnoreCase("march")) return 31;
else if( month.equalsIgnoreCase("april")) return 30;
...
}-------
My eyes bled. I said folks, just map the month to an int M in range [1..12] and simply write 1 line of code
return 30+((M+Math.floor(M/8))%2;
( except for 2, which is 28 or 29 depending on a leap year)
I was overruled. "We are programmers, not mathematicians" was the response!!!
Now they'll happily use this string-switch to do
---------
switch( month.toLowerCase() ) {
case "january" return 31;
case "february" return 28;
case "march" return 31;
case "april" return 30;
... default : return -1;
}-------
which is an even nastier abomination :(
case "september":
case "april":
case "june":
case "november": return 30;
It's sad, but still need to go through the poem in my head to remember most of the time. [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][M-1]
than your formula. Even a dictionary wouldn't be bad. And if it were wrong, it would be easier to fix it.The aforementioned code can never be verified as correct because February requires a year to be present to know the number of days.
Doesn't java have a massive calendar library to address exactly these sorts of human questions?
I mean sure you'd still be looking at code like:
public int getDaysInMonth(DateTime date) throws
CalendarFactoryFactorException,
DateOutOfRangeException,
ArrayOutOfBoundsException
{
CalendarFactoryFactory factoryMaker = new CalendarFactoryFactory("Western");
GregorianCalendarFactory gregFactory = factoryMaker.getGregorianFactory();
Calendar c = gregFactory.createCalendar(new DateTime());
return c.getDaysInMonth();
}Tests can prove the presence of bugs, but they are (in general) hopelessly inadequate to prove their absence; and once a test finds a bug, you still have to be able to understand what the code is doing in order to fix the bug.
In practice, code inspections and tests find quite distinct sets of bugs with some overlap, so it's valuable to do both of them. That's why all decent programming processes require both.
(This is probably one of the few cases where you could in fact verify that the code is correct by exhaustive testing — but only by comparing it against a known-correct implementation.)
Edit: also, if you're mapping the month string to an integer anyway, I don't see how you're going to do that without doing basically the same thing as the switches you posted anyway.
1. You have 12 months. Ignore February. Then you have 11.
2. The remaining 11 map to either 30 days or 31 days . ie. 30+0, or 30+1.
3. So the object is to write a many-to-one function that maps some members of the set to 0, rest to 1. Add 30 and you get the right answer ie. number of days in that month.
4. So you want to map {1,3,5,7,8,10,12} to 1, and {4,6,9,11} to 0.
5. Write down a 13 bit number. If you rightshift x times and AND it with unity, you get 1.
6. So then, x belongs to {1,3,5,7,8,10,12}.
7. That means the bit in each of those locations must be on. The rest of the bits must be off. That gives you the number 1010110101010, which is simply 5546 in decimal.
8. So that's ((5546>>M)&1)+30, except for M==2.
I'm sure this is useful in some cases though :-)