Вопрос: Как настроить дату Microsoft JSON?


Я беру свой первый треск на Ajax с jQuery. Я получаю свои данные на своей странице, но у меня возникают некоторые проблемы с данными JSON, которые возвращаются для типов данных Date. В принципе, я получаю строку назад, которая выглядит так:

/Date(1224043200000)/

От кого-то совершенно нового для JSON - Как мне отформатировать этот формат до короткого формата? Должно ли это обрабатываться где-нибудь в коде jQuery? Я пробовал jQuery.UI.datepickerиспользование плагина $.datepicker.formatDate()без каких-либо успехов.

FYI: Вот решение, которое я придумал, используя комбинацию ответов здесь:

function getMismatch(id) {
  $.getJSON("Main.aspx?Callback=GetMismatch",
    { MismatchId: id },

    function (result) {
      $("#AuthMerchId").text(result.AuthorizationMerchantId);
      $("#SttlMerchId").text(result.SettlementMerchantId);
      $("#CreateDate").text(formatJSONDate(Date(result.AppendDts)));
      $("#ExpireDate").text(formatJSONDate(Date(result.ExpiresDts)));
      $("#LastUpdate").text(formatJSONDate(Date(result.LastUpdateDts)));
      $("#LastUpdatedBy").text(result.LastUpdateNt);
      $("#ProcessIn").text(result.ProcessIn);
    }
  );

  return false;
}

function formatJSONDate(jsonDate) {
  var newDate = dateFormat(jsonDate, "mm/dd/yyyy");
  return newDate;
}

Это решение получило мой объект из метода обратного вызова и правильно отображало даты на странице, используя библиотеку формата даты.


1776


источник


Ответы:


Eval не требуется. Это будет нормально работать:

var date = new Date(parseInt(jsonDate.substr(6)));

Функция substr вынимает «/ Date (« part », а функция parseInt получает целое число и игнорирует«) / »в конце. Полученное число передается в конструктор Date.

EDIT: Я намеренно упустил radix (второй аргумент parseInt); видеть мой комментарий ниже , Кроме того, я полностью согласен с Комментарий Рори : Даты ISO-8601 предпочтительнее этого старого формата, поэтому этот формат обычно не должен использоваться для новой разработки. Смотрите превосходный Json.NET библиотека для отличной альтернативы, которая сериализует даты с использованием формата ISO-8601.

Для ISO-8601 отформатированных дат JSON просто передайте строку в конструктор Date:

var date = new Date(jsonDate); //no ugly parsing needed; full timezone support

1557



Вы можете использовать это, чтобы получить дату от JSON:

var date = eval(jsonDate.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));

И тогда вы можете использовать формат даты JavaScript скрипт (1,2 КБ при минировании и gzipped), чтобы отображать его по своему усмотрению.


115



Для тех, кто использует Newtonsoft Json.NET , прочитайте, как это сделать через Родной JSON в IE8, Firefox 3.5 плюс Json.NET ,

Также полезна документация по изменению формата дат, написанных Json.NET: Сериализация дат с помощью Json.NET

Для тех, кто слишком ленив, вот быстрые шаги. Поскольку JSON имеет свободную реализацию DateTime, вам необходимо использовать IsoDateTimeConverter(), Обратите внимание, что с Json.NET 4.5 формат даты по умолчанию - ISO, поэтому код ниже не нужен.

string jsonText = JsonConvert.SerializeObject(p, new IsoDateTimeConverter());

JSON будет проходить как

"fieldName": "2009-04-12T20:44:55"

Наконец, некоторый JavaScript для преобразования даты ISO в дату JavaScript:

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

Я использовал его так

$("<span />").text(isoDateReviver(item.fieldName).toLocaleString()).appendTo("#" + divName);

84



Исходный пример:

/Date(1224043200000)/  

не отражает форматирование, используемое WCF при отправке дат через WCF REST, используя встроенную сериализацию JSON. (по крайней мере, на .NET 3.5, SP1)

Я нашел ответ полезным, но требуется небольшое редактирование для регулярного выражения, так как кажется, что смещение часовой пояс GMT добавляется к возвращаемому номеру (с 1970 года) в WCF JSON.

В службе WCF у меня есть:

[OperationContract]
[WebInvoke(
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.WrappedRequest
    )]
ApptVisitLinkInfo GetCurrentLinkInfo( int appointmentsId );

ApptVisitLinkInfo определяется просто:

public class ApptVisitLinkInfo {
    string Field1 { get; set; }
    DateTime Field2 { get; set; }
    ...
}

Когда «Поле2» возвращается как Json из службы, это значение:

/Date(1224043200000-0600)/

Обратите внимание, что смещение часового пояса включено как часть значения.

Измененное регулярное выражение:

/\/Date\((.*?)\)\//gi

Он немного более энергичен и захватывает все между родителями, а не только первым номером. Результирующее время с 1970 года, плюс смещение часового пояса, может быть подано в eval для получения объекта даты.

Результирующая строка JavaScript для замены:

