In 'n' Out

知識を取り込み、そして発信する

日付と時間

日付と時間を取得・操作する

Webサイトでは現在の日時を取得するだけでなく、取得した時間をもとに処理を行う場面も多くあります。
例えばECサイトでは営業時間の表示やセールの残り時間の表示、カウントダウンタイマー、ボタン操作後の遅延処理、カレンダーでの日付選択などに利用されます。
これらはすべて日付や時間を取得し、用途に応じて処理や表示を変えることで実現されています。
ここでは日付と時間を取得する方法と、取得した時間を使った簡単な処理方法を解説します。

Date関数

Dateは日付や時間を扱うための機能です。

構文

Date.メソッド();
Date();

Date.メソッド()はDateに用意されている機能を呼び出す書き方です。
Date()は現在の日時を文字列として返します。

Date関数のメソッド

日時はDate関数から取得することができます。

構文

Date.UTC(年, 月, 日, 時, 分, 秒, ミリ秒);
Date.parse(文字列);
Date.now();

Date.UTC・Date.parse・Date.nowはいずれもメソッドで、Date関数に属しています。
また、日時を扱う際は、基準となる時間の考え方を知っておく必要があります。
JavaScriptでは、日時は世界共通の基準であるUTC(協定世界時)をもとに管理されています。
Date.UTCがその協定世界時間を表します。
Date.parseは日時を表す文字列を解析し、UTCを基準とした数値に変換します。
引数は下記となります。

引数一覧
引数名入力例内容
year95整数値で年を表し、0から99までの値は1900から1999までとなります。
それ以外は実際の年を表します。
monthIndex9整数値で月を表し、0から11までの値は1月から12月までとなります。
指定しない場合は0扱いとなり、1月になります。
day15整数値で日を表し、1から31までとなります。
指定しない場合は1扱いとなり、1日になります。
hours21整数値で時を表し、0から23までとなります。
指定しない場合は0扱いとなり、0時になります。
minutes48整数値で分を表し、0から59までとなります。
指定しない場合は0扱いとなり、0分になります。
seconds30整数値で秒を表し、0から59までとなります。
指定しない場合は0扱いとなり、0秒になります。
milliseconds501整数値でミリ秒を表し、0から999までとなります。
指定しない場合は0扱いとなり、0ミリ秒になります。

引数は一部だけ指定することも可能ですが、必ずyearから記述しなければならないため、意図しない結果になる可能性があるため注意が必要です。
なお、nowは現在時刻を数値に変換するため引数は必要ありません。

コード例

//date1.js
alert(Date.UTC(95, 9, 15, 21, 48, 30, 501));
alert(Date.parse("1995-09-15T21:48:30Z"));
alert(Date.now());

動作例

※このボタンは動作確認用です

コード例の結果は長い数字の羅列が表示されます。
これは1970年1月1日0時0分0秒0ミリ秒から、指定した1995年9月15日21時48分30秒501ミリ秒までの経過時間を表した値です。
また、nowは1970年1月1日0時0分0秒0ミリ秒から、現在までの経過時間を表した値です。
そのため、nowだけは実行するたびに数値が可変します。
しかし、このままでは人が扱うには分かりづらいため、Date()を使って日付や時間の形式に変換していきます。

Date()関数

Date()は値を文字列で返します。

コード例

//date2.js
const convertDate1 = Date.UTC(95, 9, 15, 21, 48, 30, 501);
const convertDate2 = Date.now();

alert(Date(convertDate1));
alert(Date(convertDate2));

動作例

※このボタンは動作確認用です

Date()は引数に数値を渡すと、その値をもとに日時の文字列を生成します。
ここで使用している数値は、1970年1月1日0時0分0秒0ミリ秒からの経過時間を表しており、Date.UTCやDate.nowで取得した値です。
Date()を使うことで、その数値を人が読める形式の日時に変換できます。
ただし、この時点ではあくまで文字列として返されるため、年や月を個別に取り出すことはできません。

new Date()オブジェクト

ここまで日時の取得方法を見てきましたが、取得するのみで操作は行えません。
操作するために使うのがnew Date()オブジェクトになります。

