[JavaScript] 得到某年某月的天數

這是 JavaScript 的一個作業的一部份,我把他拆成三個部份寫。這個部份是要在選擇某年某月之後,可以知道該月共有幾天,頁面操作上是有年的<select>標籤,選了年份後出現月的<select>標籤,選了月份後會出現日的<select>,而且日期的<option>必須符合該年該月,例如 2017 年 2 月有 28 天,最後一個的<option>就要 1 到 28:

這是 HTML 的樣子,其實三個<select>都在,只是月和日是隱藏的,在選擇年或月時才會顯示下一個:

<select id="seleYear">
</select>
<select id="seleMonth" style="visibility: hidden;">
</select>
<select id="seleDate" style="visibility: hidden;">
</select>

會用到 JavaScript 的 Date 物件,在上一篇 [JavaScript] 檢驗輸入日期是否真實存在 有筆記,下面快速介紹一次這次會用到的部份:

JavaScript 的 Date 物件

建構函式 new Date(Year, Month, Day):用年月日可建構代表該日期的物件,要注意 Month 是0 到 11,一月的 Month = 0,二月的 Month = 1,.... ,十二月的 Month = 11,所以 new Date( 2022, 1, 10 ) 會得到 2022 年 2 月 10 日的物件。

.getDate():回傳 Date 物件的日期,1日 = 1,2日 = 2,.... ,31日 = 31

上一篇有提到 Date 物件的推移情形,除了上一篇用來判斷日期是否存在,還可用來尋找當月的天數,因為月也可以推移,如果月 +1 會得下個月,而且跨年的情形也確實反映:

  • new Date( 1985, 11, 18 ) 得 1985 年 12 月 18 日的物件
  • new Date( 1985, 12, 18 ) 得 1986 年 1 月 18 日的物件
  • new Date( 1985, 12, 1 ) 得 1986 年 1 月 1 日的物件
  • new Date( 1985, 12, 0 ) 得 1985 年 12 月 31 日的物件

找出當年當月的天數

其實作法就是上面的兩張圖,利用月份 +1 得到下個月,將日期設為 1 則為下個月的第一天,日期設為 0 就回到這個月的最後一天,用.getDate() 就能取得這個月的總天數,其實還蠻容易的,下面把上述點選<select>標籤的程式碼貼一下:

var domYear = document.getElementById('seleYear');    // 取<select>標籤的DOM元素
var domMonth = document.getElementById('seleMonth');
var domDate = document.getElementById('seleDate');

domYear.addEventListener('change', generateMonth);    // 註冊年與月的change事件
domMonth.addEventListener('change', generateDate);

let docFrag = document.createDocumentFragment();     // 初始化填入<select>年份
let yearTitle = document.createElement('option');
yearTitle.setAttribute('value', 0);
yearTitle.textContent = '年';
docFrag.appendChild(yearTitle);

for (let i = 2010; i <= 2025; i++) {        // 作業要求可以選擇 2010 年到 2025 年
  let yearOption = document.createElement('option');
  yearOption.setAttribute('value', i);
  yearOption.textContent = i;
  docFrag.appendChild(yearOption);
}
domYear.appendChild(docFrag);

docFrag = document.createDocumentFragment();        // 初始化填入<select>月份
let monthTitle = document.createElement('option');
monthTitle.setAttribute('value', 0);
monthTitle.textContent = '月';
docFrag.appendChild(monthTitle);

for (let i = 1; i <= 12; i++) {                  // 月份可選擇 1 月到 12 月
  let monthOption = document.createElement('option');
  monthOption.setAttribute('value', i);
  monthOption.textContent = i;
  docFrag.appendChild(monthOption);
}
domMonth.appendChild(docFrag);

function generateMonth() {       // 年份<select>值改變時觸發
  if (domYear.value == 0) {
    return;
  }
  domDate.style.visibility = 'hidden';     // 隱藏日期<select>
  domMonth.style.visibility = 'visible';   // 顥示月份<select>
}
function generateDate() {        // 月份<select>值改變時觸發
  if (domMonth.value == 0) {
    return;
  }
  let selectY = domYear.value;
  let selectM = domMonth.value - 1;           // select 選到的月份要 -1 才是 date 物件裡的月
  let totalDate = new Date(selectY, selectM + 1, 0).getDate();      // +1推下一個月,日期0則退1天,得到當月最後一天

  domDate.style.visibility = 'visible';
  domDate.innerHTML = '';

  let docFrag = document.createDocumentFragment();
  let dateTitle = document.createElement('option');
  dateTitle.setAttribute('value', 0);
  dateTitle.textContent = '日';
  docFrag.appendChild(dateTitle);

  for (let i = 1; i <= totalDate; i++) {     // 產生 1 到 totalDate 的<option>
    let dateOption = document.createElement('option');
    dateOption.setAttribute('value', i);
    dateOption.textContent = i;
    docFrag.appendChild(dateOption);
  }
  domDate.appendChild(docFrag);
}

留言