Javascript 두 날짜 사이 날짜 - Javascript du naljja sai naljja

How Many Days Between Two Dates

그 날로부터 며칠이나 지났지?

100에서 40을 빼는 것은 쉽습니다. 그러나, 6월 17일로부터 40일 전의 날짜를 구하는 것은 시간이 조금 걸립니다. 각 달마다 일 수가 틀리기도 하고, 10진수가 익숙한 우리에게 30짜리 묶음을 기준으로 계산하는 것은 생각을 필요로 합니다. 이러한 불편함을 해소하기 위해, 유용한 Date 메서드를 사용하여 아주 간단한 함수를 만들어 봅시다.

예시

getDays(
  new Date("June 14, 2019"),
  new Date("June 20, 2019")
) ➞ 6

getDays(
  new Date("December 29, 2018"),
  new Date("January 1, 2019")
) ➞ 3
// 두 날짜가 항상 같은 연도나, 같은 월 안에 있지 않을 수도 있습니다.

getDays(
  new Date("July 20, 2019"),
  new Date("July 30, 2019")
) ➞ 10

문제 풀이

시도 1

첫 번째 아이디어는, 말 그대로 “날짜를 세자”였습니다.

각 달마다 일 수가 차이나는 것을 전부 코드로 작성하려고 했죠. 그러나 커다란 관문에 부딪히게 됩니다. 바로 2월인데요, 모든 달을 일 수로 구분하는 것도 굉장히 비효율적이지만 2월은 4년마다 일 수가 달라지는 아주 특수한 경우이기 때문에, 이것까지 코드로 포함하기에는 무리라는 판단을 내리게 되었습니다.

프로그래밍 코드는 컴퓨터를 위한 언어입니다. 우리는 다양한 예외 사항을 컴퓨터에게 알려주어야 합니다. 그러나 예외가 지나치게 많다면, 발상을 조금 바꿔 보는 것도 나쁘지 않습니다.

시도 2

Date.prototype.getTime() 메서드

인수로 받은 두 날짜의 연,월,일을 각각 저장한 후 일을 처리하는 것보다, 애초에 두 날짜의 차(差)를 먼저 구하고 이후 단위를 통일하는 것이 더 간편해 보이지 않나요?

전역 빌트인 객체 Date는 다양하고 유용한 메서드를 제공하며, 이 중 Date.prototype.getTime()메서드는 UTC를 기점으로 Date 객체의 시간까지 경과된 밀리초를 숫자 형태로 반환합니다. 두 날짜로부터 경과된 밀리초를 뺄셈 연산한 후 하루(밀리초 단위)로 나누어 봅시다.

function getDays(date1, date2) {
    return (date2.getTime()-date1.getTime()) / 86400000;
}

이를 화살표 함수로 간략하게 표현하면 다음과 같습니다.

const getDays = (date1, date2) => (date2.getTime()-date1.getTime()) / 86400000

타인의 코드

다른 해결법 1

function getDays(date1, date2) {
	return new Date(date2 - date1).getDate() - 1
}

추천 수 1위의 해결법이다. 인수로 받은 두 날짜를 뺀 값으로 Date 객체를 만들고, getDate()메서드로 Date 객체의 날짜(1~31)를 나타내는 정수를 얻은 후 1을 빼 줬다.

그러나 이 코드는 겉보기에는 아름답지만, 치명적인 결함이 있다. 바로 getDate()로 표현할 수 있는 일 수의 한계이다.

  • 같은 연도(2019)안의 6월 14일과 6월 20일은 4가 나온다.
getDays(
  new Date("June 14, 2019"),
  new Date("June 20, 2019")
) ➞ 6
  • 그러나, 2019년 6월 14일과 2020년 6월 20일 사이의 일 수는 예상한 값과 다르게 7이라는 엉뚱한 값이 나오게 된다.
getDays(
  new Date("June 14, 2019"),
  new Date("June 20, 2020")
) ➞ 7

단위가 일을 넘어서 월, 연까지 갈 경우 오직 일만 반환하는 getDate()로는 원하는 값을 정확하게 구할 수 없다.

다른 해결법 2

function getDays(date1, date2) {
	return Math.round(Math.abs(date1.getTime() - date2.getTime()) / (24 *60 * 60 * 1000))
}

