CALENDAR AND WALL CLOCK

月末・夏時間の前後でcron予定がずれる理由

月の最後の日は月ごとに変わり、夏時間の切替では現地時計の時刻が飛んだり重なったりします。式だけを見ず、日付とUTC instantを並べて確認しましょう。

目的と架空の入力例

架空の月次集計を月末の午前09:00に一度動かし、別の架空ジョブをニューヨーク時間の午前01:00に毎日動かすケースを確認します。実際の登録や処理は行いません。

月末日を指定する方法と、同じ壁時計時刻が変換されるUTC時刻の違いを分けて見るのが目的です。

月末はLや28〜31日だけで済むとは限らない

このツールでは 0 9 L * * のような L 指定を受け付けません。Google Cloud Schedulerのcron形式も、月末を表す L をサポートしていません。

0 9 28-31 * * に変えても「月の最後の日だけ」にはなりません。これは存在する28日・29日・30日・31日に一致します。次の表は、基準日時を2026年9月27日09:00 JST、タイムゾーンを東京にした固定例です。

0 9 28-31 * * の次の7候補
順番Asia/TokyoUTC instant月末だけか
12026年9月28日(月)09:002026-09-28T00:00:00Zいいえ
22026年9月29日(火)09:002026-09-29T00:00:00Zいいえ
32026年9月30日(水)09:002026-09-30T00:00:00Z月末
42026年10月28日(水)09:002026-10-28T00:00:00Zいいえ
52026年10月29日(木)09:002026-10-29T00:00:00Zいいえ
62026年10月30日(金)09:002026-10-30T00:00:00Zいいえ
72026年10月31日(土)09:002026-10-31T00:00:00Z月末

実装を分けて考える

28〜31日の候補で起動し、処理側が意図したタイムゾーンで「明日が翌月か」を確認して月末だけ続行する方法があります。日次起動と月末ガードを組み合わせる方法もあります。重複起動や再試行に備えて、実処理の冪等性も別途設計してください。このツールはガード条件や実ジョブを検証しません。

const { parseCron, nextRuns } = await import("/cron.js");
const result = nextRuns(parseCron("0 9 28-31 * *"), {
  after: new Date("2026-09-27T00:00:00Z"),
  timeZone: "Asia/Tokyo",
  count: 7
});
console.table(result.runs.map(({ label, iso }) => ({ local: label, utc: iso }))); 

夏時間では現地時刻とUTC instantの両方を見る

夏時間を採用する地域では、時計を進める日に存在しない現地時刻があり、時計を戻す日に同じ現地時刻が二度あります。次はツールが対応する America/New_York の固定例です。

2026年の切替付近での固定計算例
式と基準日時現地時刻の候補UTC instant
0 2 * * *
3月7日00:00 ESTより後
3月7日(土)02:002026-03-07T07:00:00Z
0 2 * * *
同じ検索の次回
3月8日(日)の02:00は候補に出ず、次は3月9日(月)02:00 EDT2026-03-09T06:00:00Z
0 1 * * *
11月1日00:30 EDTより後
11月1日(日)01:00(1回目)2026-11-01T05:00:00Z
0 1 * * *
同じ検索の次回
11月1日(日)01:00(2回目)2026-11-01T06:00:00Z

ツールの春の例では、存在しない02:00を飛ばし次の有効な日を返します。秋の例では壁時計のラベルが同じ01:00でもUTC instantが異なる候補を2つ表示します。Cloud Schedulerは壁時計時刻で動き、夏時間の前後に実行が不規則になる場合があると公式資料で説明しています。ツールの表示だけで本番スケジューラーの挙動を断定しないでください。

const { parseCron, nextRuns } = await import("/cron.js");
for (const [expression, after] of [
  ["0 2 * * *", "2026-03-07T05:00:00Z"],
  ["0 1 * * *", "2026-11-01T04:30:00Z"]
]) {
  const result = nextRuns(parseCron(expression), {
    after: new Date(after), timeZone: "America/New_York", count: 4
  });
  console.table(result.runs.map(({ label, iso }) => ({ local: label, utc: iso })));
}

確認手順

  1. トップの式欄に例を入力し、地域の予定なら該当するタイムゾーンを選びます。
  2. 日付と曜日を数件見て、月末の不要な候補や夏時間の欠落・重複を探します。
  3. UTC instant列も確認し、実際のスケジューラー側で設定したタイムゾーンと照らします。
  4. 高い頻度や正確な間隔が必要なCloud Schedulerでは、公式資料を確認し、夏時間の影響を避ける必要があればUTCを検討します。

このページとツールの制約

対応タイムゾーンはUTC・Asia/Tokyo・America/New_Yorkです。日時はブラウザのDate/Intlと現行タイムゾーンデータに依存します。祝日、実行先サービス、ジョブ登録、配信の成功、重複時の業務処理は確認しません。

一次資料

cron式と次の日時を確認する