As a part of our Free Dojo Support initiative, we received the following question about serialization dates from forms to JSON:

The Question

“In working with dojo.toJson(), I stumbled upon a peculiarity, perhaps a bug. Using the dijit.form.DateTextBox, selecting a valid date, calling frmX.get(“value”) shows that everything is fine. But using this value and calling dojo.toJson( frmX.get(“value”)) always delivers an empty object {}. Debugging the code I saw the problem: Date is an Object, but has no serialization (at least with chrome). So I tried something like this:

if (xyz.isDate(it)) { var dateString = dojo.date.locale.format(it, {formatLength: “long”, selector: “date”, datePattern: ‘dd.MM.yyyy’}); return dojo._escapeString(dateString); }

Am I doing something wrong with getting the values of a form and serializing it to JSON? Did I miss a dojo function for dates (dojo.isDate(object)) and would it be correct to ask the proto object whether it is a ‘Date’?”

Our Answer

To answer the first part of the question, Dojo 1.6 and earlier lack support for proper serialization of dates. This was resolved for the upcoming Dojo 1.7 release. In 1.7, Dojo’s JSON parser will conform to native ECMAScript date serializing standards, serializing dates to ISO format in UTC. We’ll start by explaining how to solve this with Dojo 1.7, and then also explain approaches for 1.6 and earlier.

Dojo 1.7

In Dojo 1.7, all dates are automatically serialized in this way, and native JSON mechanisms are used whenever possible.

If we don’t like the standard date serialization mechanism, we can also provide a custom serialization of dates by adding a toJSON method to the date object, with our own implementation of converting a date to a string. To follow the dd.MM.yyyy pattern suggested in the question, we could write:

define(["dojo/json"], function(JSON){
  var date = frmX.get("value");
  date.toJSON = function(){
    return dojo.date.locale.format(this, {formatLength: "long", selector: "date", datePattern: 'dd.MM.yyyy'});
  };
  var jsonSerializedObject = JSON.stringify({someDate:date});
  // jsonSerializedObject will be JSON with the date serialized with our serializer
});

We could also apply this serialization to all dates in our own application by adding the toJSON method to the native Date prototype:

  Date.prototype.toJSON = function(){
    return dojo.date.locale.format(this, {formatLength: "long", selector: "date", datePattern: 'dd.MM.yyyy'});
  };

Now, anytime we run JSON serialization, the dates will be serialized with a dd.MM.yyyy pattern. While Dojo does not extend native prototypes, this may be more convenient within your own application.

Dojo 1.6 and earlier

In Dojo versions 1.6 and earlier, we could also provide our own custom serializer. However, since dojo.toJson predated the ECMAScript standardization of JSON serialization, we used “json” as the method name instead of toJSON. This is applied in the same way as toJSON for altering date serializations, except we need to escape the string:

  var date = frmX.get("value");
  date.json = function(){
    return dojo.date.locale.format(this, {formatLength: "long", selector: "date", datePattern: 'dd.MM.yyyy'});
  };
  var jsonSerializedObject = dojo.toJson({someDate:date});
  // jsonSerializedObject will be JSON with the date serialized with our serializer

Again, we could also apply this serialization to all dates by adding the json method to the native Date prototype:

  Date.prototype.json = function(){
    return dojo.date.locale.format(this, {formatLength: "long", selector: "date", datePattern: 'dd.MM.yyyy'});
  };

If you want to use standard JSON ISO/UTC serialization for your dates, you can simply copy a few lines of code from the new (Dojo 1.7 beta) dojo/json.js module and use it in any earlier versions of Dojo:

Date.prototype.json = function(){
  var it = this;
  return '{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z'.replace(/\{(\w+)(\+)?\}/g, function(t, prop, plus){
    var num = it["getUTC" + prop]() + (plus ? 1 : 0);
    return num < 10 ? "0" + num : num;
  });
};

It should be easy to see how you can alter the ISO formatting of the UTC dates in this example as well.

Checking for Date Types

This week's question also asked the correct way to determine if a value is a date. This answer is very simple: JavaScript's instanceof operator works great!

if(value instanceof Date){
  // value is a Date
}

You should note that if the value comes from another frame or window, it could fail this test, but such cross-frame date passing is rare and not advised. For the vast majority of users, the technique above is the fastest and most correct approach. In fact, in general it is a good programming practice to utilize native type checking mechanisms rather than using Dojo's type checking functions (like dojo.isString(value)) which are used internally to deal with certain cross-frame setups. The native type checking mechanisms (like typeof value == "string") are much faster, and their usage should certainly be preferred in most circumstances.

Next Question Please!

Have a Dojo question you’re just dying to ask? Get your free Dojo support now! Or sign-up for the Best JavaScript and Dojo Support available to get all of your questions answered all the time!