定義
- $dateSubtract
- バージョン 5.0 で追加 - 指定された時間単位数で Dateオブジェクトを減算します。 - $dateSubtract式の構文は次のとおりです。- { - $dateSubtract: { - startDate: <Expression>, - unit: <Expression>, - amount: <Expression>, - timezone: <tzExpression> - } - } - Dateを返します。 - startDateは、Date 型、Timestamp 型、または ObjectId 型に変換される任意の式にできます。 どのデータ型が入力に使用されるかにかかわらず、返される値はDateオブジェクトになります。フィールド必須/オプション説明- startDate- 必須 - unit- 必須 - startDateから差し引かれた時間の- amountを測定するために使用される- unitです。- unitは、次のいずれかの文字列に変換される式です。- year
- quarter
- week
- month
- day
- hour
- minute
- second
- millisecond
 - amount- 必須 - startDateから差し引かれた- unitsの数。- amountは、integer または long に変換される式です。- amountは、その値が精度を失うことなく long に変換できる場合は、integer decimal または double に変換することもできます。- timezone- 任意 - 操作を実行するタイムゾーン。 - <tzExpression>は、有効な式であり、Olson タイムゾーン識別子 または UTC オフセット のいずれかとして形式された文字列に変換される必要があります。- timezoneが指定されていない場合、結果は- UTCに表示されます。形式例- Olson タイムゾーン識別子 - "America/New_York" - "Europe/London" - "GMT" - UTC オフセット - +/-[hh]:[mm], e.g. "+04:45" - +/-[hh][mm], e.g. "-0530" - +/-[hh], e.g. "+03" - 式とタイプの詳細については、「式とBSON types 」を参照してください。 
