Definición
$dateDiffNuevo en la versión 5.0.
Devuelve la diferencia entre dos fechas.
El
$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 cruzadosstartDatede aendDatedentrotimezonede. La longitud de los intervalos de tiempo es igual a unounity están alineados de forma que sus límites se encuentren en múltiplos enteros deunita lo largo del eje del tiempo. Excluye las unidades parciales que no cruzan un límite. Esta expresión devuelve un entero en elunitespecificado. SiendDateprecedestartDatea, devuelve un entero negativo.CampoObligatorio/OpcionalDescripciónstartDateRequerido
endDateRequerido
El final del período de tiempo.
endDatepuede ser cualquier expresión que se resuelva en una fecha, una marca de tiempo o un ID de objeto.unitRequerido
La medición de tiempo
unitentrestartDateendDatey. Es una expresión que se resuelve en una cadena:yearquarterweekmonthdayhourminutesecondmillisecond
timezoneOpcional
La zona horaria para realizar la operación.
<tzExpression>debe ser una expresión válida que se resuelva en una cadena formateada como un identificador de zona horaria de Olsono una diferencia UTC. Si notimezonese proporciona, el resultado se muestraUTCen.FormatoEjemplosIdentificador de zona horaria de 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 usa cuando la unidad
weekes. El valor predeterminadoSundayes. ElstartOfWeekparámetro es una expresión que se resuelve en una cadena que no distingue entre mayúsculas y minúsculas:monday(omon)tuesday(otue)wednesday(owed)thursday(othu)friday(ofri)saturday(osat)sunday(osun)
Tip
Expresiones, tipos BSON.
Comportamiento
Sin unidades fraccionarias
La expresión $dateDiff devuelve la diferencia entera entre startDate y endDate medidos 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 una diferencia de 18 meses devolverían una diferencia de 1 year en lugar de 1.5 years.
Inicio de semana
El inicio de week es Sunday a menos que se modifique con el parámetro startOfWeek. Se contabilizará cualquier semana que comience entre startDate y endDate del día especificado. El conteo de semanas no está limitado por los calendarios month ni 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 la diferencia horaria del identificador de zona horaria Olson. El ejemplo utiliza los operadores $hour y para devolver las partes correspondientes del $minute date campo:
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 bisiestos.
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$avgde la etapa$grouputiliza $dateDiff en cada documento para obtener el tiempo entre las fechas purchased y delivered. El valor resultante se devuelve como averageTime.
La parte decimal de averageTime se trunca ()$trunc $project en la etapa para producir un resultado como este:
{ "numDays" : 4.6 }
Precisión del resultado
Crea esta colección con fechas de inicio y finalización de 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 horaria expresada en el entero units. No hay fracciones en una unidad. Por ejemplo, al contar en years no hay medios años.
En este ejemplo, observe cómo al cambiar unit se modifica 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 esta 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 esta 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.Como el 31es domingo y está entre
startDateyendDate, se agrega unweekal recuento.El recuento
weekse incrementa incluso cuando una semana del calendario finaliza después delendDateo en el siguiente período del calendario.