Definição
$dateDiffNovidades na versão 5.0.:
Retorna a diferença entre duas datas.
A expressão
$dateDifftem esta sintaxe:{ $dateDiff: { startDate: <Expression>, endDate: <Expression>, unit: <Expression>, timezone: <tzExpression>, startOfWeek: <String> } } $dateDiffcalcula a diferença contando os limites superiores dos intervalos de tempo cruzados destartDateparaendDatedentro dotimezone. O comprimento dos intervalos de tempo é igual a umunite está alinhado de forma que seus limites ocorram em múltiplos inteiros deunitao longo do eixo do tempo. Exclui unidades parciais que não cruzam um limite. Esta expressão retorna um número inteiro nounitespecificado. SeendDateprecederstartDate, ele retornará um número inteiro negativo.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
O fuso horário para realizar a operação.
<tzExpression>deve ser uma expressão válida que resolva para uma string no formato de um Identificador de fuso horário Olson ou um Deslocamento UTC: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.
Passagem do Limite do Ano
Crie uma coleção com duas datas com apenas algumas horas de diferença, mas que estejam em cada lado do limite do ano calendário:
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 passado entre as duas datas, $dateDiff retorna 1 porque as datas estão em anos calendário diferentes. Isso reflete o fato de que $dateDiff conta os limites unitários ultrapassados 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.