構文

変数 = new Date(年, 月, 日, 曜日, 時, 分, 秒, ミリ秒)

new Dateはオブジェクトで、引数はDateメソッドの一覧表と同じです。
また、new演算子は他にも使用できますが、Dateでは必須となるため、まずはDateで使うものとして覚えて問題ありません。
new Dateで宣言することにより、日時にかかわるあらゆる情報を取り扱うメソッドを使用することができます。
メソッドは下記となります。

メソッド一覧
メソッド名取得内容戻り値
getFullYear()西暦の整数値を返します。
getMonth()0から11までの整数値を返します。
getDate()1から31までの整数値を返します。
getDay()曜日0から6までの整数値を返します。
getHours()0から23までの整数値を返します。
getMinutes()0から59までの整数値を返します。
getSeconds()0から59までの整数値を返します。
getMilliseconds()ミリ秒0から999までの整数値を返します。

Dateの引数と同様、月は0から始まる点に注意が必要です。

コード例

//newDate1.js
const date = new Date(95, 9, 15, 21, 48, 30, 501);

alert(date.getFullYear());

動作例

※このボタンは動作確認用です

このコード例では年を取得します。
メソッドを変更することで、年以外の値も取得できます。
また、メソッドは個別に呼び出すことで複数の値を取得できます。

コード例

//newDate2.js
const today = new Date();

const arr = [today.getFullYear(), today.getMonth() + 1, today.getDate(), today.getDay()];

const dayConvert = ['日', '月', '火', '水', '木', '金', '土'];

const day = dayConvert[arr[3]];

alert(arr[0] + '/' + arr[1] + '/' + arr[2] + '(' + day + ')');

動作例

※このボタンは動作確認用です

このコードはnew Date()で現在の日時を取得し、get系メソッドを使って年・月・日を取り出しています。
getMonth()は0から始まるため+1して調整しています。
取得した値を配列にまとめ、最後に「年/月/日(曜日)」の形式で表示しています。
getDay()は曜日という点に注意が必要です。
new Date()は引数を指定しない場合、現在の日時を取得します。
そのため、現在時刻を扱う場合はnew Date()だけで問題ありません。
一方で、Date.now()は現在時刻をミリ秒(数値)として取得するメソッドです。
主に時間の差分計算や経過時間の計測など、数値として扱いたい場合に使用します。

時間の差分

日時は取得するだけでなく、差分を取ることで経過時間や残り時間を計算できます。
よく目にするのが締め切りまでの時間やカウントダウン・タイマーといった機能です。
それでは年齢を例にしたコード例を見てみましょう。

コード例

//timeDiff1.js
const birthday = new Date(90, 7, 5);
const today = new Date();

alert(today.getFullYear() - birthday.getFullYear() + '歳です');

動作例

※このボタンは動作確認用です

このコード例では生年月日として1990年8月5日としました。
現在時刻の年から生まれ年を引いた結果が年齢として表示されます。
しかし、このコードでは正確ではない問題があります。
現在時刻でまだ8月5日を迎えていない可能性があるため、正確ではありません。
では、正確な年齢を表示するにはif文を追加します。

コード例

//timeDiff2.js
const birthday = new Date(90, 7, 5);
const today = new Date();

let age = today.getFullYear() - birthday.getFullYear();

if (today.getMonth() < birthday.getMonth() || (today.getMonth() === birthday.getMonth() && today.getDate() < birthday.getDate())) {
    age--;
}

alert(age + '歳です');

動作例

※このボタンは動作確認用です

途中までは先ほどのコードと同じですが、if文で条件を設定しました。
1つ目は現在の月が誕生月より小さい場合、2つ目は現在の月が誕生月と同じで、かつ現在の日付が誕生日の日付より小さい場合です。
つまり、8月5日を過ぎているかいないかで年齢を1つ減らして表示するという仕組みです。
このように、日時の差分は単純に引き算で求めることができます。
今回の例では年単位で計算しましたが、実際にはDate同士の差分はミリ秒で扱われています。
そのため、年齢のように特定の単位で扱う場合は、今回のように年・月・日を使って調整する必要があります。
また、より細かい時間の差(秒や分など)を扱う場合は、このミリ秒をもとに変換していくことになります。
この考え方を使うことで、後に経過時間や残り時間といった処理にも応用できます。

