Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

$dateSubtract (operador de expresión)

$dateSubtract

Nuevo en la versión 5.0.

Decrementa un Date() objeto por un número especificado de unidades de tiempo.

La $dateSubtract La expresión tiene la siguiente sintaxis:

{
$dateSubtract: {
startDate: <Expression>,
unit: <Expression>,
amount: <Expression>,
timezone: <tzExpression>
}
}

Retorna un Date(). El startDate puede ser cualquier expresión que resuelva a un tipo Date, Timestamp u ObjectId. No importa qué tipo de datos se haya utilizado como entrada, el valor retornado será un objeto Date().

Campo
Obligatorio/Opcional
Descripción

startDate

Requerido

La fecha de inicio, en UTC, para la operación de resta. El startDate puede ser cualquier expresión que resuelva en una Fecha, un Sello de tiempo o un ObjectID.

unit

Requerido

El unit utilizado para medir el amount del tiempo restado del startDate. El unit es una expresión que se resuelve en una de las siguientes cadenas:

  • year

  • quarter

  • week

  • month

  • day

  • hour

  • minute

  • second

  • millisecond

amount

Requerido

El número de units restado de startDate. El amount es una expresión que se resuelve a un entero o long. El amount también puede resolverse a un decimal integral y/o a un double si ese valor puede convertirse a un long sin pérdida de precisión.

timezone

Opcional

La zona horaria para llevar a cabo la operación. <tzExpression> debe ser una expresión válida que se resuelva en una string formateada como un Identificador de zona horaria Olson o un Diferencia UTC. Si no se proporciona timezone, el resultado se muestra en UTC.

Formato
Ejemplos

Identificador de zona horaria Olson

"America/New_York"
"Europe/London"
"GMT"

Desplazamiento UTC

+/-[hh]:[mm], e.g. "+04:45"
+/-[hh][mm], e.g. "-0530"
+/-[hh], e.g. "+03"

Para obtener más información sobre expresiones y tipos consulta Expresiones y BSON types.

MongoDB sigue el uso prevalente de bases de datos y trabaja con el tiempo en UTC. La expresión dateSubtract siempre toma un startDate en UTC y devuelve un resultado en UTC. Si se especifica el timezone, el cálculo se realizará utilizando el timezone especificado. La zona horaria es especialmente importante cuando un cálculo implica el horario de verano (DST).

Si el unit es un month, o mayor, la operación se ajusta para tener en cuenta el último día del mes. Restar una month el último día de marzo, por ejemplo, demuestra el ajuste "último día del mes".

{
$dateSubtract:
{
startDate: ISODate("2021-03-31T12:10:05Z"),
unit: "month",
amount: 1
}
}

Tenga en cuenta que la fecha devuelta, ISODate("2021-02-28T12:10:05Z"), es la 28 y no la 31, ya que febrero tiene menos días que marzo.

Al utilizar un identificador de zona horaria de Olson en el campo <timezone>, MongoDB aplica el Desplazamiento del horario de verano, si corresponde para la zona horaria especificada.

Por ejemplo, considera una colección sales con el siguiente documento:

db.sales.insertOne(
{
"_id" : 1,
"item" : "abc",
"price" : 10,
"quantity" : 2,
"date" : ISODate("2014-01-01T08:15:39.736Z")
}
)

La siguiente agregación ilustra cómo MongoDB gestiona el ajuste de DST para el identificador de zona horaria Olson. El ejemplo usa los operadores $hour y $minute para devolver las partes correspondientes del 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" }
}
}
}])

La operación devuelve el siguiente resultado:

{
"_id": 1,
"nycHour" : 5,
"nycMinute" : 24,
"gmtHour" : 10,
"gmtMinute" : 24,
"nycOlsonHour" : 6,
"nycOlsonMinute" : 24
}

Considera una colección de tiempos de conexión del sistema como estos:

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")
}
]
)

Debido a un problema de servicio, necesitas restar 3 horas de cada uno de los horarios de cierre de sesión de enero de 2021. Puedes usar $dateSubtract en un pipeline de agregación para decrementar el 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"
}
]
)

Se hacen dos comparaciones similares en la etapa $match. Primero, los operadores $year y $month extraen el año y el mes, respectivamente, del objeto de fecha logoutTime. Luego, se comprueba el mes y el año para ver si coinciden con los objetivos de selección. Dado que "enero" está codificado como "1", $expr es verdadero cuando el año y el mes son iguales ($eq) a "2021" y "1".

La etapa $project usa $dateSubtract para restar 3 horas del logoutTime de cada documento seleccionado.

Finalmente, la etapa $merge actualiza la colección, escribiendo el nuevo logoutTime para los documentos modificados.

Nota

A diferencia de $out, la etapa $merge solo actualiza los documentos coincidentes y conserva el resto de la colección. Para más detalles, consulta: $out en comparación con $merge.

Los documentos resultantes se ven así:

{
"_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")
}

Desea enviar una encuesta a los clientes que hayan utilizado su servicio en la última semana. La expresión $dateSubtract puede crear un filtro de rango relativo al momento en que se ejecuta la query.

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"
}
}
}
}
]
)

La variable de agregación integrada$$NOWdevuelve la fecha y hora actual en formato ISODate. La etapa$matchutiliza el valor de$$NOWpara obtener la fecha actual. A continuación, la expresión de comparación ($expr) filtra la colección utilizando valores mayores que ($gt) y $dateSubtract para encontrar los documentos con un valor de logoutTime en la última semana.

La etapa $project utiliza la expresión para convertir las fechas a un formato más $dateToString legible. Sin la conversión, MongoDB devuelve la fecha en formato ISODate y asume la zona horaria UTC.

La salida muestra que dos clientes han cerrado sesión en la última semana.

{ "custId" : 459, "loggedOut" : "2021-02-17" }
{ "custId" : 460, "loggedOut" : "2021-02-18" }

Todas las fechas se almacenan internamente en hora UTC. Cuando se especifica timezone, $dateSubtract utiliza la hora local para realizar los cálculos. Los resultados se muestran en UTC.

Tienes clientes en varias zonas horarias y quieres ver qué efecto podría tener el horario de verano en tus períodos de facturación si facturas por day o por hour.

Crea esta colección de tiempos de conexión:

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")
}
]
)

Primero reste 1 día, luego reste 24 horas de las fechas login en 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()

La expresión reformatea la salida para facilitar su lectura. Los resultados se resumen a $dateToString continuación:

Campo
New York
Ciudad de México

Inicio

2021-03-14 15:00

2021-03-14 15:00

Comienzo, Info TZ

2021-03-14 11:00

2021-03-14 04:00

1 día

2021-03-13 16:00

2021-03-13 15:00

1 día, 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

La gráfica destaca varios puntos:

  • Las fechas sin formato se devuelven en UTC. El $login de Nueva York es UTC -5, sin embargo las filas start, days y hours muestran la hora en UTC.

  • El 14 de marzo es el inicio del horario de verano en Nueva York, pero no en México. El tiempo calculado se ajusta cuando una ubicación cambia al horario de verano y cruza de uno day al siguiente.

  • El horario de verano (DST) modifica la duración de day, no de hour. No hay horario de verano (DST) para hours. Solo hay un ajuste por horario de verano (DST) cuando la medición unit es de day o más y el cálculo cruza un cambio de horario en el timezone especificado.

Tip

Volver

$dateFromString

En esta página