Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

$dateDiff(聚合)

在此页面上

  • 定义
  • 行为
  • 示例
$dateDiff

版本 5.0 中的新增功能

返回两个日期之间的差值。

$dateDiff 表达式的语法如下:

{
$dateDiff: {
startDate: <Expression>,
endDate: <Expression>,
unit: <Expression>,
timezone: <tzExpression>,
startOfWeek: <String>
}
}

endDate 中减去 startDate。返回指定 unit 中的整数。

字段
必需/可选
说明

startDate

必需

时间段的开始。startDate 可以是任何解析为 日期 时间戳 ObjectID 表达式。

endDate

必需

时间段的结束。endDate 可以是任何解析为日期时间戳对象标识符的表达式

unit

必需

startDateendDate 之间的时间测量单位 (unit)。它是一个解析为字符串的表达式

  • year

  • quarter

  • week

  • month

  • day

  • hour

  • minute

  • second

  • millisecond

timezone

Optional

执行操作的时区。 <tzExpression>必须是有效 表达式 string,可解析为格式为 Olson 时区标识符 的 或 UTC 偏移量 。如果未提供timezone ,则结果将显示在UTC中。

format
示例

Olson 时区标识符

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

UTC 偏移

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

startOfWeek

Optional

当单位等于 week 时使用。默认为 SundaystartOfWeek 参数是一个解析为不区分大小写的字符串的表达式

  • monday (或 mon

  • tuesday (或 tue

  • wednesday (或 wed

  • thursday (或 thu

  • friday (或 fri

  • saturday (或 sat

  • sunday (或 sun

提示

另请参阅:

$dateDiff 表达式返回指定 units 中测量到的 startDateendDate 之间的整数差。持续时间通过计算单位边界被传递的次数来测量。例如,相隔 18 个月的两个日期将返回 1 year 的差值,而不是 1.5 years

除非被 startOfWeek 参数修改,否则 week 的起始为 Sunday。在指定日子所介于的 startDateendDate 之间的任何一周都将计算在内。周计数不受日历 month 或日历 year 限制。

<timezone> 字段中使用 Olson 时区标识符时,如果适用于指定的时区,MongoDB 会应用 DST 偏移量。

例如,考虑包含以下文档的 sales 集合:

{
"_id" : 1,
"item" : "abc",
"price" : 20,
"quantity" : 5,
"date" : ISODate("2017-05-20T10:24:51.303Z")
}

以下聚合说明了 MongoDB 如何处理 Olson 时区标识符的 DST 偏移量。该示例使用 $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" }
}
}
}])

操作返回以下结果:

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

该算法使用公历计算日期差异。

考虑了闰年和夏令时,但不考虑闰秒。

返回的差值可以为负数。

创建一个客户订单集合:

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

如下示例:

  • 返回平均交付天数。

  • 使用 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 ]
}
}
}
]
)

$group 阶段中的 $avg 累加器在每个文档上使用 $dateDiff 来获取 purchaseddelivered 日期之间的时间。结果值作为 averageTime 返回。

averageTime 的十进制部分在 $project 阶段被截断 ($trunc) 以生成如下输出:

{ "numDays" : 4.6 }

使用订阅的开始日期和结束日期创建此集合。

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

$dateDiff 表达式返回以整数 units 表示的时间差。单位没有小数部分。例如,在计算 years 时,没有半年。

在本例中,请注意更改 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
}
}
]
)

结果汇总如下表所示:

开始
End
年份
月数
天数

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

该计数仅在新的 unit 开始时递增,因此第二行中的 18 个月报告为 1 年,第三行中的 60 天报告为一个月。

创建一个月份集合:

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

您可以使用以下代码更改每周的开始日期,并计算每个月的最终周数:

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

结果汇总如下表所示:

星期日
星期一
星期五

一月

5

4

4

二月

4

3

4

2022 年

4

4

4

从结果来看:

  • startOfWeek 是星期日时,2021 年 1 月的第 5 个 week 从 31 号开始。

  • 由于 31 日是周日,且介于 startDateendDate 之间,因此计数时要加上一个 week

  • 即使日历周在endDate之后或在下一个日历周期内结束, week计数也会增加。

后退

$dateAdd

在此页面上