mcpField
T
time-slot-generator

time-slot-generator

github.com/timerise-ai開発016 回インストール3 日前に更新
リポジトリ

time-slot-generator について

スケジュール戦略から予約可能な時間枠を生成する TypeScript スキルです。時間枠ロジックを独自サービスに組み込むチーム向けで、決定的な ID、タイムゾーン処理、一覧表示と予約で共通の空き状況確認を重視します。

主な機能

  1. 01ルールに基づく時間枠生成
  2. 02決定的な時間枠 ID
  3. 03タイムゾーンと DST の処理
  4. 04予約やブロックを反映した空き状況
  5. 05予約時の定員再確認

活用シーン

  1. 01定期または単発の予約枠を作成
  2. 02定員を反映した空き状況を表示
  3. 03同時予約による定員超過を防止
  4. 04時間枠ロジックのタイムゾーン問題を修正

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/timerise-ai/time-slot-generator --skill time-slot-generator

インストール後、Claude Code で/time-slot-generatorを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

CHANGELOG.md
.gitattributes
CLAUDE.md
LICENSE
README.md
.github/workflows/
agent-eval.yml
evals/
prompts.md
references/
firestore-backend.md
adaptation.md
availability.md
generators.md
provenance.md
timezones.md
nextjs-routes.md
strategy-model.md
testing.md
supabase-backend.md

詳細

時間枠ジェネレーター

時間枠は保存されません。戦略を保存し、読み出すたびにそこから時間枠を再生成します。予約時には、決定論的な ID を使って該当する時間枠を再特定します。このスキルの仕組みはすべて、この考え方に基づいています。ジェネレーターは戦略、現在時刻、表示範囲を入力とする純粋関数であり、その出力は表示範囲、サーバーのタイムゾーン、年の何日目かに左右されません。そのため、ゲストが「予約」を押したとき、画面に表示されていた時間枠は引き続き存在します。

使用する場面

  • ルールから予約可能な時間枠を生成する場合:「月曜日から金曜日まで、09:00~17:00、30 分ごと」、「毎月第 1 金曜日と最終金曜日の18:00~20:00」、「終日、週末のみ」、「特定の土曜日、10:00~14:00」。
  • 空き状況を表示する場合:時間枠ごとの定員から、予約、予約不可時間、ホストの他の予定、共有ルームや機器、営業時間外を差し引きます。
  • 同時リクエスト時にも定員を再確認したうえで、ID によって時間枠を予約する場合。
  • タイムゾーンに関するバグのある時間枠コードを修正する場合や、壁時計の時刻を UTC として保存する方式から移行する場合。

使用しない場面

  • 予約画面やキオスクのフロー:このスキルが生成する時間枠を利用する booking-kiosk。
  • カレンダー同期とメール機能を備えた、ホストごとの公開スケジュールリンク:calendar-scheduling-links。
  • カレンダーの繰り返し予定(RRULE、iCalendar、Google または Outlook のイベントシリーズ):rrule またはプロバイダーの API。戦略が表すのは予約可能な定員であり、イベントではありません。
  • 支払い、デポジット、請求書:bookable-events、invoicing。

アーキテクチャ

 strategies (DB) --normalizeStrategy--> SlotStrategy[] --generateSlots(now, viewport)--> GeneratedSlot[]
                                                                                              |
 bookings, busy blocks, host bookings, resources, working hours --SlotStore--> buildAvailability
                                                                                              |
   GET /api/slots       listServiceSlots: toSlotOutput (UTC + local offset) <-----------------+
   POST /api/bookings   prepareBookingSlots(ids): one generation, then lookups <--------------+
                          |
                          v
                        book_slots / assertCapacityInTransaction: seats re-counted in the write

エンジン(lib/slots/)は Next.js をインポートしない、プレーンな TypeScript です。フレームワークに触れるのはルートのファイルだけで、データベースに触れるのは SlotStore だけです。

適応に関する契約

adaptation.md に契約全体、名称の対応表、作業順序、必須事項が記載されています。

接続箇所このスキルが提供するものホストが用意するもの
ドメイン用語Service、Strategy、Booking、Host、Location、Resource、BusyBlock、projectホスト側の名称
テナントと認証保存済みサービスから読み取る projectId、マーク付きのガード用スロット書き込み前のガード
データアクセスFirestore と Supabase 向けの SlotStoreプロジェクトとスキーマ
ルートSupabase 向けの一覧取得および予約ルートハンドラーURL 方式
時間枠 IDnode:crypto による md5Edge ランタイム向けの純粋な md5 実装
文字列と UI画面はなく、エラーコードのみi18n と時間枠ピッカー

