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> } } Subtrai
startDatedeendDate. Retorna um número inteiro nounitespecificado.CampoObrigatório/OpcionalDescriçãostartDateObrigatório
O início do período. O
startDatepode ser qualquer expressão que resolva para uma Data, um carimbo de Data/hora ou um ObjectID.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 formatada como um Identificador de fuso horário Olson ou um Deslocamento UTC. Se nenhumtimezonefor fornecido, o resultado será exibido emUTC.FormatarExemplosIdentificador de fuso horário Olson
"America/New_York" "Europe/London" "GMT" UTC Offset
+/-[hh]:[mm], e.g. "+04:45" +/-[hh][mm], e.g. "-0530" +/-[hh], e.g. "+03" 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 a diferença de número inteiro entre startDate e endDate medido no units especificado. As durações são medidas contando o número de vezes que um limite unitário é passado. Por exemplo, duas datas com 18 meses de diferença retornariam uma diferença de 1 year em vez de 1,5 years.
Início da semana
O início do week é Sunday, a menos que seja modificado pelo parâmetro startOfWeek. Qualquer semana que comece entre startDate e endDate no dia especificado será contada. 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 o deslocamento de horáriode verão , se aplicável, para o fuso horário especificado.
Por exemplo, considere uma collection sales com o seguinte documento:
{ "_id" : 1, "item" : "abc", "price" : 20, "quantity" : 5, "date" : ISODate("2017-05-20T10:24:51.303Z") }
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 |
A contagem só aumenta quando um novo unit começa, portanto, 18 meses são relatados como 1 ano na segunda linha e 60 dias são relatados como um mês na terceira linha.
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.