Definição
$dateDiffNovidade na versão 5.0.
Retorna a diferença entre duas datas.
The
$dateDiffexpression has this syntax:{ $dateDiff: { startDate: <Expression>, endDate: <Expression>, unit: <Expression>, timezone: <tzExpression>, startOfWeek: <String> } } $dateDiffcalculates the difference by counting the upper boundaries of time intervals crossed fromstartDatetoendDatewithin thetimezone. The time intervals length is equal to oneunitand are aligned so that their boundaries occur at integer multiples ofunitalong the time axis. It excludes partial units that do not cross a boundary. This expression returns an integer in the specifiedunit. IfendDateprecedesstartDate, it returns a negative integer.CampoObrigatório/OpcionalDescriçãostartDateObrigatório
endDateObrigatório
unitObrigatório
A medição de tempo
unitentrestartDateeendDate. É uma expressão que se resolve para uma string:yearquarterweekmonthdayhourminutesecondmillisecond
timezoneOpcional
The timezone to carry out the operation.
<tzExpression>must be a valid expression that resolves to a string formatted as either an Olson Timezone Identifier or a UTC Offset:Identificador de fuso horário Olson: por exemplo,
"America/New_York","Europe/London","GMT"Deslocamento UTC: por exemplo,
"+04:45","-0530","+03"
Se você omitir
timezone, o resultado será exibido emUTC.startOfWeekOpcional
Usado quando a unidade é igual a
week. O padrão éSunday. O parâmetrostartOfWeeké uma expressão que resolve uma string que não diferencia maiúsculas de minúsculas:monday(oumon)tuesday(outue)wednesday(ouwed)thursday(outhu)friday(oufri)saturday(ousat)sunday(ousun)
Dica
Comportamento
Sem unidades fracionárias
A expressão $dateDiff retorna um número inteiro comparando uma parte específica de cada data. Para a unidade year, ela compara os valores do ano: qualquer data em 2022 está a uma year de qualquer data em 2023. Para a unidade week, ela compara os números da semana: qualquer data na semana 5 está a uma week de qualquer data na semana 6.
$dateDiff conta os limites da unidade ultrapassados entre startDate e.endDate Não mede a duração decorrido. Por exemplo, $dateDiff reporta uma diferença de um year entre de dezembro 31 de2022 e janeiro 1 2023de. O limite de um ano foi ultrapassado, embora algumas horas se tenham passado entre as duas datas. Consulte Passagem do limite do ano para obter um exemplo completo.
Início da semana
O início do week é Sunday, a menos que seja modificado pelo parâmetro startOfWeek. $dateDiff conta qualquer semana que comece entre startDate e endDate no dia especificado. A contagem de semanas não é limitada pelo calendário month ou pelo calendário year.
Fuso horário
Ao usar um identificador de fuso horário Olson no campo <timezone>, o MongoDB aplica a compensação de horário de verão, se aplicável ao fuso horário especificado.
Por exemplo, considere uma collection sales com o seguinte documento:
db.sales.insertOne( { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:15:39.736Z") } )
A seguinte agregação ilustra como o MongoDB lida com o deslocamento DST para o Identificador de fuso horário Olson. O exemplo utiliza os operadores $hour e $minute para retornar as partes correspondentes do 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" } } } }])
A operação retorna o seguinte resultado:
{ "_id": 1, "nycHour" : 5, "nycMinute" : 24, "gmtHour" : 10, "gmtMinute" : 24, "nycOlsonHour" : 6, "nycOlsonMinute" : 24 }
Detalhes adicionais
O algoritmo calcula a diferença de data usando o calendário gregoriano.
Os anos bissextos e o horário de verão são contabilizados, mas não os segundos bissextos.
A diferença retornada pode ser negativa.
Exemplos
Tempo decorrido
Crie uma coleção 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") } ] )
O seguinte exemplo:
Retorna o número médio de dias para uma entrega.
Utiliza
dateDiffpara calcular a diferença entre a data depurchasede a data dedelivered.
db.orders.aggregate( [ { $group: { _id: null, averageTime: { $avg: { $dateDiff: { startDate: "$purchased", endDate: "$delivered", unit: "day" } } } } }, { $project: { _id: 0, numDays: { $trunc: [ "$averageTime", 1 ] } } } ] )
O acumulador de $avg na etapa $group utiliza $dateDiff em cada documento para obter o tempo entre as datas de purchased e delivered. O valor resultante é retornado como averageTime.
A parte decimal do averageTime é truncada($trunc) no estágio $project para produzir uma saída como esta:
{ "numDays" : 4.6 }
Precisão do resultado
Crie esta coleção com datas de início e fim para uma assinatura.
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") } ] )
A expressão $dateDiff retorna uma diferença de tempo expressa no número inteiro units. Não há partes fracionárias de uma unidade. Por exemplo, ao contar em years não há meios anos.
Neste exemplo, observe como alterar o unit altera a precisão retornada:
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 } } ] )
Os resultados são resumidos nesta tabela:
Iniciar | End | Anos | Meses | Dias |
|---|---|---|---|---|
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 |
Na segunda linha, 2010-01-01 e 2011-07-01 estão em anos diferentes (2010 e 2011), então $dateDiff retorna 1 year. Na terceira linha, 2010-03-01 (março) e 2010-04-30 (abril) diferem em um mês, então $dateDiff retorna 1 month.
Cruzamento de limites de ano
Crie uma coleção com duas datas que estão a apenas algumas horas de distância, mas caem em ambos os lados de um limite de ano civil:
db.events.insertOne( { start: ISODate("2022-12-31T20:00:00Z"), end: ISODate("2023-01-01T02:00:00Z") } )
Use $dateDiff com a unidade year para encontrar a diferença entre as duas datas:
db.events.aggregate( [ { $project: { _id: 0, yearsApart: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "year" } } } } ] )
A operação retorna o seguinte resultado:
{ "yearsApart" : 1 }
Embora apenas seis horas tenham se passado entre as duas datas, $dateDiff retorna 1 porque as datas caem em anos civis diferentes. Isso reflete o fato de que $dateDiff conta os limites da unidade cruzados em vez da duração decorrida.
Semanas por mês
Crie uma coleção 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") }, ] )
Você pode alterar o início de cada semana e contar o número resultante de semanas em cada mês com o seguinte 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 } } ] )
Os resultados são resumidos nesta tabela:
Mês | Domingo | Segunda-feira | Sexta-feira |
|---|---|---|---|
Janeiro | 5 | 4 | 4 |
Fevereiro | 4 | 3 | 4 |
Março | 4 | 4 | 4 |
Dos resultados:
Quando
startOfWeekfor domingo, dia 5weekde janeiro de 2021 começa no dia 31.Como o 31º é um domingo e está entre
startDateeendDate, umweeké adicionado à contagem.A contagem de
weeké incrementada mesmo quando uma semana de calendário termina apósendDateou no próximo período de calendário.