「時間バッテリー」を表示する(JavaScript)

## はじめに

- JavaScriptの基礎を学んだ後に2番目に作成したミニアプリです。
- どの言語でもそうだと思いますが、日付や時間を扱うのはプログラミング基礎を学んだ後にやっておくとよいと思っております。（そう勝手に思っています）
- そこで、**「時間バッテリー」というタイトルで、現在を基準に、年末まで・月末まで・今日の終わりまでを算出してプログレスバーを表示してみようと思いました。**

## やったこと
- 現在日付から年末までの日数カウント、バッテリー％表示
- 現在日付から今月末までの日数カウント、バッテリー％表示
- 現在日付から今月末までの日数カウント、バッテリー％表示
- 基準日からターゲット日までの日数カウント、バッテリー％表示

[デモサイト](https://anotherskyjp.site/devapps/otherpg/02_timebattery/timebattery.html)
![time.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/2d7f56b2-8905-1f54-2926-d6de003be0bb.png)

## コード(HTML/CSS/JavaScript)
~~~timebattery.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial=1.0">
    <title>TimeBattery</title>
    <link type="text/css" rel="stylesheet" href="https://code.jquery.com/ui/1.10.3/themes/cupertino/jquery-ui.min.css">
    <link rel="stylesheet" href="./timebattery.css">
  </head>

  <body>
    <h1>Time Battery</h1>
    <p id="nowtime"></p>
    <p id="year"></p>
    <div class="progress1"><span id="loading1"></span></div>
    <br>
    <p id="month"></p>
    <div class="progress2"><span id="loading2"></span></div>
    <br>
    <p id="today"></p>
    <div class="progress3"><span id="loading3"></span></div>
    <br>
    <p>[カレンダー対応ブラウザ] Chrome、Opera、MS Edge</p>
    <p>
      基準日 <input id="cal_start" type="date" name="calendar" max="9999-12-31">
      ～ ターゲット日 <input id="cal_end" type="date" name="calendar" max="9999-12-31">
    </p>
    <p id="result"></p>
    <div class="progress4"><div id="loading4"></div></div>

    <script type="text/javascript" src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>
    <script type="text/javascript" src="./timebattery.js"></script>
  </body>
</html>
~~~

~~~timebattery.css
body {
    text-align: center;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 14px;
}
.progress1, .progress2, .progress3, .progress4 {
    margin: 0 auto;
    width: 50%;
}
#loading1, #loading2, #loading3, #loading4 {
    position: absolute;
    left: 50%;
    font-weight: bold;
}
~~~