연산 아이디어 자체는 동일한 해결법이지만, 특이하게도 Math.abs 메서드를 사용한 것이 돋보인다. 문제에는 “두 날짜 사이의 일 수”를 구하라고 했을 뿐, 어느 날짜가 앞서는지는 나와있지 않았다. Math.abs는 절댓값을 반환하기 때문에 date1와 date2 중 어느 날짜가 앞서더라도 음수가 아닌 양수가 반환된다. if문이나 삼항연산자를 통한 조건문을 대체할 수 있는 독특한 방법이다.

배운 것

getTime 메서드의 유용성

Date 객체의 밀리초를 반환한다는 것의 의미를 잘 이해하지 못했는데, 날짜 연산에 있어서 기준 역할을 해준다는 것을 알게 되었다. getTime 메서드로 보다 쉽게 두 날짜 사이의 일 수를 계산할 수 있었는데, 이를 이용하면 초,분,월 등 다양한 단위 계산에서 써먹을 수 있을 것 같다.

Date 객체끼리의 뺄셈이 가능하다

Date 객체는 오직 날짜를 보관하는 용도라고 생각했는데, Date 객체끼리도 연산이 가능하며 2022년 6월 20일에서 2022년 6월 11일을 빼면 9일이 나올수도 있다는(!) 사실을 배웠다. 생각보다 훨씬 유연했구나

Math.abs 로 조건문 대체하기

A와 B라는 매개변수에 각각 인수를 받아 뺄셈 연산을 할 때, “둘 중 어느 수가 더 큰가”는 중요한 이슈이며 이는 if문이나 삼항연산자를 통한 조건문으로 처리되는 것이 일반적이다. 이 때 Math.abs로 절댓값 처리를 해 버리면 동일한 값을 얻을 수 있다. 독특한 처리법이었다.

soso한 아재

시작 날짜와 종료 날짜의 차이, 두 날짜 사이의 일 수 계산하기 본문

JavaScript 실무

시작 날짜와 종료 날짜의 차이, 두 날짜 사이의 일 수 계산하기

잭다니엘 2018. 5. 18. 14:07

시작 날짜와 종료 날짜의 차이, 두 날짜 사이의 일 수 계산하기

안녕하세요. soso한 아재 잭다니엘 입니다. 간만에 javascript쪽 글을 올리는군요... 블로깅을 하다 보니 본래의 취지?를 자꾸 벗어나 이 글 저 글 막 올리게 되네요 -ㅅ-;; 에... 사실 아는게 별로 없어서 그렇습니다. ㅠ_ㅠ; 참 솔직한 녀석?이죠?? ㅋㅋ;; 10년차인데 아는게 별로 없습니다. ㅠㅠ;; 잡지식  잡경험만 겁나 쌓아 왔습니다.;; anyway, 시작 날짜가 있고, 종료 날짜가 있는 경우 7일 미만일 경우 경고문 띄워주어~라는 미션이 생겼을 때 구현 했던 내용의 일부 입니다.

모 예를 들어 달력이 있다고 칩시당... 시작 일자를 2018-05-18일이라 치고.. 종료 날짜를 2018-05-30를 선택했다고 가정해 보겠습니다. 이 두 날짜의 차이를 구하여서 7일이 넘으면 경고문을 띄워줄 것입니다. 먼저 두 날짜의 차이를 구할려면 종료일자에서 시작일을 빼줘야 - 가 되지 않습니다... 당연한 이야기겠지만 따라서 두 날짜의 차이를 구하기 위해 종료일자에서 시작일을 빼도록 하겠습니다.


var date1 = "2018-05-18";
var date2 = "2018-05-30";
// 날짜를 입력 받으면 위와 같이 입력 받게 되는게 일반적입니다.

date1 = date1.split('-');
date2 = date2.split('-');
// 각 날짜에서 "-" 를 빼 줍니다.

date1 = new Date(date1[0], date1[1], date1[2]);
date2 = new Date(date2[0], date2[1], date2[2]);
// 날짜 형식으로 변경해 줍니다.

var btMs = date2.getTime() - date1.getTime();
// 두 날짜간의 시간차를 구합니다. 종료일자에서 시작일을 빼줘야 합니다.

var btDay = btMs / (1000*3600*24);
// 날짜 구하는 공식입니다.

//btDay = 12
// 최종 날짜 차이는 12일이 되겠습니다.

if (btDay > 7){
  alert("일주일이 넘었어~~");
}


아래는 위 내용을 크롬 콘솔에서 실행해 본 이미지 입니다.

이상으로 마치겠습니다.