マイコン温度通知システムの製作11 超過温度のLINE通知4 Timestampオブジェクトエラー

データがTimestampオブジェクトのはずが、そうなっていない

データベースに格納されているTimestampオブジェクトを扱うと、データ形式がTimestampでないようでエラーが出ていました。

const latestRecord = latestRecordSnapshot.docs[0].data();
    console.log("latestRecord:", latestRecord);
    if (latestRecord.timestamp &&
      typeof latestRecord.timestamp.toDate === "function") {
      // FirestoreのTimestampをJavaScriptのDateに変換
      const latestTimestamp = latestRecord.timestamp.toDate();

またデータベースの格納を修正したらそこでもエラーが出るようになってしまいました。

・コード

// FirestoreのTimestampオブジェクトを使用して現在時刻を取得
    const timestamp = admin.firestore.Timestamp.now();

    // 温度とMACアドレスをFirestoreデータベースに保存
    const writeResult = await admin.firestore()
        .collection("temperatureData")
        .add({
          temperature: temperature,
          macAddress: macAddress,
          timestamp: timestamp,
          alertFlag: alertFlag,
        });

・コマンドで上記を実施した結果

$ curl -X POST http://127.0.0.1:5001/temperature-measurement-b3fcd/us-central1/XXX \
-H "Content-Type: application/json" \
-d '{"temperature": "27.5", "macAddress": "YYY"}'
{"error":"Cannot read properties of undefined (reading 'now')"}%

上についてはtimestampが定義されていないため起きたエラーになります。修正したものは以下になります。

// FirestoreのTimestampを直接インポート
const {Timestamp} = require("firebase-admin/firestore");

// Firebaseアプリがまだ初期化されていない場合のみ初期化を実行
if (admin.apps.length === 0) {
  admin.initializeApp();
}

// FirestoreのTimestampオブジェクトを使用して現在時刻を取得
const timestamp = Timestamp.now();

Timestampを宣言することによりエラーになることを回避できました。

タイムゾーンの指定をしておらず、作成したオブジェクトの日付が意図しない値になる

以下のようなコードを作り、当日の開始時刻、終了時刻、翌日の開始時刻と同じ時間のオブジェクトを作成しました。

// タイムゾーンを指定して日時を生成
  const now = new Date();
  const currentDateTime = new Date(now.
      toLocaleString("en-US", {timeZone: "Asia/Tokyo"}));

  // 開始時刻と終了時刻を指定したタイムゾーンで生成
  const startTime = new Date(now.getFullYear(),
      now.getMonth(), now.getDate(), startHour, startMinute);
  const endTime = new Date(now.getFullYear(),
      now.getMonth(), now.getDate(), endHour, endMinute);

  // 翌日の日付に設定
  const tomorrow = new Date(now);
  tomorrow.setDate(now.getDate() + 1);
  // 開始時刻と終了時刻を指定したタイムゾーンで生成
  const startTimeTomorrow = new Date(tomorrow.getFullYear(),
      tomorrow.getMonth(), tomorrow.getDate(), startHour, startMinute);

しかし、結果は以下のような意図しない動作になりました。

currentDateTime:正確
startTime:意図はプログラム動作中の同日だが、1日前になっている。
endTime:意図はプログラム動作中の同日だが、1日前になっている。
startTimeTomorrow:意図はプログラム動作中の翌日だが、動作中の日付になっている。

原因は、それぞれのオブジェクト作成時にタイムゾーンの指定がなされておらず、UTCで参照してしまい、意図するGMT+0000(日本時間)でなくなり、日付が違っていたためでした。

以下のように修正することで解決しました。

// 開始時刻と終了時刻を指定したタイムゾーンで生成
  const startTime = new Date(now.toLocaleString("en-US",
      {timeZone: "Asia/Tokyo"})).setHours(startHour, startMinute);
  const endTime = new Date(now.toLocaleString("en-US",
      {timeZone: "Asia/Tokyo"})).setHours(endHour, endMinute);
  // 翌日の日付に設定
  const tomorrow = new Date(now);
  tomorrow.setDate(now.getDate() + 1);
  // 開始時刻と終了時刻を指定したタイムゾーンで生成
  const startTimeTomorrow = new Date(tomorrow.toLocaleString("en-US",
      {timeZone: "Asia/Tokyo"})).setHours(startHour, startMinute);
タイトルとURLをコピーしました