Сериализация даты и времени JSON

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

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

Как-то .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... который настраивает часовые пояса на мне.

Ответ 1

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

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

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

Ответ 2

Когда вы пытаетесь контролировать смещения, не полагайтесь на 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 будут выполнять зачет и применять его соответствующим образом. Если нет, то остальная часть проблемы зависит от используемого вами элемента управления.

Ответ 3

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

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