Help us understand the problem. What is going on with this article?

JavaScript カウントダウンタイマー「なぜこの書き方なのか?」と悩んだこと

はじめに

フロントエンドエンジニアを目指しております、プログラミング歴5ヶ月の者です。

現在、JavaScriptの基礎を身につけるため『確かな力が身につく JavaScript 「超」入門編』で勉強中です。

本書のなかで、カウントダウンタイマー(Udemyのセールなどでよく見るような、"セール終了まで○時間○分○秒"と表示されるアレです)の処理が少しややこしく、「なぜこの書き方なんだろう」と少し考え込んでしまったので、備忘録として残そうと思います。

本書で紹介しているコード

getTime()メソッドで、まず全体の残り時間をミリ秒で算出し(restに代入)、それからそれぞれの単位(時、分、秒)の残り時間を算出しています。
※getTime()は、1970年1月1日0時からの時間をミリ秒で取得するメソッド。

countdown.js
function countdown(due) {
  const now =  new Date();
  const rest = due.getTime() - now.getTime(); //残り時間をミリ秒で算出

  const sec = Math.floor(rest / 1000) % 60;
  const min = Math.floor(rest / 1000 / 60) % 60;
  const hours = Math.floor(rest / 1000 / 60 / 60) % 24;
  const days = Math.floor(rest / 1000 / 60 / 60 / 24);
  const count = [days, hours, min, sec];

  return count;
}

let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);
console.log(countdown(goal));

const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}${counter[3]}秒`;
document.getElementById('timer').textContent = time;

これじゃダメなの?と思ったコード

正直、ミリ秒からの算出がややこしく、上記コードを理解するのに少し苦労してしまいました。(「なんで剰余算演算子(割り算の余り)なんだ..???」とか..)

率直に、「単純に "期限日時の数値 - 現在日時の数値" じゃダメなの?」と思ってしまいまして(例:「23時 - 22時」、「59分 - 30分」など)、そこで浮かんだのが以下のコードです。
※変更点は countdownファンクション内の処理のみです。

mycountdown.js
function countdown(due) {
const now = new Date;
const rest = due.getTime() - now.getTime();

const sec = due.getSeconds() - now.getSeconds();
const min = due.getMinutes() - now.getMinutes();
const hours = due.getHours() - now.getHours();
const days = due.getDay() - now.getDay();
const count = [days, hours, min, sec];

  return count;
}

//以下は countdown.js と同じ
let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);
console.log(countdown(goal));

const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}${counter[3]}秒`;
document.getElementById('timer').textContent = time;

get〜メソッドで単純にそれぞれの数値を取得して、算出する方法です。
(23時59分59秒を期限としているので、例えば現在時刻が20時00分00秒の場合、残り時間を「3時間59分59秒」と表示させます)

月と日の残りの計算がおかしくなる可能性がある

そもそも変数 goal に月日を設定していないので当たり前ですが、mycountdown.js のコードだと、「本日中(23時59分59秒まで)を期限に設定している場合」のみ使えるコードになってしまいます。

どういうことかと言うと、例えばもし翌日以降を期限日として設定し、それぞれ現在時刻と期限日を以下のパターンにした場合、 1(期限に設定した日にち) - 31(現在の日にち) = -30で、残りの日数は 「-30日」になってしまいます。

・現在時刻 → 「10月31日00時00分00秒」
・期限日 → 「11月1日23時59分59秒」

また、残り月(表示するケースはあまりなさそうですが)に関しても、以下のパターンの場合は、1 - 12 で残りの月は「-11ヶ月」となってしまいます。

・現在時刻 → 「12月31日00時00分00秒」
・期限日 → 「1月1日00時00分00秒」

「なぜこの書き方なのか?」を考えるようにする

今回の場合、一見 「mycountdown.js のコードでもいいのでは?」と思ってしまうのですが、自分なりに深掘りすると、不十分なコードだと気がつくことができました。

初学者のうちは、難しいコードに出くわすと、コードの意味をきちんと理解するのに苦労することがよくあるのではないかと思います。そんなときは、「何かしらの意味があってこの書き方をしているのだ」ということを念頭において考えると、一歩先の理解へとつながるのではないかと思いました。

こちらの記事におきまして、もしズレた解釈をしてしまっているようでしたらご指摘いただければと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした