前日リマインドメッセージに「Sat Dec 30 1899」という文字列が入っていた。
「明日10:00のご予約のリマインドです」と送るはずが、「明日Sat Dec 30 1899 10:00:00 GMT+0900 (Japan Standard Time)のご予約のリマインドです」という文字列が届いていた。
スプレッドシートの時刻セルは何を返すか
GASでスプレッドシートのシートを getValues() で読み込むと、各セルの値がJavaScriptの型で返ってくる。
数値は数値、文字列は文字列、日付セルはDateオブジェクト、時刻セルもDateオブジェクトだ。
時刻セルの扱いがやっかいだ。スプレッドシートの「時刻」は、内部ではExcelと同じ起源を持つシリアル値で管理されている。1900年1月1日を1として、1日を1.0として増加する小数値だ。「10:00」は0.416666...に相当する。
GASがこれをDateオブジェクトに変換するとき、1899年12月30日の午前0時を起点として計算する。「10:00」は「1899年12月30日 10:00:00」になる。
テンプレートリテラルで ${row[5]} と書くと、Dateオブジェクトの toString() が呼ばれる。Sat Dec 30 1899 10:00:00 GMT+0900 (Japan Standard Time) という文字列が展開される。
時刻のフォーマット関数を使う
コードには fmtTime() という関数がすでに実装されていた。
function fmtTime(d) {
const hours = d.getHours().toString().padStart(2, '0');
const mins = d.getMinutes().toString().padStart(2, '0');
return hours + ':' + mins;
}
問題の箇所でこの関数を通さずに直接展開していた。
// 修正前
const time = row[5];
const msg = `明日${time}のご予約`;
// 修正後
const time = fmtTime(row[5]);
const msg = `明日${time}のご予約`;
fmtTime(row[5]) は「10:00」を返す。それ以外の情報はいらない。
関数があるのに使われていなかった
fmtTime() は別の箇所では正しく使われていた。リマインド処理を書いたときに、他の箇所と統一しないまま直接展開してしまっていた。
コードベースに「使うべき関数」があっても、書いた人間が見落とすことはある。1899年という異常な値がメッセージに入って初めて発見できた。
正常に見える出力でも、中身が間違っている場合がある。リマインドのように定期実行する処理は、一度実際のメッセージがどう届くかを確認する必要があった。
修正後の確認方法
スプレッドシートに近い日時のテスト予約を追加し、リマインド処理を手動で実行した。GASの sendReminders() を直接呼び出してログを確認した。
「10:00」という形式で出力されていることを確認してから、本番の予約スプレッドシートに戻した。
*シンプルシステム株式会社 代表 伊藤勝彦*