An Interesting "Feature" In Ruby’s DateTime.Parse

It’s not all rainbows and unicorns in the Ruby world… everything now and then you run into something that really makes you go “WHAT THE?!” … today’s misadventure comes curtesy of Ruby’s DateTime.parse method. Generally speaking, this method is quite useful and quite forgiving in what it can parse. It will take a large number of formats and do what it can, even with very little.

For example, did you know that this string will correctly parse: “SHOW ME THE MONEY!!!” … it results in a very “interesting” date… like this:

=> #<DateTime: 2010-12-13T00:00:00+00:00 (4911087/2,0/1,2299161)>

Don’t believe me? Open up IRB in ruby 1.9.2 and run this:

Crazy, eh?! I thought so. Here’s the real fun, though… the ability for DateTime.parse to work with what should be a completely invalid date string caused a false-positive in a unit test for me earlier today. I wasn’t using “SHOW ME THE MONEY!!!” as the text, but I was passing in a string as “six_months_to_one_year”. The code that was parsing this string had some logic in it that was supposed to produce a value of “1″ for any date that fell within the range of six months to one year. Oddly enough, this code and logic produced that result because DateTime.parse(“six_months_to_one_year”) parsed as a date that fell within the range I was looking for.

Needless to say, I was expecting an exception to be thrown when this string was parsed and was shocked when the test passed. My incredulity only increased as I tried out various random strings, date ranges in the form of strings, and nonsensical garbage characters – some of which parsed, too my surprise, and some of which didn’t, again to my surprise. For example “how many days are there?” throws an exception, but “how many days are there before the wedding?” does parse.

It’s crazy I tell you.

After some time, I began to notice a pattern in what parsed, though. At first, I noticed that any string with the word “month” in it parsed correctly. I started narrowing down the text until i only had the world “month”, then “mont”, then “mon” – so far, so good. But then “mo” failed. Aha! “mon” is the abbreviation for Monday! and what did the original “six_months_to_one_year” parse as? “Monday, December 13th.”

See the pattern with the other strings, yet? “show me the MONey” and “how many days are the until the WEDding?”, or “I sat on a thumbtack today! Ouch!” … they all have a day’s abbreviation in them.

No matter how badly munged the rest of the string is, the DateTime.parse will find that abbreviation and parse it as a date because of it. … at least in Ruby 1.9.2 – I haven’t tried on any other versions, yet.

Crazy, eh? Threw me for a serious loop, for quite some time.

 

 


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Ruby. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://krazykoding.com Paul Keeble

    Java’s Date parsing is horribly overspecified and SimpleDateFormat is anything but Simple. But accepting any string that contains anywhere the first 3 characters of a day of the week is dangerous. No one would expect it to work that way!

    Thanks for the info, I’ll make sure to defend my inputs to parse better.

  • http://simpleprogrammer.com John Sonmez

    Thats it I’m not using Ruby.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    you were never going to use ruby, anyways, john. :)

  • Adam Meehan

    It is pretty crazy and one of the reasons I created my timeliness gem https://github.com/adzap/timeliness. The gem is also a lot faster and allows much greater control and custom formats.

  • Adam Meehan

    It is pretty crazy and it’s one of the reasons I created my timeliness gem https://github.com/adzap/timeliness. It is also much faster and allows greater control and custom formats.

  • workmad3

    Just found another interesting ‘feature’ of DateTime here:

    DateTime.parse(“10″) => #

    This works for all numeric strings >= “10″ and less than “31″ (although this depends on month, I expect). It gives you an invalid date if you just do

    DateTime.parse(“1″)

  • http://twitter.com/TheEricAnderson Eric Anderson

    Great post! Our team discovered this very same problem. Totally a pain the ass. What’s the best way to check for garbage when parsing dates? What did you end up coming up with?