定義
$dateDiffバージョン 5.0 の新機能。
2 つの日付の差を返します。
The
$dateDiffexpression has this syntax:{ $dateDiff: { startDate: <Expression>, endDate: <Expression>, unit: <Expression>, timezone: <tzExpression>, startOfWeek: <String> } } $dateDiffcalculates the difference by counting the upper boundaries of time intervals crossed fromstartDatetoendDatewithin thetimezone. The time intervals length is equal to oneunitand are aligned so that their boundaries occur at integer multiples ofunitalong the time axis. It excludes partial units that do not cross a boundary. This expression returns an integer in the specifiedunit. IfendDateprecedesstartDate, it returns a negative integer.フィールド必須/オプション説明startDate必須
endDate必須
unit必須
startDateとendDateの間の、時間測定のunit。これは以下の文字列に変換される式です。yearquarterweekmonthdayhourminutesecondmillisecond
timezone任意
操作を実行するタイムゾーン。
<tzExpression>は、有効な式であり、Olson タイムゾーン識別子 または UTC オフセット として形式化された string に解決される必要があります。Olsonタイムゾーン識別子:例:
"America/New_York"、"Europe/London"、"GMT"UTC オフセット: 例えば、
"+04:45"、"-0530"、"+03"
timezoneを省略すると、結果はUTCに表示されます。startOfWeek任意
単位が
weekと等しい場合に使用されます。デフォルトはSundayです。startOfWeekパラメータは、大文字と小文字を区別しない文字列に変換される式です。monday(またはmon)tuesday(またはtue)wednesday(またはwed)thursday(またはthu)friday(またはfri)saturday(またはsat)sunday(またはsun)
Tip
動作
分数単位なし
$dateDiff式は、各日付の特定の部分を比較することで整数を返します。year単位の場合、年の値が比較されます。2022のどの日付も2023のどの日付ともyearだけ離れています。week単位の場合、週番号が比較されます。第5週のどの日付も第6週のどの日付ともweekだけ離れています。
$dateDiff counts the unit boundaries crossed between startDate and endDate. It does not measure elapsed duration. For example, $dateDiff reports a difference of one year between December 31, 2022 and January 1, 2023. A year boundary was crossed, even though a few hours passed between the two dates. See Year Boundary Crossing for a full example.
週の開始
startOfWeek パラメータによって変更されない限り、week は Sunday から始まります。$dateDiff は、指定された日の startDate と endDate の間に始まるすべての週をカウントします。週数は暦上の month または year によって制限されません。
タイムゾーン
<timezone> フィールドで Olson タイムゾーン識別子を使用する場合、MongoDB は指定されたタイムゾーンに該当する場合は DST オフセットを適用します。
たとえば、次のドキュメントを含む sales コレクションを考えます。
db.sales.insertOne( { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:15:39.736Z") } )
次の集計は、MongoDB がタイムゾーン識別子の 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 アキュムレータでは、purchased の日付からdelivered の日付までの期間の取得に $dateDiff を使用します。結果の値は 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 |
2 行目では、2010-01-01 と 2011-07-01 は年が異なります(2010 と 2011)。したがって、$dateDiff は 1 year を返します。3 行目では、2010-03-01 (3 月)と 2010-04-30 (4 月)は 1 か月異なります。したがって、$dateDiff は 1 month を返します。
年境の越え
数時間しか離れていないが、暦年の境界の両側にある 2 つの日付を持つコレクションを作成します。
db.events.insertOne( { start: ISODate("2022-12-31T20:00:00Z"), end: ISODate("2023-01-01T02:00:00Z") } )
year 単位の $dateDiff を使用して、2 つの日付の間の違いを検出します。
db.events.aggregate( [ { $project: { _id: 0, yearsApart: { $dateDiff: { startDate: "$start", endDate: "$end", unit: "year" } } } } ] )
この操作では、次の結果を返します。
{ "yearsApart" : 1 }
2つの日付の間に6時間しか経っていないにもかかわらず、日付が異なる暦年に属するため、$dateDiffは1を返します。これは、$dateDiffが経過時間ではなく、単位の境界を超えた回数をカウントすることを示しています。
1 か月あたりの週数
月のコレクションを作成します。
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 } } ] )
結果を次の表にまとめています。
月 | Sunday | Monday | Friday |
|---|---|---|---|
1月 | 5 | 4 | 4 |
2月 | 4 | 3 | 4 |
3月 | 4 | 4 | 4 |
結果より:
startOfWeekが日曜日の場合、2021 年 1 月の第 5 週 (week) は31日から始まります。31日は日曜日で、
startDateからendDateの間であるため、カウントに 1weekが追加されます。暦上の週が
endDate以降、または暦上の次の期間内に終了する場合でも、weekカウントは増加します。