본문 바로가기
프론트엔드

[Javascript] 자바스크립트 Date 기간 조회하는 법 (+ 주의사항)

by BeforB 2021. 8. 12.
728x90

 

이번 포스팅에서는 자바스크립트 Date를 이용하여 기간을 조회하는 방법과, 자바스크립트 날짜 계산 시 주의할 점에 대해 발견하여 정리하고자 한다.

 

프로젝트를 그대로 가져올 수 없어서 간단하게 예제로 구현해보았다.

자바스크립트로 날짜 구간을 지정하고 해당 기간에 대한 결과를 조회하고자 한다.

아래와 같이 필터링이 일주일, 3개월, 6개월, 1년으로 지정되어 있고 각 버튼을 누르면 마감 날짜 기준으로 시작 날짜를 변경해주는 기능을 만들었다.

 

 

기본적으로 자바스크립트의 Date 객체는 setMonth(), setDate()를 이용하여 날짜를 직접 지정할 수 있는 기능을 제공하고, setMonth(월 + N) 과 같은 기능을 통해 날짜 계산이 가능하다.

let today = new Date()			// Sun Sep 19 2021 17:47:22 GMT+0900 (한국 표준시)
let newDay = new Date(today)		// Sun Sep 19 2021 17:47:22 GMT+0900 (한국 표준시)

// 1. 날짜 3일 더하기
newDay.setDate(today.getDate() + 3)	// Wed Sep 22 2021 17:47:22 GMT+0900 (한국 표준시)
// 2. 한 달 전으로 변경하기
newDay.setMonth(today.getMonth() - 1)	// Sun Aug 22 2021 17:47:22 GMT+0900 (한국 표준시)

 

 

주의할 점

 

하지만 이 계산법에는 문제점이 있다. setDate는 문제가 없지만, setMonth혹은 setYear를 사용할 경우 한 달이 30일까지인지, 31일까지인지, 28일까지인지를 전혀 고려하지 않고 정확하게 월/년 만 변경하기 때문이다.

 

예를 들어 8월 31일의 한 달 전은 7월 31일로 문제가 없다. 하지만 2달 전 이라면? 6월 30일이 출력될 것이라고 생각하지만 결과는 7월 1일이 나온다.

자바스크립트에서 8월 31일의 두 달 전은 6월 31일이고, 6월 31일은 없기 때문에 하루 넘어가 7월 1일로 계산되는 것이다. 마찬가지로 3월 31일의 한 달 전도 2월 28일이 아니라 2월 31일, 즉 3월 3일로 계산된다.

 

 

 

이 문제점을 해결하기 위해 setMonth(), setYear()를 이용할 경우는 기존 날짜와 새로운 날짜의 date가 다르면 새로운 날짜의 계산이 잘못되었다고 판단하고 해당 달의 마지막 날이 출력되도록 수정하였다. 그렇게 하고나니 어떤 날짜를 입력하더라도 계산이 정확하게 되는 것을 확인할 수 있다.

 

 

 

 

코드는 아래에 정리해두었다.

 

 

> HTML 코드(CSS 생략)

<body>
  <br/>
  <h3> 기간 조회하기 </h3>
  <br/><br/>
  시작 날짜 : <input class="datepicker" id="strtDate" /> <br/> <br/>
  종료 날짜 : <input class="datepicker" id="endDate" />
  <br/><br/><br/>
  <div>
    <button name="filterDate" value="1">일주일</button>
    <button name="filterDate" value="2">3개월</button>
    <button name="filterDate" value="3">6개월</button>
    <button name="filterDate" value="4">1년</button>
  </div>
 </body>

 

> Javascript

$(function() {
  $('.datepicker').datepicker({dateFormat: 'yy-mm-dd'});
})

// 날짜 포맷("yyyy-MM-dd") 형식으로 반환
dateFormatter = function(newDay, today) {
  let year = newDay.getFullYear()
  let month = newDay.getMonth()+1
  let date = newDay.getDate()

  // 기존 날짜와 새로운 날짜가 다를 경우 
  if(today) {
    let todayDate = today.getDate()

    if(date != todayDate) {
      if(month == 0) year-=1
      month = (month + 11) % 12
      date = new Date(year, month, 0).getDate()	// 해당 달의 마지막 날짜를 반환
    }
  }

  month = ("0"+month).slice(-2)
  date = ("0"+date).slice(-2)

  return year+"-"+month+"-"+date
}

document.getElementsByName("filterDate").forEach(e=> {
  e.addEventListener('click', function() {  
	
  let endDate = new Date($("#endDate").val())let newDate = new Date($("#endDate").val())

  switch(this.value) {
      case '1':
        console.log("일주일")
        newDate.setDate(newDate.getDate() - 7)
        newDate = dateFormatter(newDate)
        break;
      case '2':
        newDate.setMonth(newDate.getMonth() - 3)
        newDate = dateFormatter(newDate, endDate)
        console.log("3개월")
        break;
      case '3':
        newDate.setMonth(newDate.getMonth() - 6)
        newDate = dateFormatter(newDate, endDate)
        console.log("6개월")
        break;
      case '4':
        newDate.setFullYear(newDate.getFullYear() - 1)
        newDate = dateFormatter(newDate, endDate)
        console.log("1년")
        break;
  }
  $("#strtDate").val(newDate)
    
  })
})

 

 

 

 

 

 

728x90

댓글