Q1setInterval に渡す関数の中で let count = 0; を宣言し、3 で止めるようにすると?
タイマーと日付 — setTimeout / Date / Intl
時間をおいて関数を呼ぶ setTimeout、繰り返し呼ぶ setInterval の止め方、Date の作り方と月が 0 から始まる数え方、Intl.DateTimeFormat による日付の表示、日数の差の求め方を扱います。
通知を 3 秒後に閉じる、残り秒数を 1 秒ごとに減らす処理は、上の行から順に進むだけでは書けません。公開日に曜日を付けて表示したり、期限までの日数を数えたりする処理も、日付が文字列のままではできません。
この記事では、タイマーを作る setTimeout と setInterval、日時を表す Date と Intl.DateTimeFormat を扱います。
予約して後から呼ぶ — setTimeout と clearTimeout
写真の共有サイトで「アップロードしました」の通知を出し、3 秒後に閉じたいとします。上の行から順に進むコードには「3 秒たってから次を動かす」書き方が無く、for を空回りさせて時間をつぶすと、その間はクリックも画面の更新も止まります。
setTimeout(関数, ミリ秒) は関数を呼ぶ時刻を予約するだけで、すぐに次の行へ進みます。戻り値は fetch のタイムアウトで使ったタイマー ID で、clearTimeout に渡すと予約を取り消せます。
// ms ミリ秒後に fulfilled になる Promise を返す(Promise の記事の delay から value を省いた形)
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// 100ms 後に通知を閉じるよう予約し、すぐ次の行へ進む(実際の画面では 3000ms など)
setTimeout(() => console.log("通知を閉じました"), 100); // 通知を閉じました(2 番目)
console.log("アップロードしました"); // アップロードしました(1 番目)
// 画面を離れたので、おすすめの表示の予約を取り消す。100ms たっても呼ばれない
const recommendTimer = setTimeout(() => console.log("おすすめの写真を表示しました"), 100);
clearTimeout(recommendTimer);
// 200ms たつまで、この行から先へ進まない
await delay(200);
console.log("200ms 待ちました"); // 200ms 待ちました(3 番目)
予約した関数は、コードが最後の行まで進んだ後にも動きます。予約した表示を練習問題のコンソールで確かめるときは、Promise の記事と同じく、最後に await delay(…) で待つ行を置きます。
繰り返しを止める — setInterval と clearInterval
セールの終了まで、残り秒数を 1 秒ごとに減らして表示したいとします。setTimeout は予約した関数を 1 回しか呼ばないので、繰り返すには呼ばれた関数の中で毎回予約し直すことになり、止める条件もその中に散らばります。
setInterval(指定したミリ秒ごとに、同じ関数を繰り返し呼ぶ関数)は、戻り値のタイマー ID を clearInterval に渡すまで呼び続けます。
繰り返しが終わってから次の行を動かすには、関数を Promise で包み、clearInterval を呼ぶ if の中で続けて resolve を呼びます。
// 残り秒数を 100ms ごとに 1 つ減らす(実際の画面では 1000ms ごと)
function startCountdown(seconds) {
return new Promise((resolve) => {
let remaining = seconds; // 呼ばれる関数の外に置き、呼び出しをまたいで残す
const timerId = setInterval(() => {
remaining -= 1;
console.log(`残り ${remaining} 秒`); // 残り 2 秒 → 残り 1 秒 → 残り 0 秒
if (remaining === 0) {
clearInterval(timerId); // 0 になった回で止める(呼ばれる時点で timerId は代入済み)
resolve(); // 止めたことを await の行へ知らせる
}
}, 100);
});
}
await startCountdown(3);
console.log("セールは終了しました"); // セールは終了しました
- 返された Promise が fulfilled になるまで、次の行へ進まない
セールは終了しましたは resolve の後に表示される
let remaining = seconds— ここで 1 回だけ作られ、3 が入るconst timerId = setInterval(...)— 止めるときに渡す ID
remaining -= 1— 外側の変数を減らす: 2 → 1 → 0- 0 になった回で
clearInterval(timerId)とresolve()
let remaining = seconds を呼ばれる関数の中へ移すと、呼ばれるたびに 3 から作り直されて 0 にならず、clearInterval も resolve も呼ばれません。進まないまま 15 秒たつと、練習問題のコンソールは実行がタイムアウトしたと表示します。
止め忘れた繰り返しが後の実行に混ざる
練習問題のコンソールは、この記事のすべての実行で同じページを使います。clearInterval を呼ばずに実行を終えると、その関数はページを再読み込みするまで呼ばれ続け、後から実行した演習のうち await で待つものの結果に表示が混ざって、正しいコードでも不正解になります。混ざったときは、記事のページを再読み込みしてください。
日付を表示用の文字列にする — getMonth と Intl
動画の一覧に、公開日時を「2026年9月2日(水)」の形で表示したいとします。API から届く "2026-09-02T09:00:00" のような文字列から slice で月を切り出すと "09" の文字列になり、曜日はどこにも書かれていないので、文字列のままでは求められません。
Date(日時を表す組み込みのオブジェクト)は、"2026-09-02T09:00:00" を端末のタイムゾーン(UTC という基準の時刻との時差で決まる地域の時刻)の 9 時として読み、get で始まるメソッドで月や曜日を数値で返します。
Intl.DateTimeFormat(言語ごとの表記で日時を文字列にするクラス)は、"ja-JP"(日本語)を渡して作ります。
const publishedAt = new Date("2026-09-02T09:00:00");
// get で始まるメソッドは数値を返す。月は 1 月が 0、曜日は日曜が 0
console.log(publishedAt.getMonth(), publishedAt.getDate(), publishedAt.getDay()); // 8 2 3
// 言語と、表示する項目ごとの形を渡して書式を作る
const dateFormat = new Intl.DateTimeFormat("ja-JP", {
year: "numeric", // 年を数字で
month: "long", // 月を「9月」の形で
day: "numeric", // 日を数字で
weekday: "short", // 曜日を短い名前で
});
console.log(dateFormat.format(publishedAt)); // 2026年9月2日(水)
console.log(new Intl.DateTimeFormat("ja-JP", { hour: "numeric", minute: "2-digit" }).format(publishedAt)); // 9:00
// 時刻を省いた文字列は、UTC の 0 時として読まれる
const dateOnly = new Date("2026-09-02");
console.log(dateOnly.getDate()); // 日本では 2、ニューヨークでは 1(前日の 20 時)
日本で実行すると 2 が返るので、この違いには気づきにくいです。API から届く文字列が日付だけのときは "T00:00:00" を付けて渡し、端末のタイムゾーンの 0 時として読みます。下の表は、publishedAt に対する get で始まるメソッドの戻り値をまとめたものです。
| メソッド | publishedAt での戻り値 | 表示に使うとき |
|---|---|---|
| getFullYear() | 2026 | そのまま使える |
| getMonth() | 8 | 1 月が 0 なので、1 を足して 9 月 |
| getDate() | 2 | 日は 1 から数えるので、そのまま使える |
| getDay() | 3 | 日曜が 0 なので、3 は水曜 |
| getHours() | 9 | 0〜23 の 24 時間表記 |
期限までの日数を数える — Date の引き算
図書館のサイトで、返却期限まであと何日かを表示したいとします。日の数字だけを引くと、9 月 2 日に借りて期限が 10 月 3 日なら 3 - 2 で 1 日になり、月をまたいだ分の日数が数えられません。
Date は 1970 年 1 月 1 日 0 時(UTC)からのミリ秒を数値で持ち、Date どうしの引き算はその差を返すので、1 日のミリ秒 24 * 60 * 60 * 1000 で割ると日数になります。
その日の 0 時を表す new Date(年, 月, 日) でも、月は 0 から数えます。
// 1 日のミリ秒(24 時間 × 60 分 × 60 秒 × 1000)
const DAY_MS = 24 * 60 * 60 * 1000;
// 貸出日と返却期限。数値で作るときも、月は 0 から数える
const borrowedAt = new Date(2026, 8, 2); // 2026 年 9 月 2 日
const dueDate = new Date(2026, 9, 3); // 2026 年 10 月 3 日
// Date どうしの引き算は、ミリ秒の差になる
const diffMs = dueDate - borrowedAt;
console.log(Math.round(diffMs / DAY_MS)); // 31
// 9 月に無い 31 日を渡すと、エラーにならず翌月へ繰り上がる
const overflowDate = new Date(2026, 8, 31);
console.log(overflowDate.getMonth() + 1, overflowDate.getDate()); // 10 1
Math.round で丸めるのは、夏時間(夏の間だけ時計を 1 時間進める制度)のある地域では 1 日が 23 時間や 25 時間の日があり、割った結果が 30.958… のように整数にならないことがあるためです。日本で実行すると割り切れるので、丸め忘れには気づきにくくなります。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2new Date("2026-09-02T09:00:00").getMonth() の戻り値は?
Q3new Date(2026, 8, 31) で作った Date の getDate() は?