#DatatypeCastingProblems

Warning: This post is an informative programming excerpt

Changing the datatype of a variable from one form to another can often be tricky. This is especially true for dynamic languages like JavaScript.

Recently, I had to run a DB migration that was meant to convert existing┬átext dates (for e.g. ‘2016-01-18T19:34:56.264Z’) in the table to actual DB date objects. The migration to do this was written in JS.

Unfortunately, the text dates could either be ISO formatted or a timestamp (Epoch-based). You would think that doing something like:

var myDateObj = new Date(myDateString);

would just simply work. Well, unfortunately this is the case:

function getDateObj(date) {
    return new Date(date);
}

getDateObj('2016-01-18T19:34:56.264Z'); // works fine
getDateObj('1453145696264'); // throws an exception

Well, annoying as it is, the solution seems quite straightforward right – try to cast whatever I get in getDateObj to an integer. If it throws, use the string, if not, use the parsed integer.

function getDateObj(date) {
    var validDate;
    try {
        validDate = parseInt(date);
    } catch(e) {
        validDate = date;
    } finally {
        return new Date(validDate);
    }
}

Makes sense doesn’t it? In fact, for both of the above data sets, you get Date objects without an exception.

Except, the Date object created from the ISO string has the wrong date! Wtf???

The Date object will represent a date that is 2016ms from epoch time. Why is that?

Well, turns out the issue is with our faulty assumption that parseInt will throw (something that I have become accustomed to from Java and C++). According to MDN Docs:

“If parseInt encounters a character that is not a numeral in the specified radix, it ignores it and all succeeding characters and returns the integer value parsed up to that point.”

So, an ISO date string will be parsed up to the first hyphen it encounters. Hence the catch block is never entered ­čÖü

To fix the issue, I was told to use Date.parse instead and test for NaN (which will happen for a value like ‘1453145696264’). If it is NaN use parseInt, otherwise use the string as is.

Well, that was an interesting experience (especially because I nearly wrecked a production database because of this :P).
Moral – Tread carefully when attempting to make a dynamically-typed language behave like a statically-typed one.

r.gideonthomas@gmail.com / January 19, 2016 / JavaScript / 0 Comments