JavaScriptで指定月日まであと何日か毎年表示させたい！

# 目指すもの
1. 現在から指定した月日までカウントダウンしたい。
1. 指定月日になったら、 **その日だけ** 表示を変えたい。

# 実際に作ったやつ
[WEBサイト](https://null8r.github.io/uruharushia/)
[GitHub](https://github.com/null8r/uruharushia/)
[GitHubにあるJavaScript](https://github.com/null8r/uruharushia/blob/main/src%2Fjs%2Fbirthday-count.js)

# JavaScript
現在の日付を **2023年12月20日**、指定月日を**2024年1月22日**とする。

:::note warn
間違えていました。
ご指摘ありがとうございます。(2023年12月21日修正)
:::

<details><summary>間違えていたプログラム</summary>

``` diff_javascript:間違いと修正
// 表示させたい文字入れるため
let msg;

function countDown(){
    // 現在の「曜日 月 日 年 時 分 秒」を取得
    let nowDate = new Date();
    // nowDateを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let now = nowDate.getTime();
    // 現在が西暦何年か取得 (This Year)
    let tYear = nowDate.getFullYear();

    // 来年が西暦何年か
-    let nYear = tYear + 1;
+    let nYear = tYear;
    // 指定月日の月を指定
    let nMonth = 1 - 1;
    // 指定月日の日を指定
    let nDate = 22;
    
+    // 指定月日がすでに過ぎていたら、来年の月日に変更 
+    if( nowDate.getMonth() > nMonth || nowDate.getDate() > nDate ){
+        date += 1;
+    }

    // 指定月日を「曜日 月 日 年 時 分 秒」に変換
    let n = new Date( nYear, nMonth, nDate );
    // nを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let nTarget = n.getTime();

    // 現在から指定月日まであと何ミリ秒か計算
    let diffDate = nTarget - now;

    // 指定月日まであと何日か計算
    let date = Math.floor( diffDate / ( 1000 * 60 * 60 * 24 ));

-    // 年越しすると、365日を超えるから366日引く
-    if( date > 365 ){
-        date = date - 366;
-    }

    // 指定月日になった
    if( date == 0 ){
        msg = '指定月日だよ！';
    }
    // 指定月日ではない
    else{
        msg = '指定月日まで、あと' + date + '日だよ。';
    }

    // メッセージを表示
    console.log(msg);
}

// 1秒毎に「countDown()」を実行
setInterval('countDown()', 1000);
```
</details>


``` js:プログラム
// 表示させたい文字入れるため
let msg;

function countDown(){
    // 現在の「曜日 月 日 年 時 分 秒」を取得
    let nowDate = new Date();
    // 現在が西暦何年か取得 (This Year)
    let tYear = nowDate.getFullYear();
    // 現在が何月か取得 (This Month)
    let tMonth = nowDate.getMonth();
    // 現在が何日か取得 (This Date)
    let tDate = nowDate.getDate();

    // nowDateを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let now = new Date(tYear, tMonth, tDate).getTime();
    
    // 指定月日の年を指定
    let nYear = tYear;
    // 指定月日の月を指定
    let nMonth = 1 - 1;
    // 指定月日の日を指定
    let nDate = 22;

    // 指定月日がすでに過ぎていたら、来年の月日に変更
    if( nowDate.getMonth() > nMonth || nowDate.getMonth() == nMonth && nowDate.getDate() > nDate ){
        nYear += 1;
    }

    // 指定月日を「曜日 月 日 年 時 分 秒」に変換
    let n = new Date( nYear, nMonth, nDate );
    // nを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let nTarget = n.getTime();

    // 現在から指定月日まであと何ミリ秒か計算
    let diffDate = nTarget - now;

    // 指定月日まであと何日か計算
    let date = Math.floor( diffDate / ( 1000 * 60 * 60 * 24 ));

    // 現在から指定月日まであと何ミリ秒か再計算
    diffDate = nTarget - now;
    
    // 指定月日になった
    if( diffDate <= 0 ){
        msg = '指定月日だよ！';
    }
    // 指定月日ではない
    else{
        msg = '指定月日まで、あと' + date + '日だよ。';
    }

    // メッセージを表示
    console.log(msg);
}

// 1秒毎に「countDown()」を実行
setInterval('countDown()', 1000);
```


# 簡単な解説
多分間違えている。

:::note warn
**本当に間違えていました。** 
ご指摘ありがとうございます。(2023年12月21日修正)
:::

## 現在の日付を取得・処理
現在の日付を **2023年12月20日**、指定月日を**2024年1月22日**とする。
``` js
    // 現在の「曜日 月 日 年 時 分 秒」を取得
    let nowDate = new Date();
    // 現在が西暦何年か取得 (This Year)
    let tYear = nowDate.getFullYear();
    // 現在が何月か取得 (This Month)
    let tMonth = nowDate.getMonth();
    // 現在が何日か取得 (This Date)
    let tDate = nowDate.getDate();

    // nowDateを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let now = new Date(tYear, tMonth, tDate).getTime();
    
    console.log(nowDate);
    console.log(now);
    console.log(tYear);
```
``` :実行結果
Wed Dec 20 2023 00:00:00 GMT+0900 (日本標準時)
1702998000000
2023
```

## 指定月日の設定
先程も書いたように指定月日は、**1月22日**とする。

:::note warn
月を指定するときは、`-1`することを**忘れない！！！**
`1月`は`0`、`2月`は`1`のように指定していく。
[詳しいこと](#%E6%97%A5%E4%BB%98%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E5%80%8B%E5%88%A5%E5%8F%96%E5%BE%97)
:::

``` js
    // 指定月日の年を指定
    let nYear = tYear;
    // 指定月日の月を指定 -1を忘れない！！！
    let nMonth = 1 - 1;
    // 指定月日の日を指定
    let nDate = 22;
    
    // 指定月日を「曜日 月 日 年 時 分 秒」に変換
    let n = new Date( nYear, nMonth, nDate );
    // nを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let nTarget = n.getTime();

    console.log(nYear);
    console.log(n);
    console.log(nTarget);
```
``` :実行結果
2023
Sun Jan 22 2023 00:00:00 GMT+0900 (日本標準時)
1674313200000
```

## 指定月日まであと何日か計算
指定月日から現在の時間を引いて、指定月日まであと何ミリ秒か求める。
上で求めたミリ秒を下の順で計算し、日に変換する。
ミリ秒 `/ 1000ミリ秒` → 秒 `* 60秒` → 分 `* 60分` → 時間 `* 24時間` → 日
``` js
    // 現在から指定月日まであと何ミリ秒か計算
    let diffDate = nTarget - now;

    // 上で求めたミリ秒を日に変換
    // 指定日までの日数 = 指定月日までのミリ秒 / ( 1000 * 60秒 * 60分 * 24時間 )
    let date = Math.floor( diffDate / ( 1000 * 60 * 60 * 24 ));

    console.log(diffDate);
    console.log(date);
```
``` :実行結果
-28684800000
-332
```
:::note alert
指定月日まであと`-332`日になってしまった。
指定月日をすでに過ぎてしまっているため、こうなってしまう。
:::

## 指定月日をすでに過ぎているときの処理
このプログラムでは、現在(`2023年12月20日`)から指定月日(`2023年1月22日`)までを求めることになっている。
これでは、正しく求められないので修正する必要がある。

``` diff_javascript:修正
    // 指定月日の年を指定
    let nYear = tYear;
    // 指定月日の月を指定 -1を忘れない！！！
    let nMonth = 1 - 1;
    // 指定月日の日を指定
    let nDate = 22;

+   // 指定月日がすでに過ぎていたら、来年の月日に変更
+   if( nowDate.getMonth() > nMonth || nowDate.getMonth() == nMonth && nowDate.getDate() > nDate ){
+       nYear +=  1;
+   }
    
    // 指定月日を「曜日 月 日 年 時 分 秒」に変換
    let n = new Date( nYear, nMonth, nDate );
    // nを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let nTarget = n.getTime();

    console.log(nYear);
    console.log(n);
    console.log(nTarget);
```
``` :実行結果
2024
Mon Jan 22 2024 00:00:00 GMT+0900 (日本標準時)
1705849200000
```

### もう一度、指定月日まであと何日か計算する
``` js:指定月日まであと何日か
    // 現在から指定月日まであと何ミリ秒か計算
    let diffDate = nTarget - now;

    // 上で求めたミリ秒を日に変換
    // 指定日までの日数 = 指定月日までのミリ秒 / ( 1000 * 60秒 * 60分 * 24時間 )
    let date = Math.floor( diffDate / ( 1000 * 60 * 60 * 24 ));

    console.log(diffDate);
    console.log(date);
```
``` :実行結果
2851200000
33
```

:::note info
これで正しい結果になった。
:::

## 指定月日になったかどうか判定
``` js
    // 現在から指定月日まであと何ミリ秒か再計算
    diffDate = nTarget - now;
    
    // 指定月日になった
    if( diffDate <= 0 ){
        msg = '指定月日だよ！';
    }
    // 指定月日ではない
    else{
        msg = '指定月日まで、あと' + date + '日だよ。';
    }

    console.log(msg);
```

``` :実行結果(指定月日前)
指定月日まで、あと33日だよ。
```

指定月日になったら以下の表示になる。

``` :実行結果(指定月日)
指定月日だよ！
```

## 1秒ごとに繰り返す
あと何秒かまで表示させる予定だったが、ここでは日までなので1秒毎にやる必要はないかも。

``` js
// 1秒毎に「countDown()」を実行
setInterval('countDown()', 1000);
```

# おまけ
## あと何日だけでなく、時間も表示する
ここまでは、`指定月日まで、あと何日か`を表示するプログラムを作ってきた。
さらに`あと何時間何分何秒`まで表示させるプログラムを考えてみた。

## 目指すもの
- 指定日時まで、`あと何時間何分何秒`か表示する。
指定日時からその日の`23時59分59秒`まで、`指定月日だよ！`と表示する。

## JavaScript
現在の日付を 2023年12月20日**12時34分56秒**、指定月日を2024年1月22日**0時0分0秒**とする。

<details><summary>ここからコピーしてね</summary>

``` js
// 表示させたい文字入れるため
let msg;

function countDown(){
    // 現在の「曜日 月 日 年 時 分 秒」を取得
    let nowDate = new Date();
    // 現在が西暦何年か取得 (This Year)
    let tYear = nowDate.getFullYear();
    // 現在が何月か取得 (This Month)
    let tMonth = nowDate.getMonth();
    // 現在が何日か取得 (This Date)
    let tDate = nowDate.getDate();

    // nowDateを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let now = new Date(tYear, tMonth, tDate).getTime();

    // 指定月日の年を指定
    let nYear = tYear;
    // 指定月日の月を指定
    let nMonth = 1 - 1;
    // 指定月日の日を指定
    let nDate = 22;
    // 指定月日の時間を指定
    let nHours = 0;
    // 指定月日の分を指定
    let nMinutes = 0;
    // 指定月日の秒を指定
    let nSeconds = 0;

    // 指定月日がすでに過ぎていたら、来年の月日に変更
    if( nowDate.getMonth() > nMonth || nowDate.getMonth() == nMonth && nowDate.getDate() > nDate ){
        nYear += 1;
    }

    // 指定月日を「曜日 月 日 年 時 分 秒」に変換
    let n = new Date( nYear, nMonth, nDate, nHours, nMinutes, nSeconds );
    // nを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let nTarget = n.getTime();

    // 現在から指定月日まであと何ミリ秒か計算
    let diffDate = nTarget - now;

    // 指定月日まであと何日か計算
    let date = Math.floor( diffDate / ( 1000 * 60 * 60 * 24 ));
    diffDate = diffDate % ( 1000 * 60 * 60 * 24 );
   
    // 指定月日まであと何時間か計算
    let hours = Math.floor( diffDate / ( 1000 * 60 * 60 ));
    diffDate = diffDate % ( 1000 * 60 * 60 );

    // 指定月日まであと何分か計算
    let minutes = Math.floor( diffDate / ( 1000 * 60 ));
    diffDate = diffDate % ( 1000 * 60 );

    //指定月日まであと何秒か計算
    let seconds = Math.floor( diffDate / ( 1000 ));

    // 現在から指定月日まであと何ミリ秒か再計算
    diffDate = nTarget - now;

    // 指定月日になった
    if( diffDate <= 0 ){
        msg = '指定月日だよ！';
    }
    // 指定月日ではない
    else{
        msg = '指定月日まで、あと' + date + '日' + hours + '時間' + minutes + '分' + seconds + '秒だよ。';
    }

    // メッセージを表示
    console.log(msg);
}

// 1秒毎に「countDown()」を実行
setInterval('countDown()', 1000);
```
</details>

``` diff_javascript:追加部分
// 表示させたい文字入れるため
let msg;

function countDown(){
+    // 現在の「曜日 月 日 年 時 分 秒」を取得
+    let nowDate = new Date();
+    // nowDateを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
+    let now = nowDate.getTime();
+    // 現在が西暦何年か取得 (This Year)
+    let tYear = nowDate.getFullYear();

    // 指定月日の年を指定
    let nYear = tYear;
    // 指定月日の月を指定
    let nMonth = 1 - 1;
    // 指定月日の日を指定
    let nDate = 22;
+   // 指定月日の時間を指定
+   let nHours = 0;
+   // 指定月日の分を指定
+   let nMinutes = 0;
+   // 指定月日の秒を指定
+   let nSeconds = 0;

    // 指定月日がすでに過ぎていたら、来年の月日に変更
    if( nowDate.getMonth() > nMonth || nowDate.getMonth() == nMonth && nowDate.getDate() > nDate ){
        nYear += 1;
    }

    // 指定月日を「曜日 月 日 年 時 分 秒」に変換
+   let n = new Date( nYear, nMonth, nDate, nHours, nMinutes, nSeconds );
    // nを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let nTarget = n.getTime();

    // 現在から指定月日まであと何ミリ秒か計算
    let diffDate = nTarget - now;

    // 指定月日まであと何日か計算
    let date = Math.floor( diffDate / ( 1000 * 60 * 60 * 24 ));
+   diffDate = diffDate % ( 1000 * 60 * 60 * 24 );
   
+   // 指定月日まであと何時間か計算
+   let hours = Math.floor( diffDate / ( 1000 * 60 * 60 ));
+   diffDate = diffDate % ( 1000 * 60 * 60 );

+   // 指定月日まであと何分か計算
+   let minutes = Math.floor( diffDate / ( 1000 * 60 ));
+   diffDate = diffDate % ( 1000 * 60 );

+   //指定月日まであと何秒か計算
+   let seconds = Math.floor( diffDate / ( 1000 ));

+   // 現在から指定月日まであと何ミリ秒か再計算
+   diffDate = nTarget - now;

    // 指定月日になった
+   if( diffDate <= 0 ){
        msg = '指定月日だよ！';
    }
    // 指定月日ではない
    else{
        msg = '指定月日まで、あと' + date + '日' + hours + '時間' + minutes + '分' + seconds + '秒だよ。';
    }

    // メッセージを表示
    console.log(msg);
}

// 1秒毎に「countDown()」を実行
setInterval('countDown()', 1000);
```

## 簡単な解説
### 指定日時の設定
先程も書いたように、現在を 2023年12月20日**12時34分56秒**、指定日時を2024年1月22日**0時0分0秒**とする。
``` js
    // 指定月日の年を指定
    let nYear = tYear;
    // 指定月日の月を指定
    let nMonth = 1 - 1;
    // 指定月日の日を指定
    let nDate = 22;
    // 指定月日の時間を指定
    let nHours = 0;
    // 指定月日の分を指定
    let nMinutes = 0;
    // 指定月日の秒を指定
    let nSeconds = 0;

    // 指定月日がすでに過ぎていたら、来年の月日に変更
    if( nowDate.getMonth() > nMonth || nowDate.getMonth() == nMonth && nowDate.getDate() > nDate ){
        nYear += 1;
    }

    // 指定月日を「曜日 月 日 年 時 分 秒」に変換
    let n = new Date( nYear, nMonth, nDate, nHours, nMinutes, nSeconds );
    // nを「1970年1月1日00時00分00秒」から何ミリ秒経過したかに変換
    let nTarget = n.getTime();

    console.log(nYear);
    console.log(n);
    console.log(nTarget);
```
``` :実行結果
2024
Mon Jan 22 2024 00:00:00 GMT+0900 (日本標準時)
1705849200000
```

### 指定日時まであと何日何時間何分何秒か計算
指定日時から現在の時間を引いて、指定日時まであと何ミリ秒か求める。

上で求めたミリ秒を下の順で計算し、日・時間・分・秒に変換する。
- ミリ秒 / 1000ミリ秒 → 秒 * 60秒 → 分 * 60分 → 時間 * 24時間 → **日**
- ミリ秒 / 1000ミリ秒 → 秒 * 60秒 → 分 * 60分 → **時間**
- ミリ秒 / 1000ミリ秒 → 秒 * 60秒 → **分**
- ミリ秒 / 1000ミリ秒 → **秒**

``` js
    // 現在から指定月日まであと何ミリ秒か計算
    let diffDate = nTarget - now;

    // 指定月日まであと何日か計算
    let date = Math.floor( diffDate / ( 1000 * 60 * 60 * 24 ));
    diffDate = diffDate % ( 1000 * 60 * 60 * 24 );
   
    // 指定月日まであと何時間か計算
    let hours = Math.floor( diffDate / ( 1000 * 60 * 60 ));
    diffDate = diffDate % ( 1000 * 60 * 60 );

    // 指定月日まであと何分か計算
    let minutes = Math.floor( diffDate / ( 1000 * 60 ));
    diffDate = diffDate % ( 1000 * 60 );

    //指定月日まであと何秒か計算
    let seconds = Math.floor( diffDate / ( 1000 ));

    console.log(diffDate);
    console.log(date);
    console.log(hours);
    console.log(minutes);
    console.log(seconds);
```
実行結果は、上から指定日時までの
- ミリ秒(現在から指定日時までの合計)
- 日
- 時間
- 分
- 秒
``` :実行結果
2805904000
32
11
25
4
```

### 指定日時になったか判定
``` js
    // 現在から指定月日まであと何ミリ秒か再計算
    diffDate = nTarget - now;
    
    // 指定月日になった
    if( diffDate <= 0 ){
        msg = '指定月日だよ！';
    }
    // 指定月日ではない
    else{
        msg = '指定月日まで、あと' + date + '日' + hours + '時間' + minutes + '分' + seconds + '秒だよ。';
    }

    // メッセージを表示
    console.log(msg);
```
``` :実行結果(指定日時前)
指定月日まで、あと32日11時間25分4秒だよ。
```
``` :実行結果(指定日時)
指定月日だよ！
```


## 日付の使い方
### `現在の日付の取得`

``` js
// 引数指定なし
let nowDate1 = new Date();
// 文字列で指定
let nowDate2 = new Date( '2024/1/1 ' );
// 年月日時分の順番に数値を入れる 月の指定に注意！(-1する)
let nowDate3 = new Date( 2023, 0, 1 );
// 1970年1月1日00時00分00秒から経過したミリ秒で指定
let nowDate4 = new Date( 1704034800000 );

console.log(nowDate1);
console.log(nowDate2);
console.log(nowDate3);
console.log(nowDate4);
```

``` :実行結果
Mon Jan 01 2024 00:00:00 GMT+0900 (日本標準時)
Mon Jan 01 2024 00:00:00 GMT+0900 (日本標準時)
Mon Jan 01 2024 00:00:00 GMT+0900 (日本標準時)
Mon Jan 01 2024 00:00:00 GMT+0900 (日本標準時)
```

### `日付データの個別取得`
年・月・日・曜日・時・分・秒を個別に取得できる。

| メソッド | 説明 |
| :----: | :----: |
| getFullYear() | 年を4桁で取得 |
| getMonth() | 月を0~11で取得 |
| getDate() | 日を1~31で取得 |
| getHours() | 時を0~23で取得 |
| getMinutes() | 分を0~59で取得 |
| getSeconds() | 秒を0~59で取得 |

:::note warn
月を取得する`getMonth()`は、注意が必要。
:::

下のように`1月`は`0`、`2月`は`1`…となる。
取得時には、`+1`する必要がある。

| 返値 | 実際の月 |
| :----: | :----: |
| 0 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| 5 | 6 |
| 6 | 7 |
| 7 | 8 |
| 8 | 9 |
| 9 | 10 |
| 11 | 12 |

# 最後に
全部パクってください。

## 参考
[【JavaScript】日付(Dateオブジェクト)の使い方を全てまとめる](https://qiita.com/mzmz__02/items/2ab307746aad16952278)