Сериализация даты JSON и часовые пояса

У меня возникли проблемы с отображением правильной даты в браузере клиента с помощью сериализованного объекта JSON. Пользователь может определить, в каком часовом поясе он хочет просматривать данные. Учитывая это, я конвертирую дату UTC в часовой пояс пользователя на сервере. Затем я хочу сериализовать дату / время (которые уже преобразованы в их определенный часовой пояс) в браузер через JSON.

кажется простым, однако сериализаторы JSON, которые я использовал, сильно испортили мои даты. Сервер находится в формате UTC, а клиент-в Центральном (-6). Даты корректируются (-12 часов), хотя я указываю DateTime.Доброта к неопределенному.

каким-то образом .NET знает, в каком часовом поясе находится браузер клиента и в каком часовом поясе находится сервер, и он отрицает -6 от моих дат/времени, хотя я уже настроил время на глобальные настройки пользователя и установил вид дат неуказанным. Как я могу заставить сериализаторы JSON не пытаться настроить мой даты?

List<ErrorGridModel> models = Mapper.Map<ErrorCollection, List<ErrorGridModel>>(errors);
foreach (ErrorGridModel m in models)
{
    //convert UTC dates to user local dateTime - split out date vs. time for grouping & splitting columns
    DateTime dtLocal = TimeZoneInfo.ConvertTimeFromUtc(m.ErrorDate, this.AppContext.User.TimeZoneInfo);
    m.ErrorDate = new DateTime(dtLocal.Year, dtLocal.Month, dtLocal.Day, 0, 0, 0, DateTimeKind.Unspecified);
    m.ErrorTime = new DateTime(1900, 1, 1, dtLocal.Hour, dtLocal.Minute, dtLocal.Second, DateTimeKind.Unspecified);
}
IQueryable<ErrorGridModel> dataSource = models.AsQueryable();
return new ContentResult() { Content = JsonConvert.SerializeObject(dataSource.ToDataSourceResult(request), new JsonSerializerSettings() { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat }), ContentType = "application/json" };
//return Json(dataSource.ToDataSourceResult(request));

даты ISO, похоже, работают, но я не могу их использовать, поскольку у меня есть сторонние элементы управления, которые хотят более старый формат Microsoft... который регулирует часовые пояса на мне.

3 ответов


когда вы пытаетесь контролировать смещения, не полагайтесь на DateTimeKind.Unspecified. У него есть несколько причуд, которые часто интерпретируются как Unspecified == Local. Единственный способ получить Json.Net чтобы конкретно кодировать правильное смещение (независимо от формата ISO или MS), нужно передать его DateTimeOffset вместо DateTime.

// Start with the UTC time, for example your m.ErrorDate.
// Here I demonstrate with UtcNow.  Any DateTime with .Kind = UTC is ok.
var dt = DateTime.UtcNow;

// Use the appropriate time zone, here I demonstrate with EST.
var tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

// Get the offset from UTC for the time zone and date in question.
var offset = tzi.GetUtcOffset(dt);

// Get a DateTimeOffset for the date, and adjust it to the offset found above.
var dto = new DateTimeOffset(dt).ToOffset(offset);

// Serialize to json
var json = JsonConvert.SerializeObject(dto, new JsonSerializerSettings
    {
        DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
    });


// The json should now contain the correct time and offset information.
// For example,  "\/Date(1358789156229-0500)\/"

теперь, надеюсь, вы обнаружите, что элементы управления javascript, которые вы используете, будут соблюдать смещение и применять его соответствующим образом. Если нет, то остальная часть проблемы специфична для контроля вы используете.


вот длинная дискуссия о точной ситуации, в которой я был. http://www.telerik.com/community/forums/aspnet-mvc/grid/grids-and-dates.aspx

итог, если вы используете формат даты Microsoft JSON, он всегда будет отражать дату в UTC как количество миллисекунд (тиков) от 1/1/1970 UTC. Для меня нет возможности автоматически конвертировать время в локальное на сервере и отправлять то, что должно быть через JSON в сетку Kendo как сетку Kendo контроль создает дата от клещей в JS как мирового. При отображении этой даты он автоматически преобразует значение в локальный часовой пояс браузера.

единственный способ показать преобразованное значение даты моего сервера с сервера-отправить дату через JSON в виде строки клиенту.


мы столкнулись с этой проблемой. Как вы заметили, проблема на самом деле происходит на стороне клиента. Используя обработчик конца запроса в сетке, можно преобразовать дату обратно в UTC. Пример найден здесь:

http://www.kendoui.com/code-library/mvc/grid/using-utc-time-on-both-client-and-server-sides.aspx