JavaScript Date Tips

The other night at the Hudson Software Craftsmanship meeting at the Falafel Software training center in Hudson, Ohio, I did the Red Pencil Kata using JavaScript. Although I’ve run into it in the past, I was stuck for a little while (I was the odd man out without a pairing partner to help find these things faster) due to one of JavaScript’s “fun” date conventions. Being a C# developer primarily, there are many small things I have to remember that are different between JavaScript and C# (like where to declare variables, for instance). In this case, it was the code for generating a particular date that bit me. At one point, I wanted to generate a date that was over 30 days in the past (relative to the current date, which was 16 July 2014), so I wrote this:

var day1 = new Date(2014, 6, 14); // javascript

If I were in C#, this code would have worked fine:

var day1 = new DateTime(2014, 7, 11); // C#

You see, the folks who wrote C# were not insane, and so they didn’t arbitrarily make the middle ‘month’ parameter 0-based, like the JavaScript folks did. In my kata, it was important that certain things happen around the 30-day window, and of course my silly mistake had created a date that was only 3 days in the past, not 32. Oops. Of course, you should be able to avoid this by using a string, right? That’s what some of my fellow developers suggested. What do you suppose this yields?

var day1 = new Date(“2014-07-01”); // javascript

If you answered 30 June 2014, you’re right! Of course, that’s just what you would expect, too. WAT?

Of course, if you use something hideous like this, it works correctly (in the United States, which expects M/D/Y format):

var day1 = new Date(“7/14/14”); // javascript

This, too, will give you what you expect, though it’s a bit verbose:

var day1 = new Date(“July 14, 2014”); // javascript

Go ahead and play with these options yourself here:

Reading Dates (in older browsers)

This has been fixed with ECMAScript 5, but older browsers will still misbehave. If you try to read a zero-padded date, such as “09” for September, using parseInt, you may get an unexpected result because parseInt assumes zero-prefixed strings are in octal format. To avoid this potential issue, always pass in the second parameter to parseInt (for which you’ll typically want to pass a 10). Alternately, you can override parseInt so that if it is called with just one argument it will always use 10 for the radix, on all browsers, as shown here. The fiddle below demonstrates the issue – if you’re using a modern browser, the result of the first operation should be 9. Try it on an older browser and see what you get.

Any other date-related tips you’d like to share? I’d love to hear them in the comments.

  • Jason Follas

    I never work with dates directly in JavaScript these days (unless absolutely necessary). I try to wrap them in moment.js, which eliminates many of the WATs and adds more functionality.

  • jbrinkman

    +1 Moment.js It is the date lib JS should have had :)

  • Brendan Enrick

    Steve, you did not mention the coincidence about this. I’ve included it below:

    Early on in the meeting, Todd (@ropog) and Scott (@sdepouw) were talking about this piece of insanity. Todd mentioned it to me also, and we talked a bit about it.

    To our delight, when Steve couldn’t figure out why his code was not working, I noticed that he was using the date constructor and had this exact issue! What are the odds that the meeting we’re talking about the issue is the same one Steve runs into it?

  • ssmith

    Heh, next time you need to have that conversation a little louder.

  • ssmith

    Hmm, maybe I’ll add that to my standard set of scripts to use in local JavaScript code katas (along with mocha, chai, etc.). I’ve used it in production/web applications, but it hasn’t been part of my “must have every time” list of JS utilities (with obvious consequences). Thanks!

  • Artem Saveliev

    Time zone / offset support is also very “interesting” in JS – toLocaleString returns time zone, but there’s no reverse method to parse it back to datetime object (as javascript datetime object doesn’t have time zone properties). In fact, the only time zone you can use is the computers time zone…

    When I encountereed this, I wanted to use a library – and only xdate was out there and was pretty big. Now xdate is dead, and moment.js is alive… just shows that dealing with dates sucks. The general rule is that if you want to write your own date logic – don’t. This rule doesn’t work with javascript though…

  • Matt B

    +1 for moment.js. Makes working with dates much more robust and takes away the hassle of date manipulation. You can just create a new moment and subtract 30 days from it.

  • Chris Wagner

    +1 for moment.js.

    More JavaScript Date fun: getFullYear() vs. getYear(). getFullYear() was introduced to get the year component of a date, because getYear() actually returns the number of years since 1900, despite that not being what you pass into the Date constructor.

  • Dan Dart

    Only thing I’ve needed to extend about days was adding Date.prototype.toMySQL().

  • pwkad

    I’m pretty surprised that this isn’t one of those must have every time libs. The first thing I ever do when I see a datetime in JS is add moment. It’s so lightweight and helpful it makes no sense not to…

  • Šime Vidas

    Ah Americans, with their negative timezone offset issues… adorable :-P