~~~timebattery.js
$(function() {
    'use strict';

    var nowDate = new Date();
    var year = nowDate.getFullYear();     // 年(4桁の西暦)
    var mon  = nowDate.getMonth();        // 月(0～11)
    var date = nowDate.getDate();         // 日(1～31)
    var hour = nowDate.getHours();        // 時(0～23)
    var min  = nowDate.getMinutes();      // 分(0～59)
    var sec  = nowDate.getSeconds();      // 秒(0～59)

    //現在時刻の表示
    var month = mon + 1;
    var nowtime = "現在: " + year + "年" + month + "月" + date + "日";
    document.getElementById("nowtime").innerHTML = nowtime;

    //目的の日付をセット
    var yearEnd = new Date(year, 11, 31);         //年末の日付をセット
    var monthEnd = new Date(year, mon + 1, 0);    //今月末をセット
    var todayEnd = new Date(year, mon, date, 23, 59, 59);   //今日の最終時刻をセット

    //それぞれを数値化
    var dnumNow = nowDate.getTime();        //現在時刻の数字をget
    var dnumYearEnd = yearEnd.getTime();    //年末の数字をget
    var dnumMonthEnd = monthEnd.getTime();  //今月末の数字をget
    var dnumTodayEnd = todayEnd.getTime();  //今日の数字をget

    //それぞれのENDと現在との差を計算
    var diffYear = dnumYearEnd - dnumNow;
    var diffMonth = dnumMonthEnd - dnumNow;
    var diffToday = dnumTodayEnd - dnumNow;

    //差と％を計算(年)
    var diffDays1 = diffYear / ( 1000 * 60 * 60 * 24 );       // 日数を割り出す
    var showDays1 = Math.ceil( diffDays1 );                   // 小数点以下を切り上げる
    var yearValue = Math.ceil( showDays1 / 365.25 * 100 );    // %を計算
    //差と％を計算(月)
    var diffDays2 = diffMonth / ( 1000 * 60 * 60 * 24 );      // 日数を割り出す
    var showDays2 = Math.ceil( diffDays2 );                   // 小数点以下を切り上げる
    var monthValue = Math.ceil( showDays2 / 30 * 100 );       // %を計算
    //差と％を計算(時間)
    var todayValue = Math.ceil(diffToday / ( 1000 * 60 * 60 * 24 ) * 100);     // %を計算
    var dHour  = diffToday / ( 1000 * 60 * 60 );   // 時間
    diffToday = diffToday % ( 1000 * 60 * 60 );
    var dMin   = diffToday / ( 1000 * 60 );        // 分
    diffToday = diffToday % ( 1000 * 60 );
    var dSec   = diffToday / 1000;                 // 秒
    var showDays3 = Math.floor(dHour) + "時間" + Math.floor(dMin) + "分" + Math.floor(dSec) + "秒";

    //年末までの日数を表示
    var yearEnd = "年末まで あと" + showDays1 + "日";
    document.getElementById("year").innerHTML = yearEnd;

    //今月末までの日数を表示
    var monthEnd = "今月末まで あと" + showDays2 + "日";
    document.getElementById("month").innerHTML = monthEnd;

    //今日の終わりまでの時間を表示
    var todayEnd = "今日の終わりまで あと" + showDays3;
    document.getElementById("today").innerHTML = todayEnd;

    //プログレスバーと％テキスト表示
    progress('.progress1', yearValue, '#loading1');
    progress('.progress2', monthValue, '#loading2');
    progress('.progress3', todayValue, '#loading3');

    function progress(barNum, value, loadNum){
        // プログレスバーを生成
        $(barNum).progressbar({
            value: value,
            max: 100
        });
        // %のテキスト表示
        var per = $(barNum).progressbar('value') / $(barNum).progressbar('option', 'max');
        $(loadNum).text(Math.ceil(per * 100) + '％');
        // %の色つけ
        $(barNum).each(function(){
            var selector = $(this).find('div');
            var value = this.getAttribute("aria-valuenow");

            if (value >= 50 ){
                $(selector).css({ 'background': 'LightGreen' });
            } else if (value >= 30){
                $(selector).css({ 'background': 'LightYellow' });
            } else {
                $(selector).css({ 'background': 'Pink' });
            }
        });
    }

    //カレンダーにデフォルト日付を設定
    var mm = ("0"+(nowDate.getMonth()+1)).slice(-2);
    var dd = ("0"+ nowDate.getDate()).slice(-2);
    var calStartYear = year - 1;
    document.getElementById("cal_start").value = calStartYear + '-' + mm + '-' + dd;
    var calEndYear = year + 1;
    document.getElementById("cal_end").value = calEndYear + '-' + mm + '-' + dd;

    //変数設定
    var cal_startForm = document.getElementById('cal_start');
    var cal_endForm = document.getElementById('cal_end');

    //カレンダー日が変更されたときfunction timecalcを呼び出す
    cal_startForm.addEventListener('change', timecalc);
    cal_endForm.addEventListener('change', timecalc);

    function timecalc(){

        var startDate = new Date(cal_startForm.value);
        var targetDate = new Date(cal_endForm.value);

        //設定された日付が過去日付であったらメッセージ表示
        if(targetDate < nowDate) {
            document.getElementById("result").innerHTML = "未来日付を設定してください";
        } else {
            //数値化
            var dnumStart = startDate.getTime();
            var dnumNow = nowDate.getTime();
            var dnumTarget = targetDate.getTime();

            //それぞれのENDと現在との差を計算
            var calDiff1 = dnumTarget - dnumNow;
            var calDiff2 = dnumTarget - dnumStart;

            //差と％を計算(月)
            var calDiffDays1 = calDiff1 / ( 1000 * 60 * 60 * 24 );   // 日数を割り出す
            var calDiffDays2 = calDiff2 / ( 1000 * 60 * 60 * 24 );   // 日数を割り出す

            var calShowDays1 = Math.ceil( calDiffDays1 );                // 小数点以下を切り上げる
            var calShowDays2 = Math.ceil( calDiffDays2 );                // 小数点以下を切り上げる

            var dateValue1 = Math.ceil(calShowDays1 / calShowDays2 * 100);      //  %を計算
            var dateValue2 = calShowDays2 - calShowDays1;

            var dateResult = "ターゲット日付まであと" + calShowDays1 + "日" + "(" + dateValue2 + "日経過)";
            document.getElementById("result").innerHTML = dateResult;

            // プログレスバーとテキスト表示
            progress('.progress4', dateValue1, '#loading4');

        }
    };
});
~~~

## まとめ
- 言語の基礎を学んだ後は、日付や時間計算のプログラムをやるとよい、と個人的に思います。
- 「時間バッテリー」というタイトルで、プログレスバーの表示をやってみました。
- バッテリー形式にしているので、年末に向けてエネルギーがなくなるように見えるなぁ・・と思ったりもしますが(汗)。