$dateDiff (aggregation)
On this page本页内容
Definition定义
$dateDiffNew in version 5.0.5.0版新增。Returns the difference between two dates.返回两个日期之间的差值。The$dateDiffexpression has this syntax:$dateDiff表达式具有以下语法:{
$dateDiff: {
startDate: <Expression>,
endDate: <Expression>,
unit: <Expression>,
timezone: <tzExpression>,
startOfWeek: <String>
}
}Subtracts从startDatefromendDate.endDate中减去startDate。Returns an integer in the specified返回指定unit.unit的整数。Field字段Required/Optional必需/可选Description描述startDateRequired必要的The start of the time period.时间段的开始。ThestartDatecan be any expression that resolves to a Date, a Timestamp, or an ObjectID.startDate可以是解析为Date、Timestamp或ObjectID的任何表达式。endDateRequired必要的The end of the time period.时间段的结束。TheendDatecan be any expression that resolves to a Date, a Timestamp, or an ObjectID.endDate可以是解析为Date、Timestamp或ObjectID的任何表达式。unitRequired必要的The time measurementunitbetween thestartDateandendDate.startDate和endDate之间的时间度量unit。It is an expression that resolves to a string:它是一个解析为字符串的表达式:yearquarterweekmonthdayhourminutesecondmillisecond
timezoneOptional可选的The timezone to carry out the operation.执行操作的时区<tzExpression>must be a valid expression that resolves to a string formatted as either an Olson Timezone Identifieror a UTC Offset
.
<tzExpression>必须是一个有效的表达式,该表达式解析为一个格式为Olson时区标识符或UTC偏移
的字符串。
If no如果没有提供timezoneis 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"startOfWeekOptional可选的Used when the unit is equal to当单位等于week.week时使用。Defaults to默认为Sunday.Sunday。ThestartOfWeekparameter is an expression that resolves to a case insensitive string:startOfWeek参数是一个解析为不区分大小写的字符串的表达式:monday(ormon)tuesday(ortue)wednesday(orwed)thursday(orthu)friday(orfri)saturday(orsat)sunday(orsun)
See also: 另请参阅:
Behavior行为
No Fractional Units无分数单位
The $dateDiff expression returns the integer difference between the startDate and endDate measured in the specified units. $dateDiff表达式返回以指定单位测量的startDate和endDate之间的整数差。Durations are measured by counting the number of times a unit boundary is passed. For example, two dates that are 18 months apart would return 1 工期是通过计算通过单位边界的次数来衡量的。例如,相隔18个月的两个日期将返回year difference instead of 1.5 years.1年的差异,而不是1.5年。
Start Of Week本周开始
The start of the 除非week is Sunday unless modified by the startOfWeek parameter. startOfWeek参数进行了修改,否则周的开始时间为周日。Any week that begins between the 从指定日期的startDate and endDate on the specified day will be counted. startDate到endDate之间开始的任何一周都将被计算在内。The week count is not bounded by calendar 周计数不受日历month or calendar year.month或日历year的限制。
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运算符返回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" }
}
}
}])
The operation returns the following result:该操作返回以下结果:
{
"_id": 1,
"nycHour" : 5,
"nycMinute" : 24,
"gmtHour" : 10,
"gmtMinute" : 24,
"nycOlsonHour" : 6,
"nycOlsonMinute" : 24
}
Additional Details其他详细信息
The algorithm calculates the date difference using the Gregorian calendar.该算法使用公历计算日期差。
Leap years and daylight savings time are accounted for but not leap seconds.闰年和夏令时被计算在内,但没有闰秒。
The difference returned can be negative.返回的差值可以是负数。
Examples实例
Elapsed Time运行时间
Create a collection of customer orders:创建客户订单集合:
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")
}
]
)
The following example:以下示例:
Returns the average number of days for a delivery.返回交货的平均天数。Uses使用dateDiffto calculate the difference between thepurchaseddate and thedelivereddate.dateDiff计算purchased(购买)日期和delivered(交付)日期之间的差异。
db.orders.aggregate(
[
{
$group:
{
_id: null,
averageTime:
{
$avg:
{
$dateDiff:
{
startDate: "$purchased",
endDate: "$delivered",
unit: "day"
}
}
}
}
},
{
$project:
{
_id: 0,
numDays:
{
$trunc:
[ "$averageTime", 1 ]
}
}
}
]
)
The $avg accumulator in the $group stage uses $dateDiff on each document to get the time between the purchased and delivered dates. $group阶段的$avg累加器在每个文档上使用$dateDiff来获取purchased(购买)日期和delivered(交付)日期之间的时间。The resulting value is returned as 结果值将作为averageTime.averageTime返回。
The decimal portion of the averageTime is truncated ($trunc) in the $project stage to produce output like this:averageTime的小数部分在$project阶段被截断($trunc),以产生如下输出:
{ "numDays" : 4.6 }
Result Precision结果精度
Create this collection with starting and ending dates for a subscription.创建此集合,其中包含订阅的开始日期和结束日期。
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")
}
]
)
The $dateDiff expression returns a time difference expressed in integer units. $dateDiff表达式返回以整数unit表示的时间差。There are no fractional parts of a unit. 一个单位没有小数部分。For example, when counting in 例如,当以years there are no half years.years为单位计算时,没有半年。
In this example, note how changing the 在本例中,请注意更改unit changes the returned precision:unit如何更改返回的精度:
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
}
}
]
)
The results are summarized in this table:结果汇总如下表所示:
| Start | End | Years | Months | Days |
|---|---|---|---|---|
| 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 |
The count only increments when a new 计数仅在新unit starts, so 18 months are reported as 1 year in the second row and 60 days are reported as one month in the third row.unit启动时递增,因此第二行中18个月报告为1年,第三行中60天报告为1个月。
Weeks Per Month每月周数
Create a collection of months:创建月份集合:
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")
},
]
)
You can change the start of each week, and count the resulting number of weeks in each month with the following code:您可以更改每周的开始时间,并使用以下代码计算每月的周数:
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
}
}
]
)
The results are summarized in this table:结果汇总如下表所示:
| Month | Sunday | Monday | Friday |
|---|---|---|---|
| January | 5 | 4 | 4 |
| February | 4 | 3 | 4 |
| March | 4 | 4 | 4 |
From the results:从结果来看:
When the当startOfWeekis Sunday, the 5thweekin January, 2021 begins on the 31st.startOfWeek是周日时,2021年1月的第5周从31日开始。Because the 31st is a Sunday and it is between由于31日是星期日,并且介于startDateandendDate, oneweekis added to the count.startDate和endDate之间,因此计数中会添加一周。The即使日历周在weekcount is incremented even when a calendar week finishes afterendDateor in the next calendar period.endDate之后或在下一个日历周期内结束,周计数也会增加。