c# - typeparam - ServiceStack: ¿hay una manera de forzar a todas las fechas serializadas a usar un DateTimeKind específico?
summary c# visual studio (3)
El offset DateTimeKind
no se almacena con Date, por lo que, de manera predeterminada, los serializadores de ServiceStack suponen que la fecha es local, que se serializa como UTC y se deserializa como local.
Puede obtener DateTimeKind.Unspecified
para ser asumido como UTC con:
JsConfig.AssumeUtc = true;
Tengo un POCO como este:
public class BlogEntry
{
public string Title { get; set; }
public DateTime Date { get; set; }
}
La mayoría de las veces se está hidratando desde Entity Framework, pero puede y se usará fuera de Entity Framework.
La DateTimeKind para la fecha de EF no está especificada, lo que a partir de lo que leo es normal.
Cuando guardo este POCO en Redis (usando el cliente ServiceStack Redis), vuelve con un DateTimeKind de Local.
Así que hay un jitter con los objetos devueltos. La primera pasada (sin caché) tiene ISO-8061 sin desplazamiento (DateTimeKind.Unspecified). La segunda pasada (en caché) es ISO-8061 con un desplazamiento (desde Redis con DateTimeKind.Local).
¿Alguna forma de forzar que el serializador JSON de ServiceStack siempre interprete las fechas como un DateTimeKind dado? (Sé que hay una propiedad "JsConfig.AppendUtcOffset", pero si es verdadero o falso, ¿los valores nunca cambian para mí?)
¿O en algún lugar del proceso de deserialización de mi RedisClient tecleado para hacer que DateTimeKind sea local?
Puedo cambiar manualmente mis POCO para hacer cumplir DateTimeKind, y eso funciona, pero esperaba algo menos propenso a errores.
Si necesita algo más configurable que la respuesta de @ mythz, puede forzar la serialización o deserialización de DateTimes para tener un DateTimeKind
determinado anulando DateTime y opcionalmente DateTime? Métodos de serialización y / o deserialización.
Forzar todos los DateTimes serializados para ser interpretados como UTC
JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString();
A continuación, puede avanzar un paso más y cometer un error en la deserialización si DateTime no está en un formato específico. Comencé a usar esto cuando quería forzar a los clientes a especificar la zona horaria en todas las solicitudes, pero no necesariamente exigir que siempre fuera Utc.
JsConfig<DateTime>.DeSerializeFn = time =>
{
if (!IsInCorrectDateFormat(time))
throw new System.Runtime.Serialization.SerializationException(BadDateTime);
return ServiceStack.Text.Common.DateTimeSerializer.ParseDateTime(time);
};
Un pellizco a la solución bpruitt-goddard. Todo el crédito va para él.
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;
Por lo tanto, cualquier fecha que salga de la pila de servicios se forzará en un formato de fecha ISO8601 y las fechas que lleguen se convertirán automáticamente a la fecha C # de la cadena ISO8601.