Definición
$dateDiffNuevo en la versión 5.0.
Devuelve la diferencia entre dos fechas.
La
$dateDiffla expresión tiene esta sintaxis:{ $dateDiff: { startDate: <Expression>, endDate: <Expression>, unit: <Expression>, timezone: <tzExpression>, startOfWeek: <String> } } $dateDiffcalcula la diferencia contando los límites superiores de los intervalos de tiempo cruzados desdestartDatehastaendDatedentro deltimezone. La duración de los intervalos de tiempo es igual aunity están alineados de modo que sus límites ocurren en múltiplos enteros deunita lo largo del eje temporal. Excluye las unidades parciales que no cruzan un límite. Esta expresión devuelve un entero en elunitespecificado. SiendDateprecede astartDate, retorna un entero negativo.CampoObligatorio/OpcionalDescripciónstartDateRequerido
El inicio del período de tiempo. El
startDatepuede ser cualquier expresión que se resuelve en una Fecha, una Marca de tiempo o una ObjectID.endDateRequerido
El final del periodo de tiempo. El
endDatepuede ser cualquier expresión que resuelva en una Fecha, un Sello de tiempo o un ObjectID.unitRequerido
La medición de tiempo
unitentre elstartDatey elendDate. Es una expresión que se resuelve en una string:yearquarterweekmonthdayhourminutesecondmillisecond
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" startOfWeekOpcional
Se utiliza cuando la unidad es igual a
week. Por defecto esSunday. El parámetrostartOfWeekes una expresión que se resuelve en una string insensible a mayúsculas:monday(omon)tuesday(otue)wednesday(owed)thursday(othu)friday(ofri)saturday(osat)sunday(osun)
Comportamiento
Sin unidades fraccionarias
La expresión $dateDiff devuelve un número entero al comparar una parte específica de cada fecha. Para la unidad year, compara los valores del año: cualquier fecha en 2022 está a una year de distancia de cualquier fecha en 2023. Para la unidad week, compara los números de semana: cualquier fecha en la semana 5 está a una week de distancia de cualquier fecha en la semana 6.
Comienzo de la semana
El inicio de week es Sunday a menos que se modifique mediante el parámetro startOfWeek. $dateDiff cuenta cualquier semana que comience entre startDate y endDate en el día especificado. El conteo de semanas no está limitado por el calendario month ni por el calendario year.
Zona horaria
Al utilizar un identificador de zona horaria Olson en el campo <timezone>, MongoDB aplica la Compensación DST 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 }
Detalles adicionales
El algoritmo calcula la diferencia de fechas utilizando el calendario gregoriano.
Se tienen en cuenta los años bisiestos y el horario de verano, pero no los segundos intercalares.
La diferencia devuelta puede ser negativa.
Ejemplos
Tiempo transcurrido
Crea una colección de pedidos de clientes:
db.orders.insertMany( [ { custId: 456, purchased: ISODate("2020-12-31"), delivered: ISODate("2021-01-05") }, { custId: 457, purchased: ISODate("2021-02-28"), delivered: ISODate("2021-03-07") }, { custId: 458, purchased: ISODate("2021-02-16"), delivered: ISODate("2021-02-18") } ] )
El siguiente ejemplo:
Devuelve el número promedio de días para una entrega.
Utiliza
dateDiffpara calcular la diferencia entre la fechapurchasedy la fechadelivered.
db.orders.aggregate( [ { $group: { _id: null, averageTime: { $avg: { $dateDiff: { startDate: "$purchased", endDate: "$delivered", unit: "day" } } } } }, { $project: { _id: 0, numDays: { $trunc: [ "$averageTime", 1 ] } } } ] )
El acumulador $avg en la etapa $group utiliza $dateDiff en cada documento para obtener el tiempo transcurrido entre las fechas purchased y delivered. El valor resultante se devuelve como averageTime.
La parte decimal del averageTime se trunca ($trunc) en la etapa $project para producir una salida como esta:
{ "numDays" : 4.6 }
Precisión de resultados
Cree esta colección con fechas de inicio y finalización para una suscripción.
db.subscriptions.insertMany( [ { custId: 456, start: ISODate("2010-01-01"), end: ISODate("2011-01-01") }, { custId: 457, start: ISODate("2010-01-01"), end: ISODate("2011-06-31") }, { custId: 458, start: ISODate("2010-03-01"), end: ISODate("2010-04-30") } ] )
La expresión $dateDiff devuelve una diferencia de tiempo expresada en units enteros. No hay partes fraccionarias de una unidad. Por ejemplo, al contar en years no hay medios años.
En este ejemplo, observe cómo cambiar el unit cambia la precisión devuelta:
db.subscriptions.aggregate( [ { $project: { Start: "$start", End: "$end", years: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "year" } }, months: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "month" } }, days: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "day" } }, _id: 0 } } ] )
Los resultados se resumen en la siguiente tabla:
Inicio | End | Años | Meses | Días |
|---|---|---|---|---|
2010-01-01 | 2011-01-01 | 1 | 12 | 365 |
2010-01-01 | 2011-07-01 | 1 | 18 | 546 |
2010-03-01 | 2010-04-30 | 0 | 1 | 60 |
En la segunda fila, 2010-01-01 y 2011-07-01 están en años diferentes (2010 y 2011), por lo que $dateDiff devuelve 1 year. En la tercera fila, 2010-03-01 (marzo) y 2010-04-30 (abril) difieren en un mes, por lo que $dateDiff devuelve 1 month.
Semanas por mes
Crea una colección de meses:
db.months.insertMany( [ { month: "January", start: ISODate("2021-01-01"), end: ISODate("2021-01-31") }, { month: "February", start: ISODate("2021-02-01"), end: ISODate("2021-02-28") }, { month: "March", start: ISODate("2021-03-01"), end: ISODate("2021-03-31") }, ] )
Puede cambiar el inicio de cada semana y contar la cantidad resultante de semanas en cada mes con el siguiente código:
db.months.aggregate( [ { $project: { wks_default: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "week" } }, wks_monday: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "week", startOfWeek: "Monday" } }, wks_friday: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "week", startOfWeek: "fri" } }, _id: 0 } } ] )
Los resultados se resumen en la siguiente tabla:
Mes | domingo | lunes | Viernes |
|---|---|---|---|
enero | 5 | 4 | 4 |
febrero | 4 | 3 | 4 |
marzo | 4 | 4 | 4 |
De los resultados:
Cuando el
startOfWeekes domingo, el 5.ºweekde enero de 2021 comienza el día 31.Debido a que el día 31 es un domingo y se encuentra entre
startDateyendDate, se suma unweeka la cuenta.El contador
weekse incrementa incluso cuando una semana calendario termina después deendDateo en el siguiente período calendario.