Note: This post is part of a long-running series of posts covering the union of jQuery and ASP.NET: jQuery for the ASP.NET Developer.

Topics in this series range all the way from using jQuery to enhance UpdatePanels to using jQuery up to completely manage rendering and interaction in the browser with ASP.NET only acting as a backend API. If the post you're viewing now is something that interests you, be sure to check out the rest of the posts in this series.

A calendar

The problem of how to handle dates in JSON is one of the more troublesome issues that may arise when directly calling ASP.NET AJAX web services and page methods.

Unlike every other data type in the language, JavaScript offers no declarative method for expressing a Date. Consequently, embedding them within JSON requires a bit of fancy footwork. Since the question of how I handle this problem is something asked often in emails and in comments on other posts here, I want to address the topic with its own post.

To that end, I will attempt to explain what exactly the problem is with dates in JSON, how ASP.NET AJAX solves it, and my alternative solution that I believe is easier and works just as well in most cases.


What’s the problem?

The fundamental problem is that JavaScript does not provide a way to declaratively express Date objects. You may previously have seen this described as (the lack of) a Date literal.

What are literals? To illustrate, these are literals for several other data types:

// String
'foo';
 
// Number
3.14;
 
// Boolean
true;
 
// Array
[1, 2, 3, 5, 7];
 
// Object
{ pi: 3.14, phi: 1.62 };

Unfortunately, when it comes to dates, the lack of a literal means that the only way to create one is by explicitly initializing a Date object:

// Correct.
new Date('4/26/09');
 
// Correct (the month is 0 indexed, hence the 3).
new Date(2009, 3, 26);
 
// Incorrect. This is a string, not a Date.
'4/26/09';

While this limitation is fine when writing client-side JavaScript code, it leaves us without a good way to transmit dates within JSON objects.

How ASP.NET AJAX handles it

While the lack of a date literal is a problem, it’s certainly not without solution.

In fact, ASP.NET AJAX already handles this if you’re using MicrosoftAjax.js to call your services. You may not have even noticed as server-side DateTime values are transparently converted into JavaScript Date objects on the client-side.

For example, consider this web service:

[System.Web.Script.Services.ScriptService]
public class DateService : System.Web.Services.WebService
{
  [WebMethod]
  public DateTime GetDate()
  {
    return new DateTime(2009, 4, 26);
  }
}

If you consume that web service with jQuery (or any method that circumvents the ScriptManager), you’ll find that ASP.NET AJAX serializes the DateTime as an escaped JavaScript Date initializer:

{"d":"\/Date(1240718400000)\/"}

Note: If you’re unsure about why the “d” is there, be sure to see my recent post about this security feature which was added in ASP.NET 3.5.

On the client-side, MicrosoftAjax.js uses a regular expression to isolate any Date constructors and then eval() to initialize Date objects. The end result is that proper JavaScript Date objects are instantiated for every DateTime value returned.

However, if you’re not using MicrosoftAjax.js (i.e. the ScriptManager) to call your services, you’ve got a bit of a mess to decode. You can use regex machinations to work around the problem, but is that really necessary?

How I handle it

Consider why you want to send a DateTime to the client-side to begin with. Most often, you’re displaying a string representation of it and have no need for the proper JavaScript Date object.

What’s more, if you end up with a JavaScript Date object, you’ll probably use additional code or a JavaScript library to display it in a user-friendly format.

As much as I appreciate a clever workaround, I’d much rather avoid the problem completely. Rather than jump through all of these hoops to instantiate a JavaScript Date object on the client-side and then format it, I suggest simply returning a formatted string.

For example, we might modify the previous example like so:

[System.Web.Script.Services.ScriptService]
public class DateService : System.Web.Services.WebService
{
  [WebMethod]
  public string GetDate()
  {
    return new DateTime(2009, 4, 26).ToLongDateString();
  }
}

Now, calling the service will return this JSON:

{"d":"Sunday, April 26, 2009"}

No more regular expressions. No more JavaScript Date objects. No more worrying about formatting the data on the client-side.

Even better, no functionality is lost. If we need to instantiate Dates, we still can.

Still want Dates?

Even if you do end up needing JavaScript Date objects, DateTime strings are sufficient for instantiating them. JavaScript’s Date constructor is very flexible:

// ASP.NET AJAX form
var foo = new Date(1240718400000);
 
// DateTime.ToLongDateString() form
var bar = new Date('Sunday, April 26, 2009');
 
// DateTime.ToShortDateString() form
var baz = new Date('4/26/2009');
 
// true!
foo === bar === baz;

By delaying string-to-Date conversions until truly necessary, we save effort on the server- and client-side. Not only that, but we have the option of retaining both the formatted string and the JavaScript Date to use as desired.

The best of both worlds.