時間の操作

Webサイトでは、特定の処理を少し時間をおいて実行したい場面があります。
例えば数秒後にメッセージを表示させたり、ボタン操作後に処理を遅らせるなどです。

構文

変数=setTimeout(関数, 遅延時間(ミリ秒));
clearTimeout(setTimeoutで宣言した変数);

setTimeoutはメソッドで、指定した時間(ミリ秒)後に、1回だけ関数を実行します。
戻り値としてタイマーIDが返され、それを変数に代入します。
clearTimeoutもメソッドで、setTimeoutで登録した処理を途中でキャンセルします。
引数には、setTimeoutの戻り値(タイマーID)を渡します。

コード例

//timeout.js
let timeoutId;
let running = false;

function startTimeout() {
    if (!running) {
        running = true;
        timeoutId = setTimeout(() => {
            alert('3秒経過');
            running = false;
        }, 3000);
    }
}

function stopTimeout() {
    if (running) {
        running = false;
        clearTimeout(timeoutId);
        alert('キャンセルしました');
    }
}

動作例

※このボタンは動作確認用です

必ずしもこの書き方である必要はありません。
ここでは、ボタンの押下でタイマーの動作を管理するために、それぞれのボタン用に関数を用意しています。
まず、関数の外でtimeoutIdと running という変数を宣言します。
timeoutIdはsetTimeoutを管理するための変数、runningはタイマーが動作中かどうかを判定するフラグです。
初期値はfalseにしておきます。
実行ボタンを押すとstartTimeout関数が呼び出されます。
runningがfalseの場合のみsetTimeoutが実行され、3秒後にalertが表示されます。
同時にrunningをtrueにすることで、複数回の実行を防いでいます。
停止ボタンを押すとstopTimeout関数が呼び出されます。
runningがtrueの場合、clearTimeoutによってタイマーをキャンセルし、処理を停止します。
なお、タイマーの処理が完了した後(3秒後に実行された後)は、すでに処理が終了しているためキャンセルはできません。
このように、clearTimeoutを使用する場合は、必ずsetTimeoutの戻り値を代入した変数を指定する必要があります。
また、途中で中止する必要がない場合は、clearTimeoutを使用する必要はありません。

時間での操作

一定の時間間隔で繰り返し処理を行いたい場合があります。
例えば1秒ごとにカウントアップ、定期的にデータを取得するなどです。

構文

変数=setInterval(関数, 間隔(ミリ秒));
clearInterval(setIntervalで宣言した変数);

setIntervalはメソッドで、指定した時間(ミリ秒)の間隔ごとに、関数を繰り返し実行します。
戻り値としてタイマーIDが返され、それを変数に代入します。
clearIntervalもメソッドで、setIntervalで登録した処理を途中でキャンセルします。
引数には、setIntervalの戻り値(タイマーID)を渡します。

コード例

//interval.js
let intervalId;
let time = 0;
let run = false;

function startInterval() {
    if (!run) {
        run = true;
        intervalId = setInterval(() => {
            time += 3;
            alert(time + '秒経過');
        }, 3000);
    }
}

function stopInterval() {
    if (run) {
        run = false;
        clearInterval(intervalId);
        alert('キャンセルしました');
        time = 0;
    }
}

動作例

※このボタンは動作確認用です

setIntervalは、指定した時間ごとに処理を繰り返し実行するメソッドです。
setTimeoutが一度だけ実行されるのに対し、setIntervalは停止するまで繰り返し実行されるという違いがあります。
この例では、3秒ごとに処理が実行され、経過時間をalertで表示しています。
なお、setIntervalは自動では停止せず、処理が繰り返し実行され続けます。
そのため、繰り返しを止める場合はclearIntervalを使用する必要があります。
また、実行ボタンを複数回押すと、同じ処理が重複して実行されてしまうため、runフラグを使って制御しています。
これらを組み合わせることで、タイマーやカウントダウンなどの実用的な機能を実装できます。