Hay problemas para trabajar con DateTimeOffset en CosmosDb. Refiriéndose a la guía de trabajo con ellos en Microsoft Docs , dice...
Para convertir un DateTime local a UTC, el desplazamiento debe conocerse/almacenarse como una propiedad en el JSON y el cliente puede utilizar el desplazamiento para calcular el valor de UTC DateTime.
Así que estoy almacenando mis fechas en mis documentos con el formato "2021-04-23T12:15:00+01:00" . Esto funciona muy bien al consultar y mostrar a los usuarios localmente. Sin embargo, encuentro problemas al realizar consultas en estos DateTimes...
En mi servidor haré una consulta así...
Consulta Linq
.Where(x => x.ExpiresAt.UtcDateTime <= DateTime.UtcNow)Si caduca a las = "2021-04-23T12:15:00+01:00"
Y la hora UTC ahora = "2021-04-23T11:15:00+00:00"
Entonces esperaría que la consulta devuelva un artículo. Sin embargo, no se devuelven elementos hasta una hora después, casi como si la extensión .UtcDateTime no funcionara. Si ese es el caso, ¿cómo se comparan DateTimeOffsets como este? Los documentos de Microsoft hacen que parezca que necesita otro campo solo para almacenar el desplazamiento y no puede usarlo en línea con la fecha y hora en sí. Me gusta...
{ "expiresAt":"2021-04-23T11:15:00", "expiresAtOffset":"1" }Seguramente lo estoy malinterpretando, ¿verdad?
Nota: He intentado usar una consulta SQL en lugar de linq así...
"SELECT * FROM c WHERE c.expiresAt <= \"2021-04-23T11:58:05\""Pero sigue siendo el mismo problema, porque el problema es que el valor del cosmos es el que necesita convertir y ver los documentos , no hay forma de convertir el valor del cosmos en un tiempo UTC ...
Otra pregunta sobre StackOverflow sugirió almacenarlo con la abreviatura Z. Lo intenté y parece estar funcionando más o menos como quiero, pero no perfecto. Todas las fechas ahora se almacenan como valores DateTime con una Z añadida. Luego, al usar los DTO de DateTimeOffset, convertirá el valor de manera adecuada en el cliente. Sin embargo, tuve que cambiar la configuración de serialización, así...
var jsonSerializerSettings = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat, DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffZ" };Luego agregué que al crear el DocumentClient...
new DocumentClient(serviceEndpoint, authKey, serializerSettings: jsonSerializerSettings);El único problema que tengo con esto es que tengo correos electrónicos que deben enviarse desde el servidor con tiempos en ellos. Estas horas son incorrectas porque el servidor no sabe cómo convertirlas a la hora local del cliente.
En mi experiencia, esta combinación funciona para lograr la felicidad con Cosmos y datetimes en .NET:
DateTime .NET, no DateTimeOffsetyyyy-MM-ddTHH:mm:ss.fffffffZSystem.Text.Json para un control directo sobre la serialización y para un valor predeterminado que funcione como se esperaba.