now new fechas datefromstring mongodb timezone mongoid aggregation-framework

mongodb - new - ¿Cómo lidiar con el problema de la zona horaria al almacenar fechas en utc usando mongod?



mongodb new date timezone (4)

Además del SERVER-6310 mencionado por Matt Johnson, otra solución es usar el operador de $project para agregar o restar del huso horario UTC para "cambiar el horario" a la zona local correcta. Resulta que puede agregar o restar tiempo en milisegundos.

Por ejemplo, suponiendo que tengo un campo de fecha llamado orderTime . Me gustaría consultar para EDT. Eso es -4 horas de UTC. Eso es 4 * 60 * 60 * 1000 milisegundos.

Entonces, escribiría la siguiente proyección para obtener day_ordered en hora local para todos mis registros:

db.table.aggregate( { $project : { orderTimeLocal : { $subtract : [ "$orderTime", 14400000] } } }, { $project : { day_ordered : { $dayOfYear : "$orderTimeLocal" } } })

Tengo una colección de mongodb donde cada documento tiene algunos atributos y una marca de tiempo utc. Necesito extraer datos de la colección y usar el marco de agregación porque utilizo los datos de la colección para mostrar algunos gráficos en la interfaz de usuario. Sin embargo, necesito hacer la agregación según la zona horaria del usuario. Suponiendo que conozca la zona horaria del usuario (aprobada en la solicitud del navegador o de alguna otra manera), ¿hay alguna forma de utilizar el marco de agregación para agregar en función de la zona horaria [del cliente]?


Encontré una solución en el plugin de mangosta para normalizar las fechas almacenadas de la zona horaria.


Lo que está pidiendo se está discutiendo actualmente en el problema de MongoDB SERVER-6310 .

Encontré esto en un enlace de un hilo de discusión .

El problema es común para cualquier agrupación por fecha, incluidas las bases de datos SQL y las bases de datos NoSQL. De hecho, hace poco me dirigí a esta cuestión en RavenDB. Hay una buena descripción del problema y una solución RavenDB here .

Los problemas de MongoDB discuten una solución alternativa, que es similar a lo que describí en los comentarios anteriores. Precalcula las horas locales que le interesan, y las agrupa en su lugar.

Será difícil cubrir cada zona horaria del mundo con cualquiera de los enfoques. Debe decidir sobre un pequeño puñado de zonas objetivo que tengan sentido para su base de usuarios, como el enfoque por oficina que describí en el artículo de RavenDB.

ACTUALIZACIÓN: Este problema fue resuelto en MongoDB en julio de 2017 (versión 3.5.11). La solución se describe en el primer enlace anterior, pero en resumen, han introducido un nuevo formato de objeto para las fechas en expresiones de agregación: { date: <dateExpression>, timezone: <tzExpression> } que le permite especificar una zona horaria para usar al agregar . Vea here otro ejemplo en los documentos de Mongo.


Todos los enfoques sugeridos anteriormente funcionan perfectamente bien, pero dado que hay una nueva versión de mongodb, desde 2.6 puede usar $let en el marco de agregación, esto le permitirá crear variables sobre la marcha, evitando así la necesidad de $project antes de agrupar. Ahora puede crear una variable con $let que contenga la hora localizada y la use en el operador $group .

Algo como:

db.test.aggregate([ {$group: { _id: { $let: { vars: { local_time: { $subtract: ["$date", 10800000]} }, in: { $concat: [{$substr: [{$year: "$$local_time"}, 0, 4]}, "-", {$substr: [{$month: "$$local_time"}, 0, 2]}, "-", {$substr: [{$dayOfMonth: "$$local_time"}, 0, 2]}] } } }, count: {$sum: 1} } }])

Tenga en cuenta que utiliza $let dentro de la definición de un bloque / variable, y el valor de ese bloque / variable es el valor devuelto de la subexpresión "in" , donde se utilizan los vars definidos anteriormente.