Article 2DA4T CodeSOD: A Date With a Parser

CodeSOD: A Date With a Parser

by
Remy Porter
from The Daily WTF on (#2DA4T)

PastorGL inherited some front-end code. This front-end code only talks to a single, in-house developed back-end. Unfortunately, that single backend wasn't developed with any sort of consistency in mind. So, for example, depending on the end-point, sometimes you need to pass fields back and forth as productID, sometimes it's id, productId, or even _id.

Annoying, but even worse is dealing with the dreaded date datatype. JSON, of course, doesn't have a concept of date datatypes, which leaves the web-service developer needing to make a choice about how to pass the date back. As a Unix timestamp? As a string? What kind of string? With no consistency on their web-service design, the date could be passed back and forth in a number of formats.

Now, if you're familiar with the JavaScript Date datatype, you'd know that it can take most date formats as an input and convert them into a Date object, which gives you all the lovely convenience methods you might need. So, if for example, you wanted to convert a date string into a Unix timestamp, you might do something like this:

 var d = new Date(someDataThatProbablyIsADateStringButCouldAlsoBeANumber); //Could also use Date.parse return d.getTime();

That would cover 99% of cases, but PastorGL's co-worker didn't want to cover just those cases, and they certainly didn't want to try and build any sort of consistency into the web service. Not only that, since they knew that the web service was inconsistent, they even protected against date formats that it doesn't currently send back, just in case it starts doing so in the future. This is their solution:

/** * Converts a string into seconds since epoch, e.g. tp.str2timestamp('December 12, 2015 04:00:00'); * @param str The string to convert to seconds since epoch * @returns {*} */function str2timestamp(str) { if (typeof(str) == "undefined" || str.length == 0) { return; } if (typeof(str) != "string") { str = "" + str; } str = str.trim(); // already a unix timestamp if (str.match(/^[0-9]{0,10}$/)) { // TODO: fix this before january 19th, 2038 at 03:14:08 UTC return parseInt(str); } // most likely a javascript Date timestamp that is in milliseconds if (str.match(/^[0-9]{13,}$/)) { return parseInt(str) / 1000; } var ts = Date.parse(str); if (ts) { return ts / 1000; } // fix 00:XX AM|PM & 00:XX:XX AM|PM str = str.replace(/00:([0-9]{2}(:[0-9]{2})?\s*[AP]M)/i, "12:$1").replace(/([0-9]{2})([AP|M])/i, "$1 $2"); // remove any "on, at, @, or -" from the date str = str.replace(/\s*(at|@|\-|on|\|)\s*/gi, " "); str = str.replace(/\s*(mon(day)?|tue(s?day)?|wed(nesday)?|thu((rs)?day)?|fri(day)?|sat(urday)?|sun(day)?)\s*/gi, ""); str = str.replace(/([0-9]{1,2})(st|nd|rd|th)/, "$1"); // replace bad time zone if (str.match(/\s+ET$/)) { if (d.getTimezoneOffset() == 240) { str = str.replace(/\s+ET$/, " EDT"); } else { str = str.replace(/\s+ET$/, " EST"); } } str = str.trim(); var ts; ts = Date.parse(str); if (ts) { return ts / 1000; } // jan/3/2001 if (m = str.match(/!^([a-z]+)[-/ ]([0-9]+)[-/ ]([0-9]+)(.*)$!i/)) { str = m[2] + " " + m[1] + " " + m[3] + m[4]; } else if (m = str.match(/!^([0-9]+)[-/ ]([a-z]+)[-/ ]([0-9]+)(.*)$!i/)) { // 3/jan/2008 str = m[1] + " " + m[2] + " " + m[3] + m[4]; } ts = Date.parse(str); if (ts) { return ts / 1000; }};

I particularly like that, if it's not a string already, they turn it into one, because regexes are the best way to count the digits in a string, apparently.

In the end, is TRWTF this code, or the inconsistent representations of the web service endpoints?

whynotboth.jpg

otter-icon.png [Advertisement] Otter enables DevOps best practices by providing a visual, dynamic, and intuitive UI that shows, at-a-glance, the configuration state of all your servers. Find out more and download today! TheDailyWtf?d=yIl2AUoC8zAgHEW07mt5Fw
External Content
Source RSS or Atom Feed
Feed Location http://syndication.thedailywtf.com/TheDailyWtf
Feed Title The Daily WTF
Feed Link http://thedailywtf.com/
Reply 0 comments