# Friday, March 12, 2010
Handling dates in JSON responses is something many web developers struggle with. The JSON Specification doesn't specify how dates should be represented in a JSON string, so every implementation invented its own way of representing dates.

These are some of the formats in use today:
  1. {"date": new Date(ms_since_epoch) }
  2. {"date": Date(ms_since_epoch) }
  3. {"date": "Date(ms_since_epoch) }
  4. {"date": "/Date(ms_since_epoch)" }
  5. {"date": "\/Date(ms_since_epoch)\/" }
  6. {"date": "yyyy-MM-ddTHH:mm:ssZ" }
  7. {"date": "yyyy-MM-ddTHH:mm:ss" }
Formats 1 and 2 are actually invalid JSON. However, they're the only formats that were handled correctly by jQuery 1.3.2 and earlier. eval() also handles these. But again, it's not valid JSON.

That leaves the other 5 formats, which are valid according to the JSON specs.

Starting with version 1.4, jQuery's built-in JSON evaluator will check if there is a function JSON.parse() available. If it is there, it will use that function to evaluate JSON objects. If not, jQuery will use the "unsafe" eval() way of parsing JSON. JSON.parse() is a function from the json2.js file, which can be downloaded from the JSON website

The problem

JSON.parse() doesn't handle dates. At all. But it does have a way to handle non-standard values by specifying an extra parameter "reviver", which is a function that takes a value and returns the value converted to the data type of your choice.

For example: if you want to handle the ISO date format correctly, you can do this:

var parsedObject = JSON.parse(jsonData, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });


(this example is taken from the json2.js source code)

This function will check if a string value parsed from the JSON string is in a specific date format, and return a Javascript date object.

You could expand this function to handle every other possible date format, which shouldn't be too hard to do, but how do you tell jQuery to use this "reviver" function?

Well, you can't.

The solution

There's an easy solution: after including json2.js, redefine the JSON.parse() function so it passes your conversion (reviver) function to the original JSON.parse() function:
<script type="text/javascript" src="json2.js"></script>
<script>
  (function() {
     var _origParse = JSON.parse;

     JSON.parse = function(text) {
         return _origParse(text, function(key, value) {
            var a;
             if (typeof value === 'string') {
                a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                if (a) {
                  return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));
                }

                if (value.slice(0, 5) === 'Date(' && value.slice(-1) === ')') {
                   var d = new Date(value.slice(5, -1));
                   if (d) {
                     return d;
                   }
               }
            }
            return value;
         });
      }
   })();

</script>


Now when you return some JSON object to your jQuery script, dates will be parsed correctly, without having to change your code. The code snippet above handles cases 3 to 6 correctly. I'll leave it up to you to add case 7...


kick it on DotNetKicks.com
Friday, March 12, 2010 5:46:05 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0] -
 |  | 
# Friday, June 05, 2009

Read till the end, because nothing is what it seems

What is equality?

Equality means different things in different programming languages. In most modern languages (C# for example), you can define your own terms of what equality means. In others you can't.

Take javascript for example. There are actually two kinds of equality: normal equality and being identical.

To check if two variables or values are equal, you use:

if (a == b) {
  // ...
}


To check if two variables are identical, you use:

if (a === b) {
  // ...
}


Most articles (and even supposedly good books) define the latter comparison as being equal and of the same type. While this over-simplification may be true in the majority of cases, it is very inaccurate, because you have to know what "equal" means. I’m not going to talk about javascript’s normal equality operator (==), because enough has been written about that. I’ll focus on the === operator.

The correct meaning of === is that the 2 operands should be identical. This means they should reference the same object, or, in the case of value types, the values should be the same. Only numbers and booleans are value types. Strings behave as value types, but they are actually reference types.

Bringing this all together, let's look at some examples of equality in javascript:

var a = 1;
var b = 1;

alert(a == b); // true
alert(a === b); // true

b = "1";

alert(a == b); // true
alert(a === b); // false


These are the obvious ones. Now the more interesting stuff:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

alert(a === b); // false (these look equal to me, and of the same type)
alert(a === c); // true


Remember I mentioned that strings behave like value types? Now it becomes interesting:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types


And to make it really interesting:

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)


I thought strings behave like value types? Well, it depends who you ask...

EDIT: As one of the commenters (zihotki) points out, the last example adds another twist to the story. Creating a string using the String() object constructor actually doesn't create a variable of type "string", but of type "object". But you can use the object as a string. If you are unaware of this behavior, you can easily shoot yourself in the foot without knowing it.

kick it on DotNetKicks.com
Friday, June 05, 2009 10:45:55 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [4] -