Javascript: Convert a Date object to an ISO 8601 formatted string

 
One of my technical New Year’s Resolutions is to clean up my collection of code snippets. Over the years I’ve built up a sizeable collection but many of them are either not very useful anymore or could be improved. After deleting those that are no longer useful I am cleaning up the code of those that are left, making sure they validate in the latest version of JSLint, before posting them to this blog and sharing them on Gist and Snipplr, with a jsFiddle thrown in where useful.

The first snippet posted is a simple shim to convert a Javascript date object to an ISO 8601 formatted string. The format of these strings is comprehensively detailed  on the W3C website but, simply put, it looks like this:


Screenshot_1_13_13_9_18_PM-2

As well as being a simple, easy-to-understand string format it’s well-supported in many languages which makes it useful for data interchange. Most modern languages have a function to take a date and return an ISO 8601 string. In Javascript, this function is ‘ISODateString’ but, unfortunately, it isn’t implemented in all commonly used browsers – significantly, Internet Explorer 8 and earlier don’t include it.

The simple solution is a small function that will use the ‘ISODateString’ when it is available and fallback to a d-i-y solution when it isn’t. In that way we get a working solution now and the performance and reliability improvements of a native browser solution when it is available without the need to change our code.


if (typeof Date.prototype.toISOString !== 'function') {

    (function () {

        'use strict';

        // Function which takes a 1 or 2-digit number and returns
        // it as a two-character string, padded with
        // an extra leading zero, if necessary.
        function pad(number) {
            var r = String(number);
            if (r.length === 1) {
                r = '0' + r;
            }
            return r;
        }

        Date.prototype.toISOString = function () {
            return this.getUTCFullYear()
                + '-' + pad(this.getUTCMonth() + 1)
                + '-' + pad(this.getUTCDate())
                + 'T' + pad(this.getUTCHours())
                + ':' + pad(this.getUTCMinutes())
                + ':' + pad(this.getUTCSeconds())
                + '.' + String((this.getUTCMilliseconds() / 1000).toFixed(3)).slice(2, 5)
                + 'Z';
         };

    }());
}

The structure of the snippet is straightforward. In line 1 I check if the native function exists. If it does then nothing more needs to be done. If it doesn’t then I create a new function with the same name as the native one which takes a date object and concatenates together its constituent parts to make the ISO string. As ISO 8601 requires that Month, Day, Hours, etc. are two digits there is another function – ‘Pad’ – which takes a number and ensures it is two digits long by padding with a leading zero, if necessary. By wrapping the whole thing in an anonymous function I ensure that ‘Pad’ is not globally available and so won’t clash with any existing function of the same name.
A few minor tweaks to the layout and the addition of ‘use strict’ ensures that it validates cleanly in the latest version of JSLint (Edition 2012-12-31).

The source for this function can be downloaded from Gist or Snipplr.
You can also try it out in jsFiddle.


More:

Javascript: Accurate timing is (almost) here

If you’ve ever tried to optimize or locate a bottleneck in your Javascript code you’ve most likely ended up using Date().getTime(). As this function returns the number of milliseconds since the 1st of January, 1970 we can easily determine the total run time of the code we wish to test by taking two readings, one immediately prior to the code to be tested and and one immediately after. A simple subtraction will then give us the total run time in milliseconds:


var start, end;

start = (new Date()).getTime();

// Run a test

end = (new Date()).getTime();

alert(end - start);

While this is easy to use and consistently implemented across browsers it has a three flaws that make it less than ideal for benchmarking – the value returned is an integer so it’s useless for timing anything that takes less than a millisecond, it’s derived from the system clock which may be unstable or subject to adjustment and, depending on the operating system and browser, can be significantly wrong.

With the recent release of Google Chrome 20 to beta we now have the opportunity to use a new, more reliable and more precise timer – High Resolution Time a.k.a.  performance.now. More specifically, we can use the Chrome, vendor-prefixed, version – performance.webkitNow.

As performance.webkitNow returns the number of milliseconds since the navigationStart of the page and is not tied to the system clock we get more reliable timings. Better still, it returns the elapsed time as a double with microseconds in the fractional part, allowing us to have more accurate, sub-millisecond, timings.

If we rewrite the previous example to use High Resolution Time instead of Date().getTime() our code would be:


var start, end;

start = window.performance.webkitNow();

// Run a test

end = window.performance.webkitNow();

alert(end - start);

Running this example would give us results such as 0.005999987479299307 whereas our original, Date-based, example consistently returned zero.

Of course, it’s never so simple. This will work fine in Chrome 20 Beta but will error in all other browsers (and earlier versions of Chrome). To allow for other, as yet to be released, vendor-prefixed versions and to be usable today we must create a small shim function:

 var now = (function() {

// Returns the number of milliseconds elapsed since either the browser navigationStart event or
// the UNIX epoch, depending on availability.
// Where the browser supports 'performance' we use that as it is more accurate (microsoeconds
// will be returned in the fractional part) and more reliable as it does not rely on the system time.
// Where 'performance' is not available, we will fall back to Date().getTime().

var performance = window.performance || {};

performance.now = (function() {
return performance.now    ||
performance.webkitNow     ||
performance.msNow         ||
performance.oNow          ||
performance.mozNow        ||
function() { return new Date().getTime(); };
})();

return performance.now();

});   

This will use the “official” performance.now, if it is available. If not it will try each of the vendor prefixes, then ultimately fall back to Date().getTime(), allowing for all eventualities now or in the near future. Using this function is no more difficult that our previous examples:


var start, end;

start = now();

// Run a test

end = now();

alert(end - start);

 

You can try out this function on jsFiddle or grab it from Gist or Snipplr.

 

More: