$dateAdd (aggregation)
On this page本页内容
Definition定义
$dateAdd
New in version 5.0.5.0版新增。Increments a将Date()
object by a specified number of time units.Date()
对象增加指定数量的时间单位。The$dateAdd
expression has the following syntax:$dateAdd
表达式具有以下语法:{
$dateAdd: {
startDate: <Expression>,
unit: <Expression>,
amount: <Expression>,
timezone: <tzExpression>
}
}Returns a返回Date()
.Date()
。ThestartDate
can be any expression that resolves to type Date, Timestamp or ObjectId. No matter which data type is used as input, the value returned will be aDate()
object.startDate
可以是解析为Date
、Timestamp
或ObjectId
类型的任何表达式。无论使用哪种数据类型作为输入,返回的值都将是Date()
对象。Field字段Required/Optional必需/可选Description描述startDate
Required必要的The beginning date, in UTC, for the addition operation.添加操作的开始日期,以UTC为单位。ThestartDate
can be any expression that resolves to a Date, a Timestamp, or an ObjectID.startDate
可以是解析为Date
、Timestamp
或ObjectID的任何表达式。unit
Required必要的The用于测量添加到unit
used to measure theamount
of time added to thestartDate
.startDate
的时间amount
的unit
。Theunit
is an expression that resolves to one of the following strings:unit
是一个解析为以下字符串之一的表达式:year
quarter
week
month
day
hour
minute
second
millisecond
amount
Required必要的The number of添加到units
added to thestartDate
.startDate
的units
数。Theamount
is an expression that resolves to an integer or long.amount
是一个解析为整数或长的表达式。The如果可以在不损失精度的情况下将该值转换为长,则amount
can also resolve to an integral decimal or a double if that value can be converted to a long without loss of precision.amount
也可以解析为小数点整数或双精度。timezone
Optional可选的The timezone to carry out the operation.执行操作的时区。<tzExpression>
must be a valid expression that resolves to a string formatted as either an Olson Timezone Identifier必须是一个有效的表达式,该表达式解析为格式为Olson时区标识符or a UTC Offset
.
或UTC偏移的字符串
。
If no如果没有提供timezone
is provided, the result is displayed inUTC
.timezone
,结果将以UTC
显示。Format格式Examples示例Olson Timezone IdentifierOlson时区标识符"America/New_York"
"Europe/London"
"GMT"UTC Offset +/-[hh]:[mm], e.g. "+04:45"
+/-[hh][mm], e.g. "-0530"
+/-[hh], e.g. "+03"For more information on expressions and types see Expressions and BSON Types.有关表达式和类型的详细信息,请参阅表达式和BSON类型。
Behavior行为
Time Measurement时间测量
MongoDB follows prevaling database usage and works with time in UTC. MongoDB遵循普遍使用的数据库,并使用UTC中的时间。The dateAdd
expression always takes a startDate
in UTC and returns a result in UTC. dateAdd
表达式总是以UTC为起始日期,并以UTC为返回结果。If the 如果指定了timezone
is specified, the calculation will be done using the specified timezone
. timezone
,则将使用指定的timezone
进行计算。The timezone is especially important when a calculation involves Daylight Savings Time (DST).当计算涉及夏令时(DST)时,时区尤其重要。
If the 如果unit
is a month
, or larger the operation adjusts to account for the last day of the month. Adding one month
on the last day of October, for example, demonstrates the "last-day-of-the-month" adjustment.unit
是一个月或month
,则操作会根据该月的最后一天进行调整。例如,在10月的最后一天加上一个月,就表明了“一个月最后一天”的调整。
{
$dateAdd:
{
startDate: ISODate("2020-10-31T12:10:05Z"),
unit: "month",
amount: 1
}
}
Notice that the date returned, 请注意,返回的日期ISODate("2020-11-30T12:10:05Z")
, is the 30th and not the 31st since November has fewer days than October.ISODate("2020-11-30T12:10:05Z")
是第30天,而不是第31天,因为11月的天数比10月少。
Time Zone时区
When using an Olson Timezone Identifier in the 当在<timezone>
field, MongoDB applies the DST offset if applicable for the specified timezone.<timezone>
字段中使用Olson时区标识符时,MongoDB会应用DST偏移量(如果适用于指定时区)。
For example, consider a 例如,考虑具有以下文档的sales
collection with the following document:sales
集合:
{
"_id" : 1,
"item" : "abc",
"price" : 20,
"quantity" : 5,
"date" : ISODate("2017-05-20T10:24:51.303Z")
}
The following aggregation illustrates how MongoDB handles the DST offset for the Olson Timezone Identifier. 下面的聚合说明了MongoDB如何处理Olson时区标识符的DST偏移量。The example uses the 该示例使用$hour
and $minute
operators to return the corresponding portions of the date
field:$hour
和$minute
运算符返回日期字段的相应部分:
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" }
}
}
}])
The operation returns the following result:该操作返回以下结果:
{
"_id": 1,
"nycHour" : 5,
"nycMinute" : 24,
"gmtHour" : 10,
"gmtMinute" : 24,
"nycOlsonHour" : 6,
"nycOlsonMinute" : 24
}
Examples实例
Add a Future Date添加未来日期
Consider a collection of customer orders with these documents:考虑包含以下文档的客户订单集合:
db.shipping.insertMany(
[
{ custId: 456, purchaseDate: ISODate("2020-12-31") },
{ custId: 457, purchaseDate: ISODate("2021-02-28") },
{ custId: 458, purchaseDate: ISODate("2021-02-26") }
]
)
The normal shipping time is 3 days. You can use 正常运输时间为3天。您可以在聚合管道中使用$dateAdd
in an aggregation pipeline to set an expectedDeliveryDate
3 days in the future.$dateAdd
来设置未来3天的expectedDeliveryDate
。
db.shipping.aggregate(
[
{
$project:
{
expectedDeliveryDate:
{
$dateAdd:
{
startDate: "$purchaseDate",
unit: "day",
amount: 3
}
}
}
},
{
$merge: "shipping"
}
]
)
After adding 3 days to the 在purchaseDate
with $dateAdd
in the $project
stage, the $merge
stage updates the original documents with the expectedDeliveryDate
.$project
阶段中使用$dateAdd
将purchaseDate
添加3天后,$merge
阶段将使用预期的DeliveryDate
更新原始文档。
The resulting documents look like this:生成的文档如下所示:
{
"_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")
}
Filter on a Date Range按日期范围筛选
Update the 使用以下代码更新上一个示例中的shipping
collection from the last example with this code to add delivery dates to the documents:shipping
集合,以便将交货日期添加到文档中:
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" ) } }
)
You want to find late shipments. Use 您想查找延迟发货。在$dateAdd
in a $match
stage to create a filter that matches documents in a range of dates defined by a starting point ($purchaseDate
) and a time period given by $dateAdd
.$match
阶段中使用$dateAdd
可以创建一个筛选器,该筛选器匹配由起点($purchaseDate
)和$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"
}
}
}
}
]
)
The $match
stage uses $gt
and $dateAdd
in an expression ($expr
) to compare the actual deliveryDate
with an expected date. $match
阶段在表达式($expr
)中使用$gt
和$dateAdd
将实际deliveryDate
与预期日期进行比较。Documents with delivery dates more than 5 days after the 交付日期在purchaseDate
are passed on to the $project
stage.purchaseDate
后5天以上的文档将传递到$project
阶段。
The $project
stage uses the $dateToString
expression to convert the dates to a more readable format. $project
阶段使用$dateToString
表达式将日期转换为可读性更强的格式。Without the conversion, MongoDB would return the date in ISODate format.如果不进行转换,MongoDB将以ISODate
格式返回日期。
In this example only one record is returned:在本例中,只返回一条记录:
{ "custId" : 456, "purchased" : "2020-12-31", "delivery" : "2021-01-10" }
Adjust for Daylight Savings Time夏令时调整
All dates are stored internally in UTC time. When a 所有日期都以UTC时间存储在内部。指定timezone
is specified, $dateAdd
uses local time to carry out the calculations. The results are displayed in UTC.timezone
后,$dateAdd
将使用本地时间进行计算。结果以UTC显示。
You have customers in several timezones and you want to see what effect daylight savings time might have on your billing periods if you bill by 您有几个时区的客户,您想看看如果您按day
or by hour
.day
或按hour
计费,夏令时可能会对您的计费周期产生什么影响。
Create this collection of connection times:创建此连接时间集合:
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")
}
]
)
First add 1 day, then add 24 hours to the 首先在每个文档中添加1天,然后在login
dates in each document.login
日期上添加24小时。
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()
The $dateToString
expression reformats the output for readability. Results are summarized here:$dateToString
表达式重新格式化输出以提高可读性。结果总结如下:
New York | Mexico City | |
---|---|---|
Start | 2021-03-13 15:00 | 2021-03-13 10:00 |
Start, TZ Info | 2021-03-13 10:00 | 2021-03-13 04:00 |
1 Day | 2021-03-14 14:00 | 2021-03-14 10:00 |
1 Day, TZ Info | 2021-03-14 10:00 | 2021-03-14 04:00 |
24 Hours | 2021-03-14 15:00 | 2021-03-14 10:00 |
24 Hours, TZ Info | 2021-03-14 11:00 | 2021-03-14 04:00 |
The chart highlights several points:该图表突出显示了以下几点:
Unformatted dates are returned in UTC.未格式化的日期以UTC返回。The纽约的$login
for New York is UTC -5, however thestart
,days
, andhours
rows display the time in UTC.$login
是UTC-5,但是start
、days
和hours
行显示UTC时间。March 14th is the start of DST in New York, but not in Mexico.3月14日是纽约夏令时的开始,但墨西哥没有。The calculated time is adjusted when a location switches to DST and crosses from one当位置切换到夏令时并从一天穿越到下一天时,计算的时间会进行调整。day
to the next.DST modifies the length of the夏令时修改的是一天的长度,而不是小时。夏令时在数小时内没有变化。day
, not thehour
. There is no DST change forhours
.There is an only an adjustment for DST when the measurement当测量unit
isday
or larger and the computation crosses a clock change in the specifiedtimezone
.unit
为day
或更大,并且计算跨越指定时区的时钟变化时,仅对DST进行调整。