38

I've serialized an object using Newtonsoft's JSON serializer, and the DateTime has come through as:

/Date(1237588418563+0000)/

When I $.evalJSON() on that, it is an object but I can't find any normal Date methods like toUTCString on it.

Any ideas what I can do with this?

James Newton-King
  • 48,174
  • 24
  • 109
  • 130
tags2k
  • 82,117
  • 31
  • 79
  • 106

7 Answers7

80

Use one of the JsonConverters that come with Json.NET for working with dates to get a better format. JavaScriptDateTimeConverter will automatically give you a JavaScript date.

public class LogEntry    
{    
  public string Details { get; set; }    
  public DateTime LogDate { get; set; }
}

[Test]
public void WriteJsonDates()
{    
  LogEntry entry = new LogEntry    
  {    
    LogDate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc),    
    Details = "Application started."    
  };    


  string defaultJson = JsonConvert.SerializeObject(entry);    
  // {"Details":"Application started.","LogDate":"\/Date(1234656000000)\/"}     

  string javascriptJson = JsonConvert.SerializeObject(entry, new JavaScriptDateTimeConverter());    
  // {"Details":"Application started.","LogDate":new Date(1234656000000)}

  string isoJson = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter());    
  // {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}    
}

Documentation: Serializing Dates in JSON with Json.NET

James Newton-King
  • 48,174
  • 24
  • 109
  • 130
  • 4
    For reference, the namespace on IsoDateTimeConverter is Newtonsoft.Json.Converters and on JsonConvert.SerializeObject it is Newtonsoft.Json – Jarrett Widman Mar 06 '12 at 05:51
16

I came up with a different approach which might be useful to some. Basically I create my own CustomDateConverter that I call when I need it. The converter takes 2 parameters, a date format e.g. yyyy-MM-dd HH:mm:ss and a TimeZoneInfo, which allows me to convert the date from UTC to the user's time zone:

public class JSONCustomDateConverter : DateTimeConverterBase
{
    private TimeZoneInfo _timeZoneInfo;
    private string _dateFormat;

    public JSONCustomDateConverter(string dateFormat, TimeZoneInfo timeZoneInfo)
    {
        _dateFormat = dateFormat;
        _timeZoneInfo = timeZoneInfo;
    }
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime(value), _timeZoneInfo).ToString(_dateFormat));
        writer.Flush();
    }

You can use it like this:

 var jsonString = JsonConvert.SerializeObject(myObject, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = new List<JsonConverter>() { new JSONCustomDateConverter("yyyy-MM-dd HH:mm:ss", loggedUser.Timezone) } });

Obviously you could remove anything related to time zone if you only want custom date formatting. Let me know it that helped!

Johann
  • 12,158
  • 11
  • 62
  • 89
  • 1
    If someone is looking to extend it by globally registering on Asp.Net MVC.`services.AddMvc() .AddJsonOptions(jsonOption => { jsonOption.SerializerSettings.Converters.Add( new JSONCustomDateConverter("dd/mm/yyy", TimeZoneInfo.FindSystemTimeZoneById("India Standard Time"))); });` – Vikash Kumar May 03 '17 at 11:24
15

As of Newtonsoft Json.Net version 4.5r5 you use the JsonPropertyAttribute Class class and set its ItemConverterType Property property. Usage:

// class to be serialized
public class MyClass
{
    [JsonProperty(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
    public DateTime? DateTime1;
    public DateTime? DateTime2;
}

As I have observed this will set the DateTimeConverter for all properties in this class not just the one before which is declared.

Anderson
  • 1,011
  • 2
  • 11
  • 24
  • This answer is the most up-to-date – Yanick Rochon Feb 26 '13 at 05:15
  • 1
    I don't think that I'm understanding what this is supposed to do, or how it's supposed to work. On my class, I have this: [JsonProperty(ItemConverterType = typeof(IsoDateTimeConverter))] public System.DateTime RecordInsertedDate { get; set; } But my dates are still coming through as the default /Date(132456560000000)/ format – James Gray Mar 05 '15 at 20:28
  • NVM, I was using ServiceStack which was overriding this. You have to use ServiceStack's JsConfig.DateHandler = DateHandler.ISO8601; config setting in your code to get ISO8601 – James Gray Mar 05 '15 at 20:35
3

Ran into the same problem, and found a solution based on the link from Adam:

new Date(yourDate.substr(yourDate.indexOf("(") + 1, 13) - 0));

It looks like a Unix timestamp, which javascript is easily able to convert into a date object. The - 0 is simply to make javascript treat the substr output as an integer... I guess you could Number() it as well, if you don't like the looks of - 0

Tim S. Van Haren
  • 8,861
  • 2
  • 30
  • 34
peirix
  • 36,512
  • 23
  • 96
  • 126
1

The JSON object contained something like this:

var data = {"CreatedDate":"/Date(1327572000000-1000)/"});

 ///
var oddDateTimeZone = data.CreatedDate;
var utcDateTime = oddDateTimeZone.substr(oddDateTimeZone.indexOf("(")+1, 13);
var utcZone = oddDateTimeZone.substr(oddDateTimeZone.indexOf("-")+1, 4);
var utcDateTimeZone = new Date(Number(utcDateTime)-(Number(utcZone)));

but, still it would be better to fix the JSON object so the date function fired without using something like eval() or window[]. Maybe in jQuery. Not sure.

Don't forget that the offset could be + and not just - for the offset!

Peter O.
  • 32,158
  • 14
  • 82
  • 96
  • you also use a regex and then eval the text like this: `eval("new " + data.CreateDate.replace(/\//ig,""))` seems to work just fine – Anthony R Sep 25 '15 at 17:37
-1

Sorry I simplify a bit @James Newton-King

string date = Newtonsoft.Json.JsonConvert.SerializeObject(DateTime.Now);    
Ben
  • 501
  • 6
  • 20
-2
ObjectMapper mapper = new ObjectMapper();

mapper.registerModule(new JavaTimeModule());

mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

This works for me

Liam
  • 27,717
  • 28
  • 128
  • 190