Definição
$dateAddNovidades na versão 5.0.
Aumenta um objeto dedata por um número específico de unidades de tempo.
A expressão
$dateAddtem a seguinte sintaxe:{ $dateAdd: { startDate: <Expression>, unit: <Expression>, amount: <Expression>, timezone: <tzExpression> } } Retorna uma data. O
startDatepode ser qualquer expressão que resolva o tipo Date, Timestamp ou ObjectId. Não importa qual tipo de dados é usado como entrada, o valor retornado será um objeto de data .CampoObrigatório/OpcionalDescriçãostartDateObrigatório
unitObrigatório
O
unitusado para medir oamountde tempo adicionado aostartDate. Ounité uma expressão que se resolve em uma das seguintes strings:yearquarterweekmonthdayhourminutesecondmillisecond
amountObrigatório
O número de
unitsadicionado aostartDate. Oamounté uma expressão que resolve para um inteiro ou longo. Oamounttambém pode ser resolvido como um decimal integral ou double se esse valor puder ser convertido em um valor longo sem perda de precisão.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" Para mais informações sobre expressão e BSON types, consulte expressão e BSON types.
Comportamento
Medição de tempo
O MongoDB segue o uso predominante do banco de dados e trabalha com o tempo em UTC. A expressão dateAdd sempre pega um startDate em UTC e retorna um resultado em UTC. Se o timezone for especificado, o cálculo será feito utilizando o timezone especificado. O fuso horário é especialmente importante quando um cálculo envolve Horário de Verão (DST).
Se unit for month ou maior, a operação será ajustada para contabilizar o último dia do mês. Adicionar um month no último dia de outubro, por exemplo, demonstra o ajuste de "último dia do mês".
{ $dateAdd: { startDate: ISODate("2020-10-31T12:10:05Z"), unit: "month", amount: 1 } }
Observe que a data retornada, ISODate("2020-11-30T12:10:05Z"), é 30 e não 31, pois novembro tem menos dias do que outubro.
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 }
Exemplos
Adicionar uma data futura
Considere uma coleção de pedidos de clientes com estes documentos:
db.shipping.insertMany( [ { custId: 456, purchaseDate: ISODate("2020-12-31") }, { custId: 457, purchaseDate: ISODate("2021-02-28") }, { custId: 458, purchaseDate: ISODate("2021-02-26") } ] )
O tempo normal de envio é de 3 dias. Você pode usar $dateAdd em um aggregation pipeline para definir expectedDeliveryDate 3 dias no futuro.
db.shipping.aggregate( [ { $project: { expectedDeliveryDate: { $dateAdd: { startDate: "$purchaseDate", unit: "day", amount: 3 } } } }, { $merge: "shipping" } ] )
Após adicionar 3 dias ao purchaseDate com $dateAdd no estágio $project, o estágio $merge atualiza os documentos originais com o expectedDeliveryDate.
Os documentos resultantes têm a seguinte aparência:
{ "_id" : ObjectId("603dd4b2044b995ad331c0b2"), "custId" : 456, "purchaseDate" : ISODate("2020-12-31T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-01-03T00:00:00Z") } { "_id" : ObjectId("603dd4b2044b995ad331c0b3"), "custId" : 457, "purchaseDate" : ISODate("2021-02-28T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-03-03T00:00:00Z") } { "_id" : ObjectId("603dd4b2044b995ad331c0b4"), "custId" : 458, "purchaseDate" : ISODate("2021-02-26T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-03-01T00:00:00Z") }
Filtrar em um intervalo de datas
Atualize a coleção shipping do último exemplo com este código para adicionar datas de entrega aos documentos:
db.shipping.updateOne( { custId: 456 }, { $set: { deliveryDate: ISODate( "2021-01-10" ) } } ) db.shipping.updateOne( { custId: 457 }, { $set: { deliveryDate: ISODate( "2021-03-01" ) } } ) db.shipping.updateOne( { custId: 458 }, { $set: { deliveryDate: ISODate( "2021-03-02" ) } } )
Você deseja encontrar remessas atrasadas. Use $dateAdd em um estágio $match para criar um filtro que corresponda a documentos em uma faixa de datas definido por um ponto de partida ($purchaseDate) e um período dado por $dateAdd.
db.shipping.aggregate( [ { $match: { $expr: { $gt: [ "$deliveryDate", { $dateAdd: { startDate: "$purchaseDate", unit: "day", amount: 5 } } ] } } }, { $project: { _id: 0, custId: 1, purchased: { $dateToString: { format: "%Y-%m-%d", date: "$purchaseDate" } }, delivery: { $dateToString: { format: "%Y-%m-%d", date: "$deliveryDate" } } } } ] )
O estágio $match utiliza $gt e $dateAdd em uma expressão ($expr) para comparar o deliveryDate real com uma data esperada. Os documentos com datas de entrega superiores a 5 dias após o purchaseDate são passados para a etapa $project.
O estágio $project utiliza a expressão $dateToString para converter as datas em um formato mais legível. Sem a conversão, o MongoDB retornaria a data no formato ISODate.
Neste exemplo, apenas um registro é retornado:
{ "custId" : 456, "purchased" : "2020-12-31", "delivery" : "2021-01-10" }
Ajustar para o horário de verão
Todas as datas são armazenadas internamente no horário UTC. Quando um timezone é especificado, o $dateAdd utiliza a hora local para executar os cálculos. Os resultados são exibidos em UTC.
Você tem clientes em vários fusos horários e deseja ver o efeito que o horário de verão pode ter em seus períodos de faturamento se você faturar por day ou por hour.
Criar esta coleção de tempos de conexão:
db.billing.insertMany( [ { location: "America/New_York", login: ISODate("2021-03-13T10:00:00-0500"), logout: ISODate("2021-03-14T18:00:00-0500") }, { location: "America/Mexico_City", login: ISODate("2021-03-13T10:00:00-00:00"), logout: ISODate("2021-03-14T08:00:00-0500") } ] )
Primeiro, adicione 1 dia e, em seguida, adicione 24 horas às datas login em cada documento.
db.billing.aggregate( [ { $project: { _id: 0, location: 1, start: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$login" } }, days: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } } } }, hours: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "hour", amount: 24, timezone: "$location" } } } }, startTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$login", timezone: "$location" } }, daysTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } }, timezone: "$location" } }, hoursTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "hour", amount: 24, timezone: "$location" } }, timezone: "$location" } }, } } ] ).pretty()
A expressão $dateToString reformata a saída para legibilidade. Os resultados são resumidos aqui:
Campo | New York | Cidade do México |
|---|---|---|
Iniciar | 2021-03-13 15:00 | 2021-03-13 10:00 |
Início, TZ Info | 2021-03-13 10:00 | 2021-03-13 04:00 |
1 dia | 2021-03-14 14:00 | 2021-03-14 10:00 |
1 dia, informações TZ | 2021-03-14 10:00 | 2021-03-14 04:00 |
24 horas | 2021-03-14 15:00 | 2021-03-14 10:00 |
24 horas, informações sobre TZ | 2021-03-14 11:00 | 2021-03-14 04:00 |
O gráfico destaca vários pontos:
As datas não formatadas retornam em UTC. O
$loginpara Nova York é UTC -5, no entanto, as linhasstart,daysehoursexibem o tempo em UTC.de março é o início do DST em Nova York, mas não no México. O tempo calculado é ajustado quando um local muda para DST e cruza de um
daypara o outro.O horário de verão modifica o comprimento do
day, não dohour. Não há alteração de DST parahours. Só há um ajuste para o horário de verão quando a medidaunitédayou maior e o cálculo ultrapassa uma mudança de relógio notimezoneespecificado.