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 la diferencia entera entre startDate y endDate, medida en el units especificado. Las duraciones se miden contando el número de veces que se sobrepasa un límite de unidad. Por ejemplo, dos fechas con 18 meses de diferencia devolverían una diferencia de 1 year en lugar de 1,5 years.
Comienzo de la semana
El inicio de week es Sunday a menos que se modifique por el parámetro startOfWeek. Se contará cualquier semana que comience entre el startDate y el endDate el día especificado. El conteo de semanas no está limitado por el calendario month o el calendario year.
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 }
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
Crear 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 |
El recuento solo aumenta cuando comienza un nuevo unit, por lo que 18 meses se informan como 1 año en la segunda fila y 60 días se informan como un mes en la tercera fila.
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 recuento
weekse incrementa incluso cuando una semana del calendario finaliza después delendDateo en el siguiente período del calendario.