ServiceStack - Есть ли способ заставить все сериализованные даты использовать определенный DateTimeKind?

У меня есть POCO:

public class BlogEntry
{
    public string Title { get; set; }
    public DateTime Date { get; set; }
}

Большую часть времени он увлажняется из Entity Framework, но он может и будет использоваться вне Entity Framework.

DateTimeKind для даты из EF не указан, что из того, что я читаю, является нормальным.

Когда я кечу этого POCO в Redis (с помощью клиента ServiceStack Redis), он возвращается с DateTimeKind of Local.

Итак, есть дрожание с возвращенными объектами. Первый проход (без кэша) имеет ISO-8061 без смещения (DateTimeKind.Unspecified). Второй проход (кэшированный) - ISO-8061 со смещением (от Redis с DateTimeKind.Local).

Как заставить Serializer ServiceStack JSON всегда интерпретировать даты как заданный DateTimeKind? (Я знаю, что есть свойство "JsConfig.AppendUtcOffset", но верно ли это или false, значения меня не меняются?)

Или где-нибудь в процессе десериализации из моего типизированного RedisClient, чтобы сделать DateTimeKind локальным?

Я могу вручную изменить свой POCO для принудительного использования DateTimeKind - и это работает - но я надеялся на что-то менее подверженное ошибкам.

Ответы

Ответ 1

Если вам нужно что-то более настраиваемое, чем ответ @mythz, вы можете заставить сериализацию или десериализацию DateTimes иметь определенный DateTimeKind путем переопределения даты и времени DateTime? сериализации и/или десериализации.

Заставить все последовательные DateTimes интерпретироваться как UTC

JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString();

Затем вы можете сделать этот шаг дальше и ошибку при десериализации, если DateTime не в указанном формате. Я начал использовать это, когда хотел заставить клиентов указать часовой пояс во всех запросах, но не обязательно требует, чтобы он всегда был Utc.

JsConfig<DateTime>.DeSerializeFn = time =>
{
  if (!IsInCorrectDateFormat(time))
    throw new System.Runtime.Serialization.SerializationException(BadDateTime);

  return ServiceStack.Text.Common.DateTimeSerializer.ParseDateTime(time);
};

Ответ 2

Смещение DateTimeKind не сохраняется в Date, поэтому по умолчанию сериализаторы ServiceStack делают предположение, что дата является локальной, которая сериализуется как UTC и десериализована как локальная.

Вы можете получить DateTimeKind.Unspecified как UTC с помощью:

JsConfig.AssumeUtc = true;

Ответ 3

Настройка решения bpruitt-goddard. Все кредиты идут ему.

JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString("o");
        JsConfig<DateTime?>.SerializeFn = 
            time => time != null ? new DateTime(time.Value.Ticks, DateTimeKind.Local).ToString("o") : null;
        JsConfig.DateHandler = DateHandler.ISO8601;

Таким образом, любые даты, исходящие из стека служб, будут принудительно введены в формат даты ISO8601, и любые даты, которые будут отправлены, будут автоматически преобразованы в дату С# из строки ISO8601.