replace(/\/Date\((.*?)\)\//gi, "new Date($1)");

57



Don't repeat yourself - automate date conversion using $.parseJSON()

Answers to your post provide manual date conversion to JavaScript dates. I've extended jQuery's $.parseJSON() just a little bit, so it's able to automatically parse dates when you instruct it to. It processes ASP.NET formatted dates (/Date(12348721342)/) as well as ISO formatted dates (2010-01-01T12.34.56.789Z) that are supported by native JSON functions in browsers (and libraries like json2.js).

Anyway. If you don't want to repeat your date conversion code over and over again I suggest you read this blog post and get the code that will make your life a little easier.


53



If you say in JavaScript,

var thedate = new Date(1224043200000);
alert(thedate);

you will see that it's the correct date, and you can use that anywhere in JavaScript code with any framework.


50



Click here to check the Demo

JavaScript/jQuery

var = MyDate_String_Value = "/Date(1224043200000)/"
var value = new Date
            (
                 parseInt(MyDate_String_Value.replace(/(^.*\()|([+-].*$)/g, ''))
            );
var dat = value.getMonth() +
                         1 +
                       "/" +
           value.getDate() +
                       "/" +
       value.getFullYear();

Result - "10/15/2008"


46



Updated

We have an internal UI library that has to cope with both Microsoft's ASP.NET built-in JSON format, like /Date(msecs)/, asked about here originally, and most JSON's date format including JSON.NET's, like 2014-06-22T00:00:00.0. In addition we need to cope with oldIE's inability to cope with anything but 3 decimal places.

We first detect what kind of date we're consuming, parse it into a normal JavaScript Date object, then format that out.

1) Detect Microsoft Date format

// Handling of Microsoft AJAX Dates, formatted like '/Date(01238329348239)/'
function looksLikeMSDate(s) {
    return /^\/Date\(/.test(s);
}

2) Detect ISO date format

var isoDateRegex = /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d\d?\d?)?([\+-]\d\d:\d\d|Z)?$/;

function looksLikeIsoDate(s) {
    return isoDateRegex.test(s);
}

3) Parse MS date format:

function parseMSDate(s) {
    // Jump forward past the /Date(, parseInt handles the rest
    return new Date(parseInt(s.substr(6)));
}

4) Parse ISO date format.

We do at least have a way to be sure that we're dealing with standard ISO dates or ISO dates modified to always have three millisecond places (see above), so the code is different depending on the environment.

4a) Parse standard ISO Date format, cope with oldIE's issues:

function parseIsoDate(s) {
    var m = isoDateRegex.exec(s);

    // Is this UTC, offset, or undefined? Treat undefined as UTC.
    if (m.length == 7 ||                // Just the y-m-dTh:m:s, no ms, no tz offset - assume UTC
        (m.length > 7 && (
            !m[7] ||                    // Array came back length 9 with undefined for 7 and 8
            m[7].charAt(0) != '.' ||    // ms portion, no tz offset, or no ms portion, Z
            !m[8] ||                    // ms portion, no tz offset
            m[8] == 'Z'))) {            // ms portion and Z
        // JavaScript's weirdo date handling expects just the months to be 0-based, as in 0-11, not 1-12 - the rest are as you expect in dates.
        var d = new Date(Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6]));
    } else {
        // local
        var d = new Date(m[1], m[2]-1, m[3], m[4], m[5], m[6]);
    }

    return d;
}

4b) Parse ISO format with a fixed three millisecond decimal places - much easier:

function parseIsoDate(s) {
    return new Date(s);
}

5) Format it:

function hasTime(d) {
    return !!(d.getUTCHours() || d.getUTCMinutes() || d.getUTCSeconds());
}

function zeroFill(n) {
    if ((n + '').length == 1)
        return '0' + n;

    return n;
}

function formatDate(d) {
    if (hasTime(d)) {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
        s += ' ' + d.getHours() + ':' + zeroFill(d.getMinutes()) + ':' + zeroFill(d.getSeconds());
    } else {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
    }

    return s;
}

6) Tie it all together:

function parseDate(s) {
    var d;
    if (looksLikeMSDate(s))
        d = parseMSDate(s);
    else if (looksLikeIsoDate(s))
        d = parseIsoDate(s);
    else
        return null;

    return formatDate(d);
}

The below old answer is useful for tying this date formatting into jQuery's own JSON parsing so you get Date objects instead of strings, or if you're still stuck in jQuery <1.5 somehow.

Old Answer

If you're using jQuery 1.4's Ajax function with ASP.NET MVC, you can turn all DateTime properties into Date objects with:

// Once
jQuery.parseJSON = function(d) {return eval('(' + d + ')');};

$.ajax({
    ...
    dataFilter: function(d) {
        return d.replace(/"\\\/(Date\(-?\d+\))\\\/"/g, 'new $1');
    },
    ...
});

In jQuery 1.5 you can avoid overriding the parseJSON method globally by using the converters option in the Ajax call.

http://api.jquery.com/jQuery.ajax/

Unfortunately you have to switch to the older eval route in order to get Dates to parse globally in-place - otherwise you need to convert them on a more case-by-case basis post-parse.


31



I also had to search for a solution to this problem and eventually I came across moment.js which is a nice library that can parse this date format and many more.

var d = moment(yourdatestring)

It saved some headache for me so I thought I'd share it with you. :)
You can find some more info about it here: http://momentjs.com/


21



I ended up adding the "characters into Panos's regular expression to get rid of the ones generated by the Microsoft serializer for when writing objects into an inline script:

So if you have a property in your C# code-behind that's something like

protected string JsonObject { get { return jsSerialiser.Serialize(_myObject); }}

And in your aspx you have

<script type="text/javascript">
    var myObject = '<%= JsonObject %>';
</script>

You'd get something like

var myObject = '{"StartDate":"\/Date(1255131630400)\/"}';

Notice the double quotes.

To get this into a form that eval will correctly deserialize, I used:

myObject = myObject.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');

I use Prototype and to use it I added

String.prototype.evalJSONWithDates = function() {
    var jsonWithDates = this.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');
    return jsonWithDates.evalJSON(true);
}

21