Подтвердить что ты не робот

Почему изменилась сериализация DateTime по умолчанию JSON.NET?

Я использовал старую версию JSON.Net(4.0r4) некоторое время и только что обновился до последней версии (4.5r11). Я заметил, что даты форматировались так:

2013-03-20T09: 00: 00.119Z

но теперь:

2013-03-20T09: 00: 00,119

В конце отсутствует Z. Согласно Википедии:

Если время в UTC, добавьте Z непосредственно после времени без пробела

Это сильно нарушило мой код JavaScript, поскольку у меня есть метод, который преобразует его в объект DateTime и ожидает Z. Я могу исправить это, изменив эту функцию, которую я использую, и я обнаружил, что могу установите DateTimeZoneHandling на DateTimeZoneHandling.Utc, но это означает, что мне пришлось бы изменить много кода С# в нескольких проектах.

Мне просто интересно, почему это изменилось.

Спасибо...

4b9b3361

Ответ 1

Какой браузер вы видите, что это происходит? Поскольку проблема, с которой вы на самом деле справляетесь, - это разбор Javascript, по моему опыту, проблема на самом деле - это миллисекундное округление, а не наличие Z или нет.

Попробуйте это в IE9: http://jsfiddle.net/b9chris/HaBP8/

'2013-06-13T20:43:55.6',
'2013-06-13T20:43:55.61',
'2013-06-13T20:43:55.61Z',
'2013-06-13T20:43:55.611',
'2013-06-13T20:43:55.611Z'

В большинстве браузеров все даты прекрасно разбираются; в IE9 первые 3 сбой, независимо от Z или нет, потому что для IE9 требуется 3 места для миллисекундного числа. Второе 2 преуспевает с Z и без него. Что имеет значение, это 3 миллисекунды цифр - Z не имеет значения, в том числе потому, что Javascript не содержит DateTimeKind, как .Net, поэтому Z или нет, не имеет значения, как Javascript интернализует дату. Поскольку число миллисекундных цифр иногда будет равным одному или 2 в зависимости от времени, если вы пропустите отметки времени, вы получите случайные сбои.

Я сообщил об этом как об ошибке на странице Json.Net Codeplex; он был отклонен сопровождающим в комментариях об ошибке и закрыт. Откройте исходный код.

Вы можете обойти эту ошибку, используя код в этом ответе:

fooobar.com/questions/2322/...

Чтобы быть ясным, отсутствие Z неверно в части JSON.Net, если оно выдает без него для DateTimeKind.UTC, но это не является недопустимой датой ISO-8601 в более общем смысле - нет Z неявно означает Local Time:

http://en.wikipedia.org/wiki/ISO_8601#Times

Если информация о соотношении UTC не указана с представлением времени, время считается локальным.

И, как упоминалось выше, анализ Javascript не заботится о Z, поэтому для ваших целей это не имеет значения.

Обратите внимание, что вы не можете передавать UTC на JSON.Net и запускать эту проблему. Объекты DateTime в С# могут быть натуральными Local, Unspecified или UTC. Нечестно предположить, что DateTimes, которые не являются UTC, фактически являются UTC; передача его без информации о часовом поясе - самая безопасная ставка. Структура .Net DateTime выполняет временные интервалы, поэтому JSON.Net не имеет выбора, кроме как выдать значение по умолчанию DateTimes (DateTimeKind.Unspecified) как локальное, запрещая интеграцию с .Net TimeZone library.

Ответ 2

Вы можете изменить, как DateTime будет сериализован, проверьте это у автора JSON.NET: Good (Date) Times с Json.NET

Ответ 3

Если у вас есть данные UTC на сервере, вы должны явно указать свойство DateTimeZoneHandling

 //serializer fix
        config.Formatters.Clear();
        config.Formatters.Add(new JsonMediaTypeFormatter()
        {
            SerializerSettings = new JsonSerializerSettings() {
                ContractResolver=new CamelCasePropertyNamesContractResolver(),
                DateTimeZoneHandling = DateTimeZoneHandling.Utc},

        });

После этого DateTime имеет "Z" в конце: 2017-05-11T00: 35: 20.8242381 Z