Definição
$dateSubtractNovidades na versão 5.0.
Reduz um objeto dedata por um número específico de unidades de tempo.
A expressão
$dateSubtracttem a seguinte sintaxe:{ $dateSubtract: { 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
A data de início, em UTC, para a operação de subtração. O
startDatepode ser qualquer expressão que resolva para uma Data, um Timestamp ou um ObjectID.unitObrigatório
O
unitusado para medir oamountde tempo subtraído dostartDate. Ounité uma expressão que se resolve em uma das seguintes strings:yearquarterweekmonthdayhourminutesecondmillisecond
amountObrigatório
O número de
unitssubtraído destartDate. Oamounté uma expressão que resolve para um inteiro ou longo. Oamounttambém pode resolver para um decimal integral e ou um double se esse valor puder ser convertido em um 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 dateSubtract 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. Subtraindo um month no último dia de março, por exemplo, demonstra o ajuste de "último dia do mês".
{ $dateSubtract: { startDate: ISODate("2021-03-31T12:10:05Z"), unit: "month", amount: 1 } }
Observe que a data de regresso, ISODate("2021-02-28T12:10:05Z"), é a e não a desde fevereiro tem menos dias do que março.
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
Subtrair uma quantia fixa
Considere uma coleção de tempos de conexão do sistema como estes:
db.connectionTime.insertMany( [ { custId: 457, login: ISODate("2020-12-25T19:04:00"), logout: ISODate("2020-12-28T09:04:00") }, { custId: 457, login: ISODate("2021-01-27T05:12:00"), logout: ISODate("2021-01-28T13:05:00") }, { custId: 458, login: ISODate("2021-01-22T06:27:00"), logout: ISODate("2021-01-31T11:00:00") }, { custId: 459, login: ISODate("2021-02-14T20:14:00"), logout: ISODate("2021-02-17T16:05:00") }, { custId: 460, login: ISODate("2021-02-26T02:44:00"), logout: ISODate("2021-02-18T14:13:00") } ] )
Devido a um problema de serviço, você precisa subtrair 3 horas de cada um dos horários de logout de janeiro de 2021. Você pode usar $dateSubtract em um aggregation pipeline para diminuir o logoutTime.
db.connectionTime.aggregate( [ { $match: { $expr: { $eq: [ { $year: "$logout" }, 2021 ] }, $expr: { $eq: [ { $month: "$logout" }, 1 ] } } }, { $project: { logoutTime: { $dateSubtract: { startDate: "$logout", unit: "hour", amount: 3 } } } }, { $merge: "connectionTime" } ] )
Duas comparações semelhantes são feitas no estágio $match. Primeiro, os operadores $year e $month extraem o ano e o mês, respectivamente, do objeto Data logoutTime. Em seguida, o mês e o ano são verificados para ver se correspondem às metas de seleção. Como "janeiro" é codificado como "1", $expr é verdadeiro quando o ano e o mês são iguais ($eq) a "2021" e "1".
O estágio $project utiliza $dateSubtract para subtrair 3 horas do logoutTime de cada dcoumento selecionado.
O estágio $merge atualiza a coleção, escrevendo o novo logoutTime para os documentos modificados.
Observação
Ao contrário $out, o estágio $merge apenas atualiza os documentos correspondentes e preserva o restante da coleção. Para mais detalhes, consulte: $out em comparação com $merge.
Os documentos resultantes têm a seguinte aparência:
{ "_id" : ObjectId("603dd94b044b995ad331c0b5"), "custId" : 457, "login" : ISODate("2020-12-25T19:04:00Z"), "logout" : ISODate("2020-12-28T09:04:00Z") } { "_id" : ObjectId("603dd94b044b995ad331c0b6"), "custId" : 457, "login" : ISODate("2021-01-27T05:12:00Z"), "logout" : ISODate("2021-01-28T13:05:00Z"), "logoutTime" : ISODate("2021-01-28T10:05:00Z") } { "_id" : ObjectId("603dd94b044b995ad331c0b7"), "custId" : 458, "login" : ISODate("2021-01-22T06:27:00Z"), "logout" : ISODate("2021-01-31T11:00:00Z"), "logoutTime" : ISODate("2021-01-31T08:00:00Z") } { "_id" : ObjectId("603dd94b044b995ad331c0b8"), "custId" : 459, "login" : ISODate("2021-02-14T20:14:00Z"), "logout" : ISODate("2021-02-17T16:05:00Z") } { "_id" : ObjectId("603dd94b044b995ad331c0b9"), "custId" : 460, "login" : ISODate("2021-02-26T02:44:00Z"), "logout" : ISODate("2021-02-18T14:13:00Z") }
Filtrar por datas relativas
Você deseja enviar uma pesquisa para clientes que usaram seu serviço na última semana. A expressão $dateSubtract pode criar um filtro de intervalo relativo ao tempo em que a consulta é executada.
db.connectionTime.aggregate( [ { $match: { $expr: { $gt: [ "$logoutTime", { $dateSubtract: { startDate: "$$NOW", unit: "week", amount: 1 } } ] } } }, { $project: { _id: 0, custId: 1, loggedOut: { $dateToString: { format: "%Y-%m-%d", date: "$logoutTime" } } } } ] )
A variável de agregação incorporada $$NOW retorna a data/hora atual no formato ISODate. O estágio $match usa o valor em $$NOW para obter a data de hoje. Em seguida, a expressão de comparação ($expr) filtra a coleção usando maior que ($gt) e $dateSubtract para combinar documentos que tiveram logoutTime na semana passada.
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. O resultado mostra que dois clientes se desconectaram na última semana.
{ "custId" : 459, "loggedOut" : "2021-02-17" } { "custId" : 460, "loggedOut" : "2021-02-18" }
Ajustar para o horário de verão
Todas as datas são armazenadas internamente no horário UTC. Quando um timezone é especificado, o $dateSubtract 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-14T10:00:00-0500"), logout: ISODate("2021-03-14T18:00:00-0500") }, { location: "America/Mexico_City", login: ISODate("2021-03-14T10:00:00-00:00"), logout: ISODate("2021-03-15T08:00:00-0500") } ] )
Primeiro subtraia 1 dia e, em seguida, subtraia 24 horas das login datas 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: { $dateSubtract: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } } } }, hours: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateSubtract: { 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: { $dateSubtract: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } }, timezone: "$location" } }, hoursTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateSubtract: { 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-14 15:00 | 2021-03-14 15:00 |
Início, TZ Info | 2021-03-14 11:00 | 2021-03-14 04:00 |
1 dia | 2021-03-13 16:00 | 2021-03-13 15:00 |
1 dias, TZInfo | 2021-03-13 11:00 | 2021-03-13 09:00 |
24 horas | 2021-03-13 15:00 | 2021-03-13 15:00 |
24 horas, TZInfo | 2021-03-13 10:00 | 2021-03-13 09: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.