views:

1713

answers:

8

Hi,

I have a controller action that effectively simply returns a JsonResult of my model. So, in my method I have something like the following:

return new JsonResult(myModel);

This works well, except for one problem. There is a date property in the model and this appears to be returned in the Json result like so:

"\/Date(1239018869048)\/"

How should I be dealing with dates so they are returned in the format I require? Or how do I handle this format above in script?

Thanks

A: 

See this thread:

http://forums.asp.net/p/1038457/1441866.aspx#1441866

Basically, while the Date() format is valid javascript, it is NOT valid JSON (there is a difference). If you want the old format, you will probably have to create a facade and transform the value yourself, or find a way to get at the serializer for your type in the JsonResult and have it use a custom format for dates.

casperOne
Think you meant "while the new Date() format is valid javascript" [note the "new" keyword]?
JPot
A: 

If you doing eval("(" + jsonResult + ")") on the result, it should work. You may be best to, as mentioned, do a cusom serialization of the date/time to a client specific GMT/UTC string. Dates aren't defined within the JSON specification, but using Date(TIME_T) will work unless you are doing client-side validation of JSON responses.

Edit:example


var o = eval("({ dtm: new Date('1990/01/05') })");
alert(o.dtm);

//milliseconds from 1970-01-01 to 1990-01-05 aka TIME_T * 1000
o = eval("({ dtm: new Date(631522800000) })");
alert(o.dtm); 

both work...

Tracker1
Alas, it doesn't work.
Craig Stuntz
not for me either :-(
Simon_Weaver
added sample, should be 'new Date(Time_T * 1000)' which is pretty easily calculated.
Tracker1
+8  A: 

Just to expand on CasperOne's answer.

The JSON spec does not account for Date values. MS had to make a call, and the path they chose was to exploit a little trick in the javascript representation of strings: the string literal "/" is the same as "\/", and a string literal will never get serialized to "\/" (even "\/" must be mapped to "\\/").

See http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2 for a better explanation (scroll down to "From JavaScript Literals to JSON")

One of the sore points of JSON is the lack of a date/time literal. Many people are surprised and disappointed to learn this when they first encounter JSON. The simple explanation (consoling or not) for the absence of a date/time literal is that JavaScript never had one either: The support for date and time values in JavaScript is entirely provided through the Date object. Most applications using JSON as a data format, therefore, generally tend to use either a string or a number to express date and time values. If a string is used, you can generally expect it to be in the ISO 8601 format. If a number is used, instead, then the value is usually taken to mean the number of milliseconds in Universal Coordinated Time (UTC) since epoch, where epoch is defined as midnight January 1, 1970 (UTC). Again, this is a mere convention and not part of the JSON standard. If you are exchanging data with another application, you will need to check its documentation to see how it encodes date and time values within a JSON literal. For example, Microsoft's ASP.NET AJAX uses neither of the described conventions. Rather, it encodes .NET DateTime values as a JSON string, where the content of the string is \/Date(ticks)\/ and where ticks represents milliseconds since epoch (UTC). So November 29, 1989, 4:55:30 AM, in UTC is encoded as "\/Date(628318530718)\/".

A solution would be to just parse it out:

value = new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10));

However I've heard that there is a setting somewhere to get the serializer to output DateTime objects with the new Date(xxx) syntax. I'll try to dig that out.

JPot
Thanks, where would the parsing go though?
Jon Archway
The code I posted is JavaScript. You would put it in your client code.
JPot
You can shorten the js to new Date(parseInt(dateString.replace(/\/Date\((\d+)\)\//gi, "$1")))
David Kemp
In fact the regex is more correct asreplace(/\/Date\((-?\d+)\)\//gi, "$1")since the date may be represented as a -ve number too
Dokie
+1  A: 

Here's my solution in Javascript - very much like JPots', but shorter (and possibly a tiny bit faster):

value = new Date(parseInt(value.substr(6)));

"value.substr(6)" takes out the "/Date(" part, and the parseInt function ignores the non-number characters that occur at the end.

EDIT: I would change this to a comment under JPots's answer, but commenting on that answer appears to be closed to me.

Roy Tinker
A: 

Not the most elegant way but this worked for me:

var ms = date.substring(6, date.length - 2);
var newDate = formatDate(ms);


function formatDate(ms) {

    var date = new Date(parseInt(ms));
    var hour = date.getHours();
    var mins = date.getMinutes() + '';
    var time = "AM";

    // find time 
    if (hour >= 12) {
        time = "PM";
    }
    // fix hours format
    if (hour > 12) {
        hour -= 12;
    }
    else if (hour == 0) {
        hour = 12;
    }
    // fix minutes format
    if (mins.length == 1) {
        mins = "0" + mins;
    }
    // return formatted date time string
    return date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + hour + ":" + mins + " " + time;
}
gmcalab
A: 

I had the same problem and instead of returning the actual date value I just used ToString("dd MMM yyyy") on it. Then in my javascript I used new Date(datevalue), where datevalue may be "01 Jan 2009".

Joe
A: 

I have been working on a solution to this issue as none of the above answers really helped me. I am working with the jquery week calendar and needed my dates to have time zone information on the server and locally on the page. After quite a bit of digging around, I figured out a solution that may help others.

I am using asp.net 3.5, vs 2008, asp.net MVC 2, and jquery week calendar,

First, I am using a library written by Steven Levithan that helps with dealing with dates on the client side, Steven Levithan's date library. The isoUtcDateTime format is perfect for what I needed. In my jquery AJAX call I use the format function provided with the library with the isoUtcDateTime format and when the ajax call hits my action method, the datetime Kind is set to local and reflects the server time.

When I send dates to my page via AJAX, I send them as text strings by formatting the dates using "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz". This format is easily converted client side using

var myDate = new Date(myReceivedDate);

Here is my complete solution minus Steve Levithan's source, which you can download:

Controller:

public class HomeController : Controller
{
    public const string DATE_FORMAT = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz";

    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    public ActionResult About()
    {
        return View();
    }


    public JsonResult GetData()
    {
        DateTime myDate = DateTime.Now.ToLocalTime();

        return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }

    public JsonResult ReceiveData(DateTime myDate)
    {
        return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }
}

Javascript:

<script type="text/javascript">

function getData() { $.ajax({ url: "/Home/GetData", type: "POST", cache: "false", dataType: "json", success: function(data) { alert(data.myDate); var newDate = cleanDate(data.myDate); alert(newDate); sendData(newDate); } }); }

function cleanDate(d) { if (typeof d == 'string') { return new Date(d) || Date.parse(d) || new Date(parseInt(d)); } if (typeof d == 'number') { return new Date(d); } return d; }

function sendData(newDate) { $.ajax({ url: "/Home/ReceiveData", type: "POST", cache: "false", dataType: "json", data: { myDate: newDate.format("isoUtcDateTime") }, success: function(data) { alert(data.myDate); var newDate = cleanDate(data.myDate); alert(newDate); } }); }

// bind myButton click event to call getData $(document).ready(function() { $('input#myButton').bind('click', getData); });

I apologize for the formatting of the javascript... doesn't want to seem to render nicely. I hope this quick example helps out others in the same situation I was in. At this time it seems to work very well with the Microsoft JSON Serialization and keeps my dates correct across timezones.

Jesse