
SLAが土日を飛ばす理由:営業時間(cmn_schedule)
ServiceNow で SLA の「あと◯時間で違反」を確認していると、その時間が土日や夜間を飛ばして数えられていることに気づきます。あの「平日 8:00〜17:00 だけ時計が進む」挙動を支えているのが、スケジュール(営業時間)の仕組みです。Incident や SLA のフォームを眺めているだけだと、この営業時間がどのテーブルに、どう積み上がっているのかは見えてきません。
この記事では、スケジュールを機能論だけで説明しません。起点にするのは、実際の cmn_schedule(Schedule)と cmn_schedule_span(Schedule Entry)という2つのテーブルです。この2つがどう結びつくのかを、「スケジュールの定義(カレンダーの箱)」と「期間/繰り返しの1本1本(営業時間の中身)」という切り口で見ます。type で用途がどう分かれるか、タイムゾーンがどう効くか、祝日がどう除外されるかも扱います。数値はすべて PDI(Zurich)の OOTB で確認した実測値です。
この記事は、ServiceNow の Incident や SLA は触ったことがあるが、その土台にある営業時間カレンダーのテーブル構造をこれから理解したい人を想定しています。管理者・開発者が実機で見るべきポイントは、2テーブルの役割分担と主要フィールドです。そこに type・繰り返し・タイムゾーンを重ねて確認します。
この記事で分かること
スケジュールの「定義」は cmn_schedule、「期間/繰り返し」は cmn_schedule_span に分かれて保存されること。
cmn_schedule は business_calendar を継承した設定メタデータで、タイムゾーンは親テーブル由来であること。
cmn_schedule.type で営業時間・オンコール・メンテ窓などに用途が分かれること(今回の PDI では9分類)。
cmn_schedule_span の repeat_type(繰り返し)と type=exclude(除外)で、平日 8-5 や祝日除外が表現されること。
このスケジュールが SLA の稼働時間(business 経過時間)計算の土台になること。
実機で確認するときに見るべき一覧URL。
この記事の内容は ServiceNow の PDI(Personal Developer Instance)Zurich(ズーリッヒ)リリースの OOTB(初期設定)で確認した個人メモです。本番環境やカスタマイズ済み環境では、スケジュール定義・フィールド・件数の内容が異なる場合があります。
スケジュール(営業時間)とは
ServiceNow のスケジュールとは、「いつが稼働時間で、いつがそうでないか」をカレンダーとして定義する仕組みです。定義したカレンダーは、SLA の経過時間計算や通知のタイミング、メンテナンス窓などから参照されます。SLA の「あと◯時間」が土日を飛ばして数えられるのも、このスケジュールが「平日だけ稼働」と教えているからです。
スケジュールも「定義」と「中身」の2枚に分かれています。「8-5 weekdays」のようなカレンダーの箱が cmn_schedule(Schedule) です。その中の「平日 8:00〜17:00」「この祝日は除外」といった期間/繰り返しの1本1本が cmn_schedule_span(Schedule Entry)にあたります。今回確認した PDI(Zurich / OOTB)では、cmn_schedule が 94 件、cmn_schedule_span(期間エントリ)が 120 件ありました。
スケジュールまわりのテーブル関係(定義と期間)
スケジュールに関係するテーブルは、「定義(箱)」「期間(中身)」「利用側(SLA など)」の3つに分けて見ると整理できます。

今回確認した PDI(Zurich / OOTB)では、それぞれ次の構造でした。
cmn_schedule(Schedule) … super_class は business_calendar(Business Calendar)です。その先は sys_metadata(Application File)につながります。つまり設定メタデータとして管理され、Update Set で運ばれます。固有フィールドは 6 と少なく、name / type / document などを持ちます。
cmn_schedule_span(Schedule Entry) … super_class は business_calendar_span(ルート基底)でした。固有フィールドは 22 です。schedule(→ cmn_schedule)で「どのスケジュールに属する期間か」を参照で持ちます。
つまり、定義(cmn_schedule)は1枚のカレンダーの箱、期間(cmn_schedule_span)はその中に何本も入る稼働/除外の帯という役割分担です。1つのスケジュールに複数の span がぶら下がる構造が、営業時間とその例外(祝日など)を表現する土台になっています。
テーブル定義は、次のURLで確認できます(先頭の <YourInstance> は自分のインスタンスに置き換えてください)。
https://<YourInstance>/sys_db_object_list.do?sysparm_query=name=cmn_schedule^ORname=cmn_schedule_span継承構造とタイムゾーンの出どころ
スケジュールのフォームを開くと Time zone(タイムゾーン) という項目が出ますが、これは少し注意が必要です。

