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

$dateAdd(聚合)

在此页面上

  • 定义
  • 行为
  • 示例
$dateAdd

版本 5.0 中的新增功能

Date() 对象递增指定数量的时间单位。

$dateAdd 表达式的语法如下:

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

返回 Date()startDate 可以是解析为 Date、Timestamp 或 ObjectId 类型的任何表达式。无论使用哪种数据类型作为输入,返回的值都将是 Date() 对象。

字段
必需/可选
说明
startDate
必需
加法运算的开始日期(以 UTC 为单位)。startDate 可以是任何可解析为日期时间戳对象标识符表达式
unit
必需

用于测量添加到 startDate 中的时间 amountunitunit 是一个表达式,可解析为以下字符串之一:

  • year

  • quarter

  • week

  • month

  • day

  • hour

  • minute

  • second

  • millisecond

amount
必需
添加到 startDate 中的 units 个数。amount 是解析为整数或长整数的表达式amount 也可以解析为十进制整数或 double,前提是该值可以在不降低精度的情况下转换为长整数。
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"

有关表达式和类型的更多信息,请参阅表达式操作符BSON 类型

MongoDB 遵循流行的数据库使用情况并使用 UTC 时间。dateAdd 表达式始终采用 UTC 格式的startDate 并返回 UTC 格式的结果。如果指定了 timezone,则将使用指定的 timezone 完成计算。当计算涉及夏令时 (DST) 时,时区尤其重要。

如果 unitmonth,则操作将调整以考虑该月的最后一天。例如,在 10 月的最后一天添加一个 month,结果演示了“月末最后一天”调整。

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

请注意,返回的日期 ISODate("2020-11-30T12:10:05Z") 是 30 日,而不是 31 日,因为 11 月的天数比 10 月少。

<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.shipping.insertMany(
[
{ custId: 456, purchaseDate: ISODate("2020-12-31") },
{ custId: 457, purchaseDate: ISODate("2021-02-28") },
{ custId: 458, purchaseDate: ISODate("2021-02-26") }
]
)

正常发货时间为 3 天。您可以在聚合管道中使用 $dateAdd 设置 expectedDeliveryDate 为未来 3 天。

db.shipping.aggregate(
[
{
$project:
{
expectedDeliveryDate:
{
$dateAdd:
{
startDate: "$purchaseDate",
unit: "day",
amount: 3
}
}
}
},
{
$merge: "shipping"
}
]
)

$project 阶段用 $dateAddpurchaseDate 加了 3 天后,$merge 阶段用 expectedDeliveryDate 更新原始文档。

生成的文档如下所示:

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

使用以下代码更新上一个示例中的 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" ) } }
)

您想要找到延迟发货的订单。在 $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"
}
}
}
}
]
)

$match 阶段在表达式 ($expr) 中使用 $gt$dateAdd 将实际 deliveryDate 与预期日期相比较。交付日期超过 purchaseDate 后 5 天的文档将被传送到 $project 阶段。

$project 阶段使用 $dateToString 表达式将日期转换为更可读的格式。如果不转换,MongoDB 将以 ISODate 格式返回日期。

在此示例中,仅返回一条记录:

{ "custId" : 456, "purchased" : "2020-12-31", "delivery" : "2021-01-10" }

所有日期均以 UTC 时间存储在内部。指定 timezone 时,$dateAdd 使用当地时间进行计算。结果以 UTC 时间显示。

您的客户分布在多个时区,您想了解如果您在 dayhour 之前计费,夏令时可能会对计费周期产生什么影响。

创建此连接时间的集合:

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

首先向每个文档中的 login 日期添加 1 天,然后添加 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()

$dateToString 表达式将输出重新格式化,以提高可读性。现将结果汇总如下:

字段
New York
墨西哥城
开始
2021-03-13 15:00
2021-03-13 10:00
开始,TZ Info
2021-03-13 10:00
2021-03-13 04:00
1 天
2021-03-14 14:00
2021-03-14 10:00
1 天,TZ Info
2021-03-14 10:00
2021-03-14 04:00
24 小时
2021-03-14 15:00
2021-03-14 10:00
24 小时,TZ Info
2021-03-14 11:00
2021-03-14 04:00

该图表突出显示以下几点:

  • 未格式化的日期以 UTC 格式返回。纽约的 $login 为 UTC -5,但startdayshours 行显示 UTC 时间。

  • 3 月 14 日是纽约而不是墨西哥的夏令时开始时间。当一个位置切换到夏令时并从一个 day 跨越到下一个时,计算出的时间会进行调整。

  • DST 修改 day 的长度,而不是 hour 的长度。hours 的 DST 没有变化。仅当测量值 unit 不低于 day 且计算跨越指定的 timezone 中的时钟变化时,才会对 DST 进行调整。

提示

另请参阅:

后退

$covarianceSamp

在此页面上