iT邦幫忙

2022 iThome 鐵人賽

DAY 20
1
自我挑戰組

被MongoDB用Aggregate暴打的後端小菜雞日記系列 第 20

被MongoDB用Aggregate暴打的後端小菜雞日記-day20-日期時間操作符(下)

  • 分享至 

  • xImage
  •  

今天延續昨天的主題,繼續講解日期時間相關操作符,但主要會專注在時區、時間資料格式的轉換部分。

昨天我們有講到$hour這類的操作符,可以幫助我們取得特定的單位日期、時間是多少,其實他們還有第二種用法,透過帶入時區的設定,這時候就會針對不同的時區,轉換時間。

例如:現在標準時間是2022-09-16T02:00:00.000Z,如果我們想要轉換時區顯示時間,寫法是在date後面寫入要轉換的時間資料,在timezone寫入時區。

db.collection.aggregate([
  { $addFields: { date: new Date("2022-09-16T02:00:00.000Z") } },
  {
    $project: {
      new_date_1: {
        hour: { $hour: { date: "$date", timezone: "+0830" } },
        min: { $minute: { date: "$date", timezone: "+0830" } }
      },
      new_date_2: {
        hour: { $hour: { date: "$date", timezone: "Africa/Addis_Ababa" } },
        min: { $minute: { date: "$date", timezone: "Africa/Addis_Ababa" } }
      }
    }
  }
]);

// 最後回傳的結果
  {
    _id: 1,
    new_date_1: { hour: 10, min: 30 },
    new_date_2: { hour: 5, min: 0 }
  }

時區的部分也有兩種寫法,第一種比如說要轉換時區到+08:30(比標準時間多8個半小時),那就直接帶入+08:30,這個方法個人覺得是最簡單的。

第二種方法是,改用地區的名稱帶入時區,MongoDB時區名稱主要參考這裡,可以找到目前所在地區的時區,並且填入。

例如:上面的範例填入的時區是"Africa/Addis_Ababa",這地方屬於+05:00,所以在做時間的轉換,才會從00:00轉成05:00。


接下來要介紹的$toDate$dateFromString,這些操作符都可以將其他格式的資料型態,轉換成日期時間格式。

差別在於$toDate可以接受任何型態的資料,不過轉變的格式,必須按照MongoDB的規定,而$dateFromString限定只能從文字轉換成日期時間格式,但可以自行定義轉換的格式。

例如:我們現在有不同的資料,想要都轉換成date

const { ObjectId } = require("mongodb");

db.collection.aggregate([
  {
    $addFields: {
      number: 1663293600000, // Timestamp資料型態
      string: "2022-09-16",
      string_timezone: "2022-09-16 05:00:00 +0500", // 有包含時區的寫法
      objectId: ObjectId() // 建立ObjectId
    }
  },
  {
    $project: {
      number: { $toDate: "$number" },
      string: { $toDate: "$string" },
      string_timezone: { $toDate: "$string_timezone" },
      objectId: { $toDate: "$objectId" } // 也可以轉換objectId
    }
  }
]);

// 最後回傳的資料
  {
    _id: 1,
    number: 2022-09-16T02:00:00.000Z,
    string: 2022-09-16T00:00:00.000Z,
    string_timezone: 2022-09-16T00:00:00.000Z,
    objectId: 2022-09-20T13:35:13.000Z
  }

這裡比較特別的是,objectId其實也可以轉換成時間,因為它本身有一段區塊是紀錄,建立objectId當下時間的timestamp。


另外一個$dateFromString的語法使用的範例如下,其中比較特別的是,可以透過timezone來設定時區,例如:我設定時區是+08:00,而時間是2018-06-15",那轉換成標準時間,就會扣掉8小時,變成2018-06-14T16:00:00.000Z。

db.collection.aggregate([
  {
    $addFields: {
      date: "06-15-2018" // 可以自己定義時間怎麼撰寫的順序
    }
  },
  {
    $project: {
      date: {
        $dateFromString: {
          dateString: "$date", // 代入要轉換的文字
          format: "%m-%d-%Y" // 寫入轉換規則
        }
      },
      date_timezone: {
        $dateFromString: {
          dateString: "$date",
          format: "%m-%d-%Y",
          timezone: "+08:00" // 寫入時區
        }
      }
    }
  }
]);

// 最後回傳的資料
  {
    _id: 1,
    date: 2018-06-15T00:00:00.000Z,
    date_timezone: 2018-06-14T16:00:00.000Z
  }

轉換的規則,會用%Y代表年份、%m代表月份、%d代表日期,更詳細的轉換規則,請參考官方文件


最後一個要介紹的操作符是$dateFromParts,它可以藉由帶入各種參數,讓使用者自己建立一個時間資料,使用方法也很簡單,相信大家看範例也看得懂。

db.collection.aggregate([
  {
    $project: {
      date: {
        $dateFromParts: {
          "year": 2022,
          "month": 9,
          "day": 20,
          "hour": 22,
          "minute": 12,
          "second": 24,
          "millisecond": 342,
          "timezone": "+08:00"
        }
      }
    }
  }
]);
    
// 最後回傳的資料
{ _id: 1, date: 2022-09-20T14:12:24.342Z }

本篇文章同步放在我的部落格,大家有空可以進來逛逛


上一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day19-日期時間操作符(上)
下一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day21-文字操作符
系列文
被MongoDB用Aggregate暴打的後端小菜雞日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言