見出し画像

#42 Google Classroom に予約投稿する際の公開誤差を調べてみた

以下の記事でネタにした「特定の日時」によるトリガーの実行タイミングを検証したネタの第二弾です。

内容としては、GAS で予約投稿してみただけで、他の GAS に関する記事とは違い、Google Classroom に関する記事と言えるかもしれません。

先の記事でも触れたように、Google が提供するヘルプ記事の中で、

予定を設定した投稿は、予定時刻より最長 5 分ほど遅れて投稿される場合があります。

https://support.google.com/edu/classroom/answer/6020270?hl=ja
生徒へのお知らせを投稿する - パソコン - Classroom ヘルプ

と説明されていますが、「実際に確認してみよう!」と考えたものの、手作業で予約投稿を作成するのは面倒なので、以下のような GAS のプログラムを作成して、大量の予約投稿を作成してみました。

作成したプログラム

function classPost() {
  const sSheet = SpreadsheetApp.getActiveSheet();     // 
  const courseId = sSheet.getRange("A1").getValue();

  // 投稿する日時は、現在時刻から設定
  let postDate = new Date();
  postDate.setHours(postDate.getHours() + 1);     // 時間を変更
  postDate.setMinutes(0);                         // 分を変更
  postDate.setSeconds(0);                         // 秒を変更   ※有効かは不明

  for (i = 0; i < 200; i++) {
    let strBody = `予約投稿 ${i + 1} 回目 ${Utilities.formatDate(postDate, 'JST', 'HH:mm:ss')} に公開設定された投稿`;

    try {
      let res = Classroom.Courses.Announcements.create(
        {
          courseId: String(courseId),
          text: strBody,
          scheduledTime: Utilities.formatDate(postDate, "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'"),
          state: "DRAFT",
          assigneeMode: "ALL_STUDENTS",
        },
        courseId);
    } catch (e) {
      console.log(e.message);
    }

    postDate.setMinutes(postDate.getMinutes() + 15);  // 15分後に設定
  }
}

このプログラムは、以下の記事で作成したプログラムから抽出したものを変更したので、ものの 5分くらいで出来上がったものです。

そんなに結果が出るまでに待ってられなかったので、15分間隔で公開されていく予約投稿を 200件作成して、その予約投稿が実際に公開されるタイミングを確認してみることにしました。
ヘルプ記事では最長で 5分程度の遅れが生じるように書かれていたので、これぐらいの間隔を確保していれば大丈夫かな、と考えたものです。サンプル数が 200件なのは何となくです… (^-^;

上記のプログラムを実行して、下図のように 200件の予約投稿が作成できました。

作成された 200件の予約投稿

この予約投稿を作成するのも関数の実行すると、後は待っていればいいのですが、1分半くらいの時間を要していました。こんなの手作業ではやってられませんね。

200件の予約投稿を作成するのも、それなりの時間が…

結果

前述のプログラムで作成した大量の予約投稿を、手作業で確認するのも大変なので、次のようなプログラムを作成しました。

function classPostList() {
  const sSheet = SpreadsheetApp.getActiveSheet();     // 
  const courseId = sSheet.getRange("A1").getValue();  // 処理対象となるクラスの ID
  let pageToken = null;
  let nowDate = new Date();                           // 現在時刻を取得
  const nSheet = SpreadsheetApp.getActive().insertSheet();  // 新しいシートを作成
  nSheet.setName(                                     // 現在時刻からシート名を設定
    Utilities.formatString("%02d%02d-%02d%02d%02d",
      nowDate.getMonth() + 1, nowDate.getDate(), 
      nowDate.getHours() + 1, nowDate.getMinutes(), nowDate.getSeconds()));

  console.log("courseId : " + courseId);
  nSheet.appendRow(["id", "text", "creationTime", "updateTime", "scheduledTime",]);

  do {                                                // プログラムのメインループ
    try {
      let res = Classroom.Courses.Announcements.list(courseId,
        {
          pageSize: 5,                                // 少しずつ読み込んで処理
          pageToken: pageToken,                       // 前回の続きから読む込む
        });

      for (let i = 0; i < res.announcements.length; i++) {
        let textBody = res.announcements[i].text.split(" ");
        if (textBody[0] == "予約投稿") {                // 今回の処理対象であるか?
          let creationTime = "";
          let updateTime = "";
          let scheduledTime = "";
          if (res.announcements[i].creationTime != undefined) {
            creationTime = Utilities.formatDate(new Date(res.announcements[i].creationTime), 'JST', 'HH:mm:ss');
          }
          if (res.announcements[i].updateTime != undefined) {
            updateTime = Utilities.formatDate(new Date(res.announcements[i].updateTime), 'JST', 'HH:mm:ss');
          }
          if (res.announcements[i].scheduledTime != undefined) {
            scheduledTime = Utilities.formatDate(new Date(res.announcements[i].scheduledTime), 'JST', 'HH:mm:ss');
          }
          else {
            scheduledTime = textBody[3];              // 投稿の本文から予定投稿の時間を取得
          }

          nSheet.appendRow([ 
            res.announcements[i].id,
            res.announcements[i].text,
            creationTime,
            updateTime,
            scheduledTime,
          ]);
        }
      }
      console.log(res.announcements.length);
      pageToken = res.nextPageToken;
    } catch (e) {
      console.log(e.message);
      pageToken = null;
    }
  } while (pageToken != null);
}

先のプログラムと同様に、指定されたクラスに投稿されている内容から、対象となる投稿を拾い出して、スプレッドシートに書き出します。

API で取得できる投稿の情報には、

  • creationTime
    このお知らせが作成されたときのタイムスタンプ。

  • updateTime
    最近行われた変更のタイムスタンプ。

  • scheduledTime
    このお知らせを公開する予定のスケジュールのタイムスタンプ

という 3つのタイムスタンプが記録されていますが、今回のような予約投稿した投稿の場合には、creationTime は「予約投稿を作成した日時」、updateTime は「予約投稿が公開された日時」、scheduledTime は未定義(GAS のプログラムで言えば undefined)となります。
予約投稿が公開される前は、scheduledTime に公開する日時が指定されていますが、公開に合わせて scheduledTime は削除されてしまうようです。予約投稿を作成する際に、投稿の本文に記載しておいた公開予定時刻を切り出して、scheduledTime に設定するようにしています。

先のプログラムで大量に作成した予約投稿を、このプログラムで処理して、スプレッドシートの関数で updateTime(実際に公開された時間)と scheduledTime(指定した公開時間)の差を求め、その平均や最大/最小を求めた結果が下図の通りです。

200回の予約投稿が公開された結果

上図の列 E までは、GAS のプログラムで取得したもので、列 F は列 D(実際に公開された時間)と列 E(公開が指定された時間)の差を求めています。列 G:H には、列 F の平均・最大・最小を表示させました。

冒頭で参照したヘルプ記事にあったように、指定された時間から 5分以内には公開されているようです。 とは言え、この時間は投稿が公開された時間なので、Google Classroom アプリや Gmail アプリなどでの通知には、もう少し時間がかかると思います。

ヘルプ記事にも記載されている通りの結果ではありますが、2022年 7月時点で上記のような方法で検証した結果です。何かの参考になれば幸いです。

この記事が気に入ったらサポートをしてみませんか?