Definición
$dateAddNuevo en la versión 5.0.
Incrementa a
Date()objeto por un número especificado de unidades de tiempo.La
$dateAddLa expresión tiene la siguiente sintaxis:{ $dateAdd: { startDate: <Expression>, unit: <Expression>, amount: <Expression>, timezone: <tzExpression> } } Retorna un
Date(). ElstartDatepuede ser cualquier expresión que resuelva a un tipo Date, Timestamp u ObjectId. No importa qué tipo de datos se haya utilizado como entrada, el valor retornado será un objetoDate().CampoObligatorio/OpcionalDescripciónstartDateRequerido
La fecha de inicio, en UTC, de la operación de suma. El
startDatepuede ser cualquier expresión que se resuelva en una fecha, una marca de tiempo o un ID de objeto.unitRequerido
El
unitutilizado para medir elamountdel tiempo agregado astartDate. Elunites una expresión que se resuelve en una de las siguientes cadenas:yearquarterweekmonthdayhourminutesecondmillisecond
amountRequerido
El número de
unitsañadido a losstartDate. Elamountes una expresión que se resuelve a un entero o long. Elamounttambién puede resolverse como un decimal entero o un double si ese valor puede convertirse en un long sin pérdida de precisión.timezoneOpcional
La zona horaria para llevar a cabo la operación.
<tzExpression>debe ser una expresión válida que se resuelva en una string formateada como un Identificador de zona horaria Olson o un Diferencia UTC. Si no se proporcionatimezone, el resultado se muestra enUTC.FormatoEjemplosIdentificador de zona horaria Olson
"America/New_York" "Europe/London" "GMT" Desplazamiento UTC
+/-[hh]:[mm], e.g. "+04:45" +/-[hh][mm], e.g. "-0530" +/-[hh], e.g. "+03" Para obtener más información sobre expresiones y tipos consulta Expresiones y BSON types.
Comportamiento
Medición del tiempo
MongoDB sigue el uso prevalente de bases de datos y trabaja con el tiempo en UTC. La expresión dateAdd siempre toma un startDate en UTC y devuelve un resultado en UTC. Si se especifica el timezone, el cálculo se realizará utilizando el timezone especificado. La zona horaria es especialmente importante cuando un cálculo implica el horario de verano (DST).
Si el unit es un month o mayor, la operación se ajusta para tener en cuenta el último día del mes. Agregar un month el último día de octubre, por ejemplo, demuestra el ajuste de "último día del mes".
{ $dateAdd: { startDate: ISODate("2020-10-31T12:10:05Z"), unit: "month", amount: 1 } }
Tenga en cuenta que la fecha devuelta, ISODate("2020-11-30T12:10:05Z"), es el 30 y no el 31, ya que noviembre tiene menos días que octubre.
Zona horaria
Al utilizar un identificador de zona horaria de Olson en el campo <timezone>, MongoDB aplica el Desplazamiento del horario de verano, si corresponde para la zona horaria especificada.
Por ejemplo, considera una colección sales con el siguiente documento:
db.sales.insertOne( { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:15:39.736Z") } )
La siguiente agregación ilustra cómo MongoDB gestiona el ajuste de DST para el identificador de zona horaria Olson. El ejemplo usa los operadores $hour y $minute para devolver las partes correspondientes del campo date:
db.sales.aggregate([ { $project: { "nycHour": { $hour: { date: "$date", timezone: "-05:00" } }, "nycMinute": { $minute: { date: "$date", timezone: "-05:00" } }, "gmtHour": { $hour: { date: "$date", timezone: "GMT" } }, "gmtMinute": { $minute: { date: "$date", timezone: "GMT" } }, "nycOlsonHour": { $hour: { date: "$date", timezone: "America/New_York" } }, "nycOlsonMinute": { $minute: { date: "$date", timezone: "America/New_York" } } } }])
La operación devuelve el siguiente resultado:
{ "_id": 1, "nycHour" : 5, "nycMinute" : 24, "gmtHour" : 10, "gmtMinute" : 24, "nycOlsonHour" : 6, "nycOlsonMinute" : 24 }
Ejemplos
Agregar una fecha futura
Considere una colección de pedidos de clientes con los siguientes documentos:
db.shipping.insertMany( [ { custId: 456, purchaseDate: ISODate("2020-12-31") }, { custId: 457, purchaseDate: ISODate("2021-02-28") }, { custId: 458, purchaseDate: ISODate("2021-02-26") } ] )
El tiempo normal de envío es de 3 días. Puede usar $dateAdd en un pipeline de agregación para establecer un expectedDeliveryDate 3 días en el futuro.
db.shipping.aggregate( [ { $project: { expectedDeliveryDate: { $dateAdd: { startDate: "$purchaseDate", unit: "day", amount: 3 } } } }, { $merge: "shipping" } ] )
Tras añadir 3 días a la purchaseDate con $dateAdd en la etapa $project, la etapa $merge actualiza los documentos originales con el expectedDeliveryDate.
Los documentos resultantes se ven así:
{ "_id" : ObjectId("603dd4b2044b995ad331c0b2"), "custId" : 456, "purchaseDate" : ISODate("2020-12-31T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-01-03T00:00:00Z") } { "_id" : ObjectId("603dd4b2044b995ad331c0b3"), "custId" : 457, "purchaseDate" : ISODate("2021-02-28T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-03-03T00:00:00Z") } { "_id" : ObjectId("603dd4b2044b995ad331c0b4"), "custId" : 458, "purchaseDate" : ISODate("2021-02-26T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-03-01T00:00:00Z") }
Filtrar por rango de fechas
Actualiza la colección shipping del último ejemplo con este código para agregar fechas de entrega a los documentos:
db.shipping.updateOne( { custId: 456 }, { $set: { deliveryDate: ISODate( "2021-01-10" ) } } ) db.shipping.updateOne( { custId: 457 }, { $set: { deliveryDate: ISODate( "2021-03-01" ) } } ) db.shipping.updateOne( { custId: 458 }, { $set: { deliveryDate: ISODate( "2021-03-02" ) } } )
Quieres encontrar envíos retrasados. Usa $dateAdd en una etapa $match para crear un filtro que coincida con documentos en un rango de fechas definido por un punto de partida ($purchaseDate) y un período de tiempo dado por $dateAdd.
db.shipping.aggregate( [ { $match: { $expr: { $gt: [ "$deliveryDate", { $dateAdd: { startDate: "$purchaseDate", unit: "day", amount: 5 } } ] } } }, { $project: { _id: 0, custId: 1, purchased: { $dateToString: { format: "%Y-%m-%d", date: "$purchaseDate" } }, delivery: { $dateToString: { format: "%Y-%m-%d", date: "$deliveryDate" } } } } ] )
La etapa $match utiliza $gt y $dateAdd en una expresión ($expr) para comparar el deliveryDate real con una fecha esperada. Los documentos con fechas de entrega superiores a 5 días después del purchaseDate pasan a la etapa $project.
La etapa $project utiliza la expresión para convertir las fechas a un formato $dateToString más legible. Sin la conversión, MongoDB devolvería la fecha en formato ISODate.
En este ejemplo, solo se devuelve un registro:
{ "custId" : 456, "purchased" : "2020-12-31", "delivery" : "2021-01-10" }
Ajusta para el horario de verano
Todas las fechas se almacenan internamente en hora UTC. Cuando se especifica timezone, $dateAdd utiliza la hora local para realizar los cálculos. Los resultados se muestran en UTC.
Tienes clientes en varias zonas horarias y quieres ver qué efecto podría tener el horario de verano en tus períodos de facturación si facturas por day o por hour.
Crea esta colección de tiempos de conexión:
db.billing.insertMany( [ { location: "America/New_York", login: ISODate("2021-03-13T10:00:00-0500"), logout: ISODate("2021-03-14T18:00:00-0500") }, { location: "America/Mexico_City", login: ISODate("2021-03-13T10:00:00-00:00"), logout: ISODate("2021-03-14T08:00:00-0500") } ] )
Primero añade 1 día, luego añade 24 horas a las fechas login en cada documento.
db.billing.aggregate( [ { $project: { _id: 0, location: 1, start: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$login" } }, days: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } } } }, hours: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "hour", amount: 24, timezone: "$location" } } } }, startTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$login", timezone: "$location" } }, daysTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } }, timezone: "$location" } }, hoursTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "hour", amount: 24, timezone: "$location" } }, timezone: "$location" } }, } } ] ).pretty()
La expresión reformatea la salida para facilitar su lectura. Los resultados se resumen a $dateToString continuación:
Campo | New York | Ciudad de México |
|---|---|---|
Inicio | 2021-03-13 15:00 | 2021-03-13 10:00 |
Comienzo, Info TZ | 2021-03-13 10:00 | 2021-03-13 04:00 |
1 día | 2021-03-14 14:00 | 2021-03-14 10:00 |
1 Día, Información TZ | 2021-03-14 10:00 | 2021-03-14 04:00 |
24 horas | 2021-03-14 15:00 | 2021-03-14 10:00 |
24 horas, información TZ | 2021-03-14 11:00 | 2021-03-14 04:00 |
La gráfica destaca varios puntos:
Las fechas sin formato se devuelven en UTC. El
$loginde Nueva York es UTC -5, sin embargo las filasstart,daysyhoursmuestran la hora en UTC.El 14 de marzo es el inicio del horario de verano en Nueva York, pero no en México. El tiempo calculado se ajusta cuando una ubicación cambia al horario de verano y cruza de uno
dayal siguiente.El horario de verano (DST) modifica la duración de
day, no dehour. No hay horario de verano (DST) parahours. Solo hay un ajuste por horario de verano (DST) cuando la mediciónunites dedayo más y el cálculo cruza un cambio de horario en eltimezoneespecificado.