今回の PDI(Zurich / OOTB)で確認したところ、time_zone は cmn_schedule 自身の固有フィールドではありませんでした。実体は親の business_calendar 側のフィールドです。継承によって cmn_schedule のフォームに表示されているだけで、label(表示ラベル)や parent(親スケジュール)も同じく親側です。
実機でスケジュールフォームを開くと、この構造がそのまま見えます。

注目したいのは Time zone が「-- Floating --」(空)になっている点です。今回の PDI では、cmn_schedule 94 件のうち 16 件が time_zone 空(Floating)でした。Floating は「評価する人のタイムゾーンで判定する」という意味です。SLA で使う「8-5 weekdays」のような汎用カレンダーは、この Floating になっていました。一方、オンコール系のスケジュール(後述)は US/Pacific・Europe/London・Asia/Kolkata などの具体的なタイムゾーンを持っていました。
https://<YourInstance>/cmn_schedule_list.do公式の Domain support for schedules(Zurich) に、スケジュールがどのテーブル(cmn_schedule / cmn_schedule_span)で構成され、タイムゾーンや Floating がどう効くかが説明されています。
cmn_schedule の type(用途の分かれ方)
スケジュールは「営業時間」だけではありません。type フィールドで、オンコールやメンテナンス窓など用途が分かれます。

今回の PDI(Zurich / OOTB)では、cmn_schedule.type に sys_choice 定義は無く、データ上の値で用途が分かれていました。94 件の内訳は次のとおりです。

実機の一覧を type でグルーピングすると、この分布がそのまま見えます。

(空)6 件 … 素の営業時間カレンダー。8-5 weekdays や 24 x 7 系など、SLA の稼働時間計算で使う「素直なカレンダー」はここに入ります。
rotation 59 / roster 12 件 … オンコールの輪番・当番表。group / user を指して「誰がいつ当番か」を表します。
maintenance 7 / blackout 2 件 … メンテナンス窓・変更凍結(ブラックアウト)窓。Change 管理の制御に使われます。
create_new_roster 5 / application 1 / network 1 / server 1 件 … その他の用途別。
同じ cmn_schedule テーブルでも、type によって「営業時間」「オンコール」「メンテ窓」と役割がまったく違います。スケジュールを調べるときは、まず type を見て「これは何のためのカレンダーか」を確かめる必要があります。
https://<YourInstance>/cmn_schedule_list.do?sysparm_query=GROUPBYtypecmn_schedule_span の主なフィールド
期間エントリ(cmn_schedule_span)は、「いつからいつまで・どう繰り返すか」を表す項目を持ちます。役割で分けると、参照(親スケジュール)・時間(開始/終了/終日)・繰り返し(種別/間隔/曜日)・種別(除外など)に整理できます。

主なフィールドの代表は次のとおりです。ラベルは画面上の表示名で、実機どおり記載します。
schedule(Schedule → cmn_schedule) … どのスケジュールに属する期間か。
start_date_time / end_date_time(Start/End date time) … 期間の開始・終了日時。
all_day(All day) … 終日フラグ(既定 false)。祝日などは true。
repeat_type(Repeats) … 繰り返し種別(後述)。
days_of_week(Repeat on) … 曜日指定。Days of Week という専用型で、sys_choice ではありません。
type(Type) … 期間の種別。営業時間カレンダーでは exclude(Excluded)が効いてきます(後述)。
float_day / float_week … 「第N週の何曜日」のような相対指定(例:第3 Saturday、第4 Thursday の祝日)。
実機の辞書一覧を見ると、これらのフィールドと型がそのまま確認できます。

全フィールドは、次のURLで一覧できます。
https://<YourInstance>/sys_dictionary_list.do?sysparm_query=name=cmn_schedule_span^elementISNOTEMPTY繰り返し(repeat_type)と期間の作り方
営業時間の「中身」は、期間エントリの repeat_type(繰り返し)で表されます。
今回確認した PDI(Zurich / OOTB)の cmn_schedule_span.repeat_type は 9値でした。値は Does not repeat / daily / weekdays / weekends / weekMWF です。続けて weekTT / weekly / monthly / yearly / specific が並びます。実データ 120 件の分布は daily 66 / yearly 20 / weekly 16 / weekdays 11 / weekends 2 / monthly 1 が中心です。
代表的な「8-5 weekdays」スケジュールの期間エントリを実機で開くと、繰り返しの作り方が分かります。

