1

I am successfully calling $http.get in my Angular controller and getting back a large json object. Like this:

var self=this;
self.createNewStatusReport = function()
{
    $http.get(self.NewStatusReportUrl).then(function(response)
    {
        self.AngularModel.StatusReportJsons.push(response.data);
    });
};

The returned json includes many dates. The format, unfortunately, looks like this: /Date(1420099200000)/. Here's a simplified piece of the response data:

{
    "StatusReportID": 25, 
    "DueDate": "/Date(1468566000000)/", 
    "SubmitDate": null,
    "WorkStatement": [
    {
        "WorkStatementID": 41, 
        "Milestone": [
        {
            "MilestoneID": 501,
            "ContractorComments": null, 
            "Title": "Do some specific piece of work", 
            "StartDate": "/Date(1459494000000)/", 
            "EndDate": "/Date(1469948400000)/", 
            "IsCompleted": false, 
            ...

I also have (some) control over the server side, but can't change the date types in StatusReportJson from DateTime? to string. It is MVC written in C#:

[HttpGet]
public JsonResult NewStatusReport(string agreementNumber)
{
    var statusReport = StatusReports.GetStatusReport(25);
    return Json(new StatusReportJson(statusReport), JsonRequestBehavior.AllowGet);
}

Is there an easy way to recursively convert these date strings to date objects? The response data comes to me already parsed; can I insert my own parse step? On the server side, can I make the dates come in as date strings that look more like "2016-04-01T00:00:00" or simply "2016-04-01" without modifying my StatusReportJson object's data types? Others have already solved the conversion problem here: How do I format a Microsoft JSON date? I need help structuring where to put the solution so it is effective in my case. Thanks for helping!

Community
  • 1
  • 1
rjacobsen0
  • 1,287
  • 13
  • 25
  • Simple to loop over data and convert each instance before pushing to array. Having to do client side data transformations is not uncommon – charlietfl Jul 02 '16 at 17:25
  • That creates a dependency I would rather not have. If the StatusReportJson changes on the server side, which it is likely to do, I don't want to have to change the client side to match. Makes for less maintainable code. – rjacobsen0 Jul 02 '16 at 17:36
  • I have no idea how you can change things at server-side. But at client-side, you could just use a filter that transforms the /Date()/ string into a number, and then passes that number to the standard date filter. – JB Nizet Jul 02 '16 at 17:36
  • *"Makes for less maintainable code"* ... doesn't make sense. – charlietfl Jul 02 '16 at 17:39
  • Interesting idea. Are you talking about an Angular filter? (I'm not very familiar with them yet.) Assuming I could look up how to write one, how would I put it in place to work here, before the json is parsed? – rjacobsen0 Jul 02 '16 at 17:40
  • If use an angular filter would only need it in view `{{milestone.StartDate | dateParsefilter}}`. If need date objects such as for datepickers then do a transform of your data first when you receive it – charlietfl Jul 02 '16 at 17:45
  • Thanks for the input. But I get an object. The string has already been deserialized by the time I get it. Plus, I need real date objects, not simply to display bad dates nicely to the user. I'm doing more with the dates than just displaying them. – rjacobsen0 Jul 02 '16 at 17:52
  • So iterate through that object and do a transform of the values for all the date related fields – charlietfl Jul 02 '16 at 18:29

3 Answers3

1

Hope this solves your problem:

$scope.DateIssue = function(input) {
input = '/Date(1468566000000)/';
$scope.formatedDate = input.toString().replace('/Date(', '').replace(')/', '');
$scope.formatedDate = $filter('date', $scope.formatedDate);
return $scope.formatedDate

};

Prianca
  • 484
  • 2
  • 8
  • Thanks for this. Hmmm. But I have an object, not a string. Is there a way to run a function which pre-processes the response before angular does its json deserialization? – rjacobsen0 Jul 02 '16 at 18:54
  • you can convert that object as string and use this function. – Prianca Jul 02 '16 at 19:01
0

Here's how I solved this. First, I used the JavaScript serializer on the server side like this:

[HttpGet]
public JsonResult NewStatusReport(string agreementNumber)
{
    var statusReport = StatusReports.GetStatusReport(25);
    var statusReportJson = new StatusReportJson(statusReport);
    var json = new JavaScriptSerializer().Serialize(statusReportJson);
    return Json(json, JsonRequestBehavior.AllowGet);
}

Then, on the client side, I pulled in code from this excellent page http://erraticdev.blogspot.com/2010/12/converting-dates-in-json-strings-using.html and called it like this:

var self = this;
$http.get(self.NewStatusReportUrl).then(function(response)
{
    var jsonObject = jQuery.parseJSON(response.data, true);
    self.AngularModel.StatusReportJsons.push(jsonObject);
});

Thanks to Robert Koritnik for the answer! And thanks to everyone who helped!

rjacobsen0
  • 1,287
  • 13
  • 25
0

A little late, but I thought helpful. Most of the suggestions were to locally convert it. In my case the date is returned as string (with Timezone info).

E.g. '2018-06-01T13:57:41.3867449Z'

So I created a common service for getJson & PostJson and in handled responses there with '$q'.

if (response.data) {
    // Check for datetime object & convert  
    // TODO:: *** May impact performance, so check later or use momentJS
    //console.info('Before-convertDateStringsToDates:', new Date());
    appUtils.convertDateStringsToDates(response.data);
    //console.info('After-convertDateStringsToDates:', new Date());
}

My appUtil method is as below:

// --------------------------------------------------------------------------------
// Ref: http://aboutcode.net/2013/07/27/json-date-parsing-angularjs.html
// Function to convert string (as ReGex format) property to date - used as generic in Common Serivce.
convertDateStringsToDates(input) {
    // ReGex for format we receive from Web API e.g. "1980-05-09T00:00:00Z"
    var jsonDateTimeFormatRegex = "((?:2|1)\\d{3}(?:-|\\/)(?:(?:0[1-9])|(?:1[0-2]))(?:-|\\/)(?:(?:0[1-9])|(?:[1-2][0-9])|(?:3[0-1]))(?:T|\\s)(?:(?:[0-1][0-9])|(?:2[0-3])):(?:[0-5][0-9]):(?:[0-5][0-9]))";
    // Ignore things that aren't objects.
    if (typeof input !== "object") return input;

    for (var key in input) {
        if (!input.hasOwnProperty(key)) continue;

        var value = input[key];
        var match;
        // Check for string properties which look like dates.
        // TODO: Improve this regex to better match ISO 8601 date strings.
        if (typeof value === "string" && (match = value.match(jsonDateTimeFormatRegex))) {
            // Assume that Date.parse can parse ISO 8601 strings, or has been shimmed in older browsers to do so.
            //console.info(match[0]);
            var date = new Date(match[0]); // Need to convert to UTC. Ref: https://stackoverflow.com/a/14006555/1161069
            input[key] = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));

            // var milliseconds = Date.parse(match[0]);
            // if (!isNaN(milliseconds)) {
            //     input[key] = new Date(milliseconds);
            // }
        } else if (typeof value === "object") {
            // Recurse into object
            this.convertDateStringsToDates(value);
        }
    }
}

Now, after each GET or POST request, I get my JSON with proper dates.

Just in case someone wants to know Web API code, it's as below:

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services

    //var cors = new System.Web.Http.Cors.EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);

    // Web API routes
    config.MapHttpAttributeRoutes();

    // other code ......

    var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
    //jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

    JsonSerializerSettings jSettings = new JsonSerializerSettings()
    {
        Formatting = Formatting.None
    };
    jSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    jsonFormatter.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
    jsonFormatter.SerializerSettings = jSettings;

    // rest of the code....
}
NikhilP
  • 53
  • 2
  • 11