イベント管理機能をデプロイした直後、イベントが1件も返ってこなかった。
管理画面でイベントを登録した。スプレッドシートには確かに行が入っている。しかし予約フォームのAPIを叩くと {"events": []} が返ってくる。0件だ。
フィルタを疑った
getEvents() の中でイベントをフィルタしている箇所があった。
const todayKey = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd');
if (dateStr < todayKey) continue;
過去のイベントは表示しない、という処理だ。文字列比較で日付を比べている。
todayKey は "2026/06/10" のような形式になる。スラッシュ区切りだ。
では dateStr は何か。
問題の根は入力フォームにあった
管理画面のイベント作成フォームに <input type="date"> を使っていた。
HTML の date 入力が返す値は "2026-06-10" 形式だ。ハイフン区切り。
この値をそのままスプレッドシートに保存していた。
スプレッドシートから読み出した dateStr はハイフン区切り。todayKey はスラッシュ区切り。
"2026-06-10" < "2026/06/10"
これが true になる。
ASCII の問題だった
- のASCIIコードは45。/ のASCIIコードは47。
- のほうが小さい。
文字列比較は左から1文字ずつ比較する。"2026-06-10" と "2026/06/10" は5文字目が -(45)と /(47)で違う。- のほうが小さいので、ハイフン形式の日付はすべてスラッシュ形式の日付より「過去」と判定される。
つまり、どんな未来の日付を登録しても、ハイフン形式で保存されている限り todayKey より小さくなる。全件スキップされる。events: [] が返る。
保存時に正規化した
解決策は保存するときにフォーマットを統一することだ。
// adminCreateEvent
(params.date || '').replace(/-/g, '/'), // HTMLのdateInputをスラッシュ形式に統一
// adminUpdateEvent
if (params.date !== undefined) sheet.getRange(r, 4).setValue(params.date.replace(/-/g, '/'));
読み出し側でも対応した。スプレッドシートのセルがDate型として返ることがある。その場合はGASの Utilities.formatDate で変換する。
const dateStr = rows[i][3] instanceof Date
? Utilities.formatDate(rows[i][3], 'Asia/Tokyo', 'yyyy/MM/dd')
: String(rows[i][3]).replace(/-/g, '/');
管理画面でイベントを編集するとき、date inputに日付をセットし直す処理も対応が必要だった。スプレッドシートにはスラッシュ形式で入っているが、date inputはハイフン形式しか受け付けない。
document.getElementById('ev-date').value = (ev.date || '').replace(/\//g, '-');
保存するときはスラッシュ形式に変換。表示するときはハイフン形式に変換。この2方向の変換を忘れると、どちらかが壊れる。
なぜ先に気づかなかったか
予約枠シートの日付は別の経路で保存されている。管理画面から adminAddSlot を呼ぶとき、すでにスラッシュ形式に変換する処理が書いてあった。
const dateStr = params.date.replace(/-/g, '/');
既存の処理を見て、同じことをやればいいと思っていた。しかしイベント作成のコードを書くとき、この変換を入れ忘れた。
動くか動かないかという確認はした。スプレッドシートに行が入ることも確認した。しかしフィルタを通過するかどうかまでは確認していなかった。
Codexが指摘する前に、動作確認の段階で気づきたかった。
次回は、LIFFが認証後にURLを書き換えてしまう問題の話を書く。
シンプルシステム株式会社 代表 伊藤勝彦