このエントリは、When(08:00〜17:00)+ Repeats(Every Weekday) の組み合わせで「平日 8:00〜17:00」を1本で表現しています。これが今回の PDI では 8-5 weekdays スケジュールに紐づく唯一の span でした。24 x 7 スケジュールなら、repeat_type=daily / all_day=true / 00:00〜23:59:59 の span 1本で「毎日24時間」を表します。
営業時間は「開始/終了時刻」と「繰り返し方」の組み合わせです。平日 8-5 も、24x7 も、土日だけの当番も、この2つの軸で表現されています。
https://<YourInstance>/cmn_schedule_span_list.do?sysparm_query=schedule.name=8-5 weekdays公式の Schedules within SLA(Zurich) に、SLA がスケジュールを使って稼働時間(business 時間)をどう累積するかが説明されています。
祝日の除外と Child Schedule(営業時間の組み立て)
「平日 8-5」だけでは祝日まで稼働扱いになってしまいます。ServiceNow は type=exclude の期間 と Child Schedule(子スケジュール) を組み合わせて、祝日を稼働時間から除きます。

今回の PDI(Zurich / OOTB)では、8-5 weekdays excluding holidays を確認しました。稼働の span(Monday-Friday 8-5)に加えて、祝日カレンダーを Child Schedule として含めることで祝日を除外する構造でした。祝日エントリそのものは、次のように作られていました。
repeat_type = yearly(毎年)。
all_day = true(終日)。
type = exclude(Excluded=除外)。
float_day / float_week … 「第N週の何曜日」(例:Thanksgiving Day = 4th Thursday)。
実機の祝日エントリ一覧を見ると、これらが並んでいます。

営業時間は「稼働の span(含める)」と「除外の span(type=exclude)」の足し引きで組み立てられます。今回の PDI では、yearly の祝日エントリ 20 件はいずれも type=exclude でした。スケジュールを読むときは、「稼働の帯」だけでなく「除外の帯」がどこから来ているか(同じスケジュールか、Child Schedule か)を確かめる必要があります。
公式の SLA duration and schedules(Zurich) に、SLA の期間(duration)とスケジュールが、稼働時間の起算にどう組み合わさるかが説明されています。
スケジュールに関わる周辺機能
スケジュールの動きも、フィールド定義だけでは決まりません。保存時の処理、繰り返しに応じた項目表示、権限など、複数の設定が組み合わさって動きます。大まかには、保存時のサーバ側処理は Business Rule、繰り返し種別に応じた項目の出し分けは UI Policy が担います。
実測の件数は次の表にまとめます。今回確認した PDI(Zurich / OOTB・active 中心・2026-06-20 確認)では、2テーブルに次のような設定が紐づいていました。