動作
時間測定
MongoDB は一般的なデータベースの使用法に従い、UTC の時間で動作します。dateSubtract式は常に UTC のstartDateを受け取り、UTC で結果を返します。 timezoneが指定されている場合は、指定されたtimezoneを使用して計算が行われます。 計算に夏時間 (DST) が含まれる場合、タイムゾーンは特に重要です。
unit が month またはそれより大きい場合、操作は月の最終日を考慮して調整されます。たとえば、3 月の最終日に month を 1 つ引くと、「月末日」の調整が行われます。
{    $dateSubtract:       {          startDate: ISODate("2021-03-31T12:10:05Z"),          unit: "month",          amount: 1       } } 
2 月は 3 月よりも日数が少ないため、返される日付 ISODate("2021-02-28T12:10:05Z") は 31 日ではなく 28 日であることがわかります。
タイムゾーン
<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.connectionTime.insertMany(   [      {         custId: 457,         login: ISODate("2020-12-25T19:04:00"),         logout: ISODate("2020-12-28T09:04:00")      },      {         custId: 457,         login: ISODate("2021-01-27T05:12:00"),         logout: ISODate("2021-01-28T13:05:00")      },      {         custId: 458,         login: ISODate("2021-01-22T06:27:00"),         logout: ISODate("2021-01-31T11:00:00")      },      {         custId: 459,         login: ISODate("2021-02-14T20:14:00"),         logout: ISODate("2021-02-17T16:05:00")      },      {         custId: 460,         login: ISODate("2021-02-26T02:44:00"),         logout: ISODate("2021-02-18T14:13:00")         }   ] ) 
サービスの問題により、2021 年 1 月の各ログアウト時間から 3 時間を差し引く必要があります。集計パイプラインで $dateSubtract を使用して、logoutTime から減算できます。
db.connectionTime.aggregate(    [       {          $match:             {                $expr:                   {                      $eq:                         [                             { $year: "$logout" },                               2021                         ]                   },                $expr:                   {                      $eq:                         [                             { $month: "$logout" },                               1                         ]                    }              }        },        {           $project:              {                 logoutTime:                    {                       $dateSubtract:                          {                             startDate: "$logout",                             unit: "hour",                             amount: 3                          }                    }               }         },         {            $merge: "connectionTime"         }    ] ) 
$match ステージでは同様の比較が 2 回行われます。まず、$year 演算子と $month 演算子は、logoutTime Date オブジェクトからそれぞれ年と月を抽出します。次に、月と年が選択対象と一致するかどうかをチェックします。"January" は "1" としてエンコードされるため、$expr は、年と月が "2021" と "1" に等しい($eq)場合、true です。
$project ステージでは、$dateSubtract を使用して、選択された各ドキュメントの logoutTime から 3 時間を差し引きます。
最後に、$merge ステージでコレクションが更新され、変更されたドキュメントの新しい logoutTime が書き込まれます。
注意
$out とは異なり、$merge ステージでは一致したドキュメントのみが更新され、コレクションの残りの部分は保持されます。詳細については、「$out と $merge の比較」を参照してください。
結果のドキュメントは次のようになります。
{  "_id" : ObjectId("603dd94b044b995ad331c0b5"),  "custId" : 457,  "login" : ISODate("2020-12-25T19:04:00Z"),  "logout" : ISODate("2020-12-28T09:04:00Z") } {  "_id" : ObjectId("603dd94b044b995ad331c0b6"),  "custId" : 457,  "login" : ISODate("2021-01-27T05:12:00Z"),  "logout" : ISODate("2021-01-28T13:05:00Z"),  "logoutTime" : ISODate("2021-01-28T10:05:00Z") } {  "_id" : ObjectId("603dd94b044b995ad331c0b7"),  "custId" : 458,  "login" : ISODate("2021-01-22T06:27:00Z"),  "logout" : ISODate("2021-01-31T11:00:00Z"),  "logoutTime" : ISODate("2021-01-31T08:00:00Z") } {  "_id" : ObjectId("603dd94b044b995ad331c0b8"),  "custId" : 459,  "login" : ISODate("2021-02-14T20:14:00Z"),  "logout" : ISODate("2021-02-17T16:05:00Z") } {  "_id" : ObjectId("603dd94b044b995ad331c0b9"),  "custId" : 460,  "login" : ISODate("2021-02-26T02:44:00Z"),  "logout" : ISODate("2021-02-18T14:13:00Z") } 
相対日付でフィルタリングする
過去 1 週間にサービスを利用したクライアントにアンケートを送ろうとしています。$dateSubtract 式は、クエリが実行される時間を基準とした範囲フィルターを作成できます。
db.connectionTime.aggregate(    [       {          $match:             {                $expr:                   {                      $gt:                         [                            "$logoutTime",                             {                                $dateSubtract:                                   {                                      startDate: "$$NOW",                                      unit: "week",                                      amount: 1                                   }                             }                         ]                   }              }       },       {          $project:             {                _id: 0,                custId: 1,                loggedOut:                   {                      $dateToString:                         {                            format: "%Y-%m-%d",                            date: "$logoutTime"                         }                   }             }       }    ] ) 
組み込み集計変数 $$NOW は、現在の日時を ISODate 形式で返します。$match ステージでは、$$NOW の値を使用して今日の日付を取得します。次に、比較式($expr)は、「より大きい」($gt)と $dateSubtract を使用してコレクションをフィルタリングし、過去 1 週間に logoutTime があるドキュメントと一致させます。
$project ステージでは、$dateToString 式を使用して日付をより読みやすい形式に変換します。変換を行わない場合、MongoDB は日付を ISODate 形式で返します。出力には、過去 1 週間に 2 人のカスタマーがログアウトしたことが示されています。
{ "custId" : 459, "loggedOut" : "2021-02-17" } { "custId" : 460, "loggedOut" : "2021-02-18" } 
夏時間に合わせて調整する
すべての日付は、内部的には UTC 時間でストアされます。timezone が指定されている場合、$dateSubtract はローカル タイムを使用して計算を実行します。結果は UTC で表示されます。
複数のタイムゾーンのカスタマーがいて、day や hour で請求した場合、夏時間が請求期間にどのような影響を与えるかを確認したい場合があります。
この接続時間のコレクションを作成します。
db.billing.insertMany(    [       {          location: "America/New_York",          login: ISODate("2021-03-14T10:00:00-0500"),          logout: ISODate("2021-03-14T18:00:00-0500")       },       {          location: "America/Mexico_City",          login: ISODate("2021-03-14T10:00:00-00:00"),          logout: ISODate("2021-03-15T08: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:                               {                                  $dateSubtract:                                     {                                        startDate: "$login",                                        unit: "day",                                        amount: 1,                                        timezone: "$location"                                     }                               }                         }                   },                hours:                   {                      $dateToString:                         {                            format: "%Y-%m-%d %H:%M",                            date:                               {                                  $dateSubtract:                                  {                                     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:                               {                                  $dateSubtract:                                     {                                        startDate: "$login",                                        unit: "day",                                        amount: 1,                                        timezone: "$location"                                     }                               },                            timezone: "$location"                         }                   },                hoursTZInfo:                   {                      $dateToString:                         {                            format: "%Y-%m-%d %H:%M",                            date:                               {                                  $dateSubtract:                                     {                                        startDate: "$login",                                        unit: "hour",                                        amount: 24,                                        timezone: "$location"                                     }                               },                            timezone: "$location"                         }                   },             }       }    ] ).pretty() 
$dateToString 式は、読みやすいように出力を再フォーマットします。 結果の概要は次のとおりです。
| フィールド | New York | メキシコシティ | 
|---|---|---|
| 始める | 2021-03-14 15:00 | 2021-03-14 15:00 | 
| スタート、タイムゾーン情報 | 2021-03-14 11:00 | 2021-03-14 04:00 | 
| 1 日 | 2021-03-13 16:00 | 2021-03-13 15:00 | 
| 1 日、タイムゾーン情報 | 2021-03-13 11:00 | 2021-03-13 09:00 | 
| 24 時間 | 2021-03-13 15:00 | 2021-03-13 15:00 | 
| 24 時間、タイムゾーン情報 | 2021-03-13 10:00 | 2021-03-13 09:00 | 
このチャートには、いくつかの重要なポイントがあります。
- 書式設定されていない日付は UTC で返されます。ニューヨークの - $loginは UTC -5 ですが、- start行、- days行、および- hours行には時刻が UTC で表示されます。
- 3 月 14 日はニューヨークでは夏時間の開始日ですが、メキシコでは違います。計算された時間は、ロケーションが DST に切り替わり、ある - dayから次の日に移るときに調整されます。
- DST は、 - hourではなく、- dayの長さを変更します。- hoursでは、DST の変更はありません。DST の調整は、測定- unitが- day以上で、計算が指定された- timezoneで時差が生じる場合にのみ行われます。