重要事項

  1. 時点は UTC で保存し、壁時計の時刻を記述し、タイムゾーンを固定します。 start.time: "09:00" は、作成時に固定された戦略の timeZone における09:00を意味します。そのため、後からプロジェクトのタイムゾーンを変更しても、既存の時間枠は移動しません。
  2. ローカルの暦日を順に処理し、決して +24h を使わないでください。 DST の日は23時間または25時間です。春の夏時間への切り替え日の前夜、23:30に24時間を足すと、ローカル時刻では2日後になります。
  3. 早期終了する前に、時系列順に出力してください。 ジェネレーターはカットオフを過ぎた最初の時間枠で終了するため、曜日ごとに候補を生成すると、週表示が最初の平日で終わってしまいます。
  4. 上限は表示範囲ではなく、戦略の開始時点から数えます。 そうしないと、「最初の10枠」はクライアントがどの週を要求するかによって変わり、ある表示では見える時間枠が予約できなくなります。
  5. サーバーのタイムゾーンは関係ありません。 new Date('2026-03-29T09:00') はプロセスのタイムゾーンで解析されます。また、時刻をずらした Date に対する getUTCDay() が正しいのは、プロセスが UTC の場合だけです。そのため、エンジンでは Intl ヘルパーを使います。
  6. 予約ごとに一度だけ生成し、その後は検索します。 要求された時間枠ごとに再生成すると、予約内の時間枠数に応じて処理量が増えます。
  7. 書き込み時には生成結果が古くなっています。 2人のゲストが最後の1席を同時に見ている場合があるため、予約トランザクション内で席数を再集計します。

厳守事項

  1. スロット ID の入力を絶対に変更しないでください。 md5("<utcStartISO>;<duration>;<strategyId>") は、すべてのクライアントと予約が保持する識別情報です。入力が異なると、すべてのクライアントと予約が紐付かなくなります。
  2. 終了時刻が開始時刻より前だからといって、「夜間」と推測しないでください。 時刻の逆転は夜勤よりも入力ミスであることがはるかに多いため、夜間の時間帯には overnight: true が必要です。
  3. 期間を指定せずに生成しないでください。 maxHorizonDays と maxSlots ですべてのストラテジーに上限を設けてください。そうしないと、終了条件のないストラテジーは 2038 年まで生成し続けます。
  4. 一覧表示のときだけ空き状況でフィルタリングしないでください。 一覧表示と予約処理は同じ buildAvailability マップを参照するため、一覧に表示されない ID は予約できません。
  5. ホストがこのサービスを予約した分を、ホストの予約済み時間として数えないでください。 その予約はすでに BOOKING として座席数から差し引かれています。さらに予約済みとしてブロックすると、まだ空きがあるスロットが非表示になります。

クイックスタート

  1. ホストを確認し、接合部の契約と名前変更テーブルを記入します。adaptation.md を参照してください。
  2. 型とバリデーションをコピーします。strategy-model.md を参照してください。
  3. 時刻ヘルパー、期間、正規化処理をコピーします。timezones.md を参照してください。
  4. スロットの識別方法とジェネレーターをコピーします。generators.md を参照してください。
  5. 空き状況の処理とサービスのエントリーポイントをコピーします。availability.md を参照してください。
  6. テストスイートをコピーし、4 つの TZ 値で npm test に接続して実行します。 testing.md を参照してください。
  7. バックエンドを選択します。supabase-backend.md または firestore-backend.md を参照してください。
  8. ルートハンドラーから提供します。nextjs-routes.md を参照してください。
  9. 既存のエンジンを再構築しますか?provenance.md に台帳と修正の順序が、 testing.md に差分チェックが記載されています。

引き継ぎ時には、適用するスキーマまたはインデックス、2 つの環境変数、ホストのガードを配置する場所を伝えてください。

リファレンスディレクトリ

シナリオトリガーキーワードリファレンス
接合部、名前変更、作業順序adapt, host, rename, tenant, auth guard, non-negotiablesadaptation.md
ストラテジーの形式、フィールド、バリデーションRANGE, PERIODICITY, ONCE, DAY_RANGE, tendency, timeOffset, slotsLimit, overnight, strategy-bounds-invalidstrategy-model.md
タイムゾーンと DSTIANA, wall clock, UTC, DST gap, overlap, fromZonedTime, offset, storageVersion, legacytimezones.md
スロットの生成generateSlots, horizon, maxSlots, truncated, slot ID, md5, chronological, viewportgenerators.md
まだ空いている枠availability, seats, BOOKING, BLOCK, working hours, resource, capacity, overbooking, prepareBookingSlotsavailability.md
Supabase と Postgrestimestamptz, jsonb, RLS, with check, gin index, book_slots, advisory locksupabase-backend.md
Firestorefirebase-admin, Timestamp, composite index, array-contains-any, onSnapshot, runTransactionfirestore-backend.md
ルートハンドラーapp/api/slots, app/api/bookings, route.ts, Node.js runtime, 409, SUPABASE_SERVICE_ROLE_KEYnextjs-routes.md
動作の検証node:test, vitest, npm test, TZ=, DST regression, Lord Howe, Auckland, differential checktesting.md
この設計を採用した理由provenance, audit, kept deliberately, fix orderprovenance.md

兄弟スキルを一覧できる Timerise Skills インデックスの一部です。

コメント