特徴的なのは、cmn_schedule_span 側に UI Policy が 8 件 あることです。期間エントリでは、繰り返しが weekly なら曜日を、yearly なら月日を出す必要があります。この出し分けのぶん、UI Policy が厚くなっています。一方、cmn_schedule 本体側は固有フィールドが 6 と少なく、設定もシンプルでした。
ここで数えているのは、スケジュール側に直接紐づく設定だけです。実際の営業時間の挙動は、SLA(contract_sla の schedule 参照)や通知、Scheduled Job など利用側の設定とも合わさって決まります。今回の PDI では、SLA 定義(contract_sla)のうち 7 件が schedule を参照していました。スケジュール単体だけを見て全体を判断しないようにします。
自分のインスタンスでは、次のURLで各一覧を開けます(先頭の <YourInstance> は置き換えてください)。
Business Rules : https://<YourInstance>/sys_script_list.do?sysparm_query=collection=cmn_schedule_span^active=true
UI Policies : https://<YourInstance>/sys_ui_policy_list.do?sysparm_query=table=cmn_schedule_span
Choices : https://<YourInstance>/sys_choice_list.do?sysparm_query=name=cmn_schedule_spanServiceNow におけるスケジュールのポイント
スケジュールは 定義(cmn_schedule)と期間(cmn_schedule_span)の2枚に分かれます。今回の PDI では定義 94 件・期間 120 件でした。
cmn_schedule は business_calendar→sys_metadata 継承の設定メタデータ(固有6)です。タイムゾーンは親 business_calendar 由来で、汎用カレンダーは「Floating」(今回 94 件中 16 件が空)でした。
cmn_schedule.type で用途が分かれます。今回の PDI では(空)6 / rotation 59 / roster 12 / maintenance 7 など 9 分類で、営業時間・オンコール・メンテ窓が同居していました。
cmn_schedule_span の repeat_type(9値)と When の組み合わせで営業時間を作ります。「平日 8-5」は weekdays × 08:00-17:00、「24x7」は daily × 終日でした。
祝日は type=exclude の期間と Child Schedule で稼働時間から除外します。今回の PDI では yearly の祝日エントリ 20 件すべてが type=exclude でした。
このスケジュールが SLA の business 経過時間(稼働時間)計算の土台です。今回の PDI では SLA 定義 7 件が schedule を参照していました。
スケジュールを調べるときは、まず3点を読みます。「この cmn_schedule は何の用途か(type)」「どの期間(span)が稼働で、どれが除外(exclude)か」「タイムゾーンは Floating か固定か」です。そのうえで、スケジュール単体ではなく、それを参照する SLA・通知・Scheduled Job をセットで見ます。
実機で気づいたこと
days_of_week(曜日指定)は sys_choice のような選択肢ではなく、Days of Week という専用型でした。最初はチェックボックスの多重選択か choice リストだろうと思って辞書を開きましたが、独自型が用意されていて、曜日という「よくある繰り返し」のために型レベルで対応している作りでした。汎用のフィールド型で済ませず専用型を起こすあたりに、繰り返しスケジュールがプラットフォームの中でも重視されている機能だと感じました。
cmn_schedule のフォームで一番目立つ Time zone は、実は cmn_schedule 自身のフィールドではなく、継承元の business_calendar 側のフィールドでした。フォーム上は同じ画面に並んでいるので、最初は気づきませんでした。cmn_schedule の辞書だけを見ていると Time zone や Parent がどこにも定義されていないように見えて戸惑います。継承先までたどる癖をつけたほうがよさそうです。
cmn_schedule は固有フィールドがわずか6個なのに対し、期間を1本ずつ記録する cmn_schedule_span は22個、UI Policy も8件ぶら下がっていました。カレンダーの「箱」自体は薄く、繰り返しの種類ごとに項目を出し分ける複雑さはすべて中身(span)側に寄せている作りです。フォームの挙動がおかしいと感じたら、まず cmn_schedule 本体ではなく Schedule Entry 側を疑うほうが早そうです。
次に読むなら
次に確認するなら、SLA 定義(contract_sla)が schedule をどう参照して business 経過時間を起算するかです。Scheduled Job がスケジュールでどう発火制御されるか、Change 管理がメンテナンス窓(maintenance / blackout)をどう使うかも同じ流れで追えます。「スケジュール側の稼働定義」と「利用側の起算ロジック」を分けて理解すると、SLA が想定外に進む/止まるといった調査が楽になります。これらは本記事の「繰り返し」「祝日の除外」で触れた仕組みの先にあたり、別記事で扱う予定です。
用語
PDI:Personal Developer Instance(無料の検証用インスタンス)。
OOTB:Out of the Box(初期設定のまま)。
Schedule(cmn_schedule):スケジュールの定義(カレンダーの箱)。type・タイムゾーンを持つ。
Schedule Entry(cmn_schedule_span):スケジュールに属する期間/繰り返しの1本。
Floating(タイムゾーン):評価する人のタイムゾーンで判定する設定。
exclude(type=exclude):その期間を稼働から除外する(祝日など)。
Child Schedule:別のスケジュールを子として包含する仕組み(祝日カレンダーの取り込みなど)。
自分の環境で確認するときのURL
自分のインスタンス名を先頭に付けると、同じ画面が開けます。
テーブル定義 : sys_db_object_list.do?sysparm_query=name=cmn_schedule^ORname=cmn_schedule_span
固有フィールド一覧 : sys_dictionary_list.do?sysparm_query=name=cmn_schedule_span^elementISNOTEMPTY
type グループ表示 : cmn_schedule_list.do?sysparm_query=GROUPBYtype
span の choices : sys_choice_list.do?sysparm_query=name=cmn_schedule_span
スケジュール一覧 : cmn_schedule_list.doテーブルの基本
cmn_schedule … Label:Schedule / Extends:business_calendar → sys_metadata / 固有フィールド 6
cmn_schedule_span … Label:Schedule Entry / Extends:business_calendar_span(ルート基底) / 固有フィールド 22
レコード件数:cmn_schedule 94 / cmn_schedule_span 120
time_zone 空(Floating)の cmn_schedule:16 件
contract_sla(SLA 定義)のうち schedule 参照:7 件
cmn_schedule.type の分布(sys_choice 無し・データ実測・全94件)
(空)6 / rotation 59 / roster 12 / maintenance 7 / create_new_roster 5 / blackout 2 / application 1 / network 1 / server 1
cmn_schedule_span.type の値(8値・value=label・sequence順)
time_off=Time off / appointment=Appointment / meeting=Meeting / call=Phone call / exclude=Excluded / on_call=On call / time_off_in_approval=Time off - In approval / time_off_rejected=Time off - rejected
cmn_schedule_span.repeat_type の値(9値・value=label・sequence順)
NULL_OVERRIDE=Does not repeat / daily=Daily / weekdays=Every Weekday (Mon-Fri) / weekends=Every Weekend (Sat, Sun) / weekMWF=Every Mon, Wed, Fri / weekTT=Every Tue, Thu / weekly=Weekly / monthly=Monthly / yearly=Yearly / specific=Specific
分布(120件):daily 66 / yearly 20 / weekly 16 / weekdays 11 / weekends 2 / monthly 1 / 他 4
代表 OOTB スケジュールと span(実測例)
8-5 weekdays … type=(空)/ time_zone=Floating / span 1件:Monday-Friday 8-5(weekdays / 08:00–17:00 / all_day=false)
24 x 7 … type=create_new_roster / span 1件:daily / 00:00–23:59:59 / all_day=true
祝日エントリ(Non-US Holidays 等)… repeat_type=yearly / all_day=true / type=exclude(Excluded)
周辺設定の件数(OOTB・active 中心)
cmn_schedule … Business Rules 6 / Client Scripts 1 / UI Policies 0 / UI Actions 2 / Notifications 0 / ACL(テーブル18=name 17+フィールド 1) / Dictionary 6(固有)
cmn_schedule_span … Business Rules 9 / UI Policies 8 / UI Actions 1 / Choices 40 / Dictionary 22(固有)
cmn_schedule_span の主な固有フィールド(検索用)
schedule, name, type, start_date_time, end_date_time, all_day, repeat_type, repeat_count, repeat_until, days_of_week, month, monthly_type, yearly_type, float_day, float_week, show_as, group, user, parent, override_start_date, notes
関連テーブル(検索用)
cmn_schedule(Schedule), cmn_schedule_span(Schedule Entry), business_calendar(親・time_zone を持つ), business_calendar_span(span の親), cmn_other_schedule(Child Schedule の包含), contract_sla(schedule を参照する SLA 定義), sys_user_group / sys_user(オンコールの対象)
検証範囲とおことわり
確認した範囲:cmn_schedule / cmn_schedule_span の階層(cmn_schedule→business_calendar→sys_metadata、cmn_schedule_span→business_calendar_span ルート基底)。固有フィールド数(schedule 6 / span 22、time_zone は親由来)、span の type(8値)・repeat_type(9値)選択肢。cmn_schedule.type のデータ分布(全94件)、span の repeat_type 分布、代表 OOTB スケジュールと span の中身。レコード件数(schedule 94 / span 120)、Floating の件数(16)、contract_sla の schedule 参照件数(7)、周辺設定件数。すべて PDI(Zurich / 2026-06-20 確認)の OOTB で取得しています。
確認していない範囲(断定しません):business 時間(稼働時間)計算エンジンの内部実装、Child Schedule の包含解決アルゴリズムの詳細。DST(夏時間)境界での丸め、rotation / roster のオンコール展開ロジック。各 Business Rule / UI Policy の内部スクリプト、SLA・通知・Change の各機能がスケジュールをどう参照するかの全経路。本番でのカスタムスケジュール。これらは別記事で扱います。
今回は PDI の OOTB(初期設定)を前提に、スケジュールの構造を確認しました。実環境では、既存のカスタマイズによってスケジュール定義・フィールド・件数が変わります。