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.