This post is reinforcement of a programming trap I should avoid in future, and punishment for selecting poor test cases. It’s not a bug of epic proportions, so move along if you have better things to laugh at than a bug in my Daily WTF-candidate code.

I threw together a simple booking calendar that uses a touch of JavaScript to make it a little more animated than a basic web form on cheapo PHP hosting. Part of the magic of this calendar is that it creates a string of the form “Your booking is for one night from Wednesday July 13th 2011, departing Thursday July 14th 2011” to help reinforce to the user that the correct dates have been understood by the booking system.

When I implemented this booking calendar it appeared to work nicely. Nonetheless, I wrote test cases for it. When there were plenty of tests and they all passed I was feeling smug that my JavaScript was probably provably better quality than most of the JavaScript in existence given it had tests.

It operated for a few months with no complaint. Then there were several reports in one week that the code wasn’t generating the correct weekday.

“Inconceivable!” I thought.

I tried it myself with the dates users complained about and found it was generating crazy weekdays. I checked, and my regression tests were passing just fine. I then plugged the reported problem dates into my test suite. My old test cases succeeded and the new ones failed.

So, down to diagnosis.

The “bulk” of the code is pulling the date string apart so I can use date-related utility functions. The problem was my use of parseInt().  

parseInt() parses a string and returns an integer. I discovered that it works fine for some months (01, 02, 03, 04, 05, 06, 07, 10, 11, & 12) and not for 08 and 09. This is because parseInt() assumes that if the string it is parsing begins with a 0, then it’s an octal number. That works for 01-07 because they generate the same number whether you parse them as octal or not. 11 and 12 work because parseInt() correctly guesses that they are base 10. 08 and 09 are automatically detected as octal, but they fail to parse as octal numbers. I used the error return value to populate the month in a Date object which dutifully interpreted the value as December. The weekdays were right… for December.

Sure enough, none of my test data contained a date in August or September.

The main fix is that the parseInt() function takes a second optional argument that sets the radix to use and stops it from guessing.

I’m still trying to think of a situation when you might want parseInt() to guess the radix for you.