#1. 날짜 선택 구현하기

웹에서 사용자가 날짜를 선택 해야하는 일이 종종 있다.

예를들어 예약시스템의 경우가 대표적일 것이다.

구현 방법은 매우 간단하다.

<input type="date" />

작성일 기준 9월 25일

<input> 태그의 타입을 date로 지정해주기만 하면 된다.

하지만 이렇게만 구현해 놓으면 문제가 하나 있는데, 그것은 사용자가 지난 날짜를 선택해서 예약할 수 있다는 것이다.

물론 지난 날짜를 선택하면 예약이 안되게 따로 구현하는 것도 방법이지만,

아예 선택할 때 부터 지난 날짜는 선택하지 못하게 막아버리면 더 괜찮지 않을까 하는 생각으로 구현해보았다.

그럼 어떻게 구현해야할까?

 

1. 최소날짜 지정

<input type="date" min={"yyyy-mm-dd"} />
  • date 타입에 사용 가능한 속성중에 min이라는 속성이 있는데, 이 속성에 문자열로 날짜를 지정하면 그 날짜를 기준으로 지난 날짜들은 disabled 처리가 되어 선택할 수 없다. (ex "2022-09-25")
  • 값은 반드시 "yyyy-mm-dd" 형식이여야 적용된다. (2022-9-25로 값을 넣으면 적용안됨)

 

2. 날짜 구하는 함수 생성

/** 
 * @discription 내일 날짜 구하는 함수
 * @return yyyy-mm-dd 
 */
const tomorrow = () => {
  // date 객체 생성
  const date = new Date();
  // date 객체에서 현재 년도를 구한다
  const year = date.getFullYear();
  // date 객체에서 현재 월을 구한다 (getMonth는 0부터 시작하기 때문에 +1을 해준다)
  let month = date.getMonth() + 1;
  // date 객체에서 오늘 날짜를 구한다
  const today = date.getDate();
  // 오늘 날짜에 +1을 하여 내일 날짜를 구한다
  let tomorrow = today + 1;
  
  // "yyyy-mm-dd" 형식으로 값을 전달 해야하기 때문에 삼항연산자를 활용해 10보다 작을 경우 앞에 0을 붙인다
  return `${year}-` + (month > 9 ? `${month}-` : `0${month}-`) + (tomorrow > 9 ? tomorrow : `0${tomorrow}`);
};

export { tomorrow };
  • 보통 당일 예약을 허용하는 시스템이 아니고서는 내일부터 예약 가능하게 구현한다. (당일 예약을 허용하려면 return문에 tomorrow 대신에 today 변수를 대입하면 된다.)
  • 위에서 언급했듯이 min속성에 값을 넣을 때는 "yyyy-mm-dd" 형식으로 넣어야 한다.
    • Date 객체에서 얻은 날짜는 10 이하일 경우 한자리 수로 나타낸다.(예를들어 22년 9월 2일이면 2022-9-2 이런식으로 나온다)
    • 그렇기 때문에 "yyyy-mm-dd"형식을 맞추기 위해 삼항연산자를 활용해 10보다 작을 경우 앞에 0을 붙여준다.

 

3. 마지막 날에 대한 대비

위 방법대로 하면 이론상으로는 문제가 없었다. (내 머리의 한계인듯)

하지만 문제가 하나 있었는데, 해당 월의 마지막 날 인데도 다음달로 넘기지 않고 없는 날짜가 지정 되어버린 것이다.

예를들어 오늘 날짜가 2022-08-31이면 2022-09-01로 넘어가지 않고 2022-08-32가 되어버린 것이다..(32일은 없어요...)

해결 방법을 고민하다가 해당 월의 마지막 날을 구해 오늘 날짜와 같다면 month와 tomorrow를 직접 변경하는 방식으로 해결해보았다. (month 와 tomorrow만 let으로 선언한 이유)

/** 해당 월의 마지막 날이면? */

// Date객체에서 마지막 날을 구해 오늘 날짜와 같은지 비교한다
if(new Date(year, month, 0).getDate() === today) {
  // 다음달로 넘기기 위해 +2를 한다 (month는 0부터 시작하기 때문에 이번달을 구할 땐 +1, 다음달은 +2)
  month = date.getMonth() + 2;
  // 오늘날짜 - (오늘날짜 -1)을 한 날짜로 변경 (31일 이면 30을 빼 1이 남도록 한다, 월의 1일)
  tomorrow = date.getDate() - (date.getDate() - 1);
}

// return문 위에 작성된 코드를 따로 발췌
  • new Date(년, 월, 0)을 통해 해당 월의 마지막 날을 구할 수 있다. (마지막에 0을 생략하면 1일이 출력)
// 2100년 2월의 마지막 날 구하기
console.log(new Date(2100, 2, 0));

2100년 2월의 마지막 날은 28일이다

  • 여기서 getDate()를 사용해 마지막 날짜만 추출해 오늘 날짜와 같다면 if문을 실행해 month와 tomorrow 값을 바꿔준다.

 

4. 함수적용

import { tomorrow } from '../경로';

<input type="date" min={tomorrow() || ''} />
  • min 속성에 위에 작성한 내일 날짜를 구하는 함수를 적용한다.
  • 함수에서 값을 제대로 전달받지 못할 때를 대비해서 오류가 나지 않도록 함수 또는 빈문자열을 받게 지정

 

구현결과

작성일 25일을 기준으로 지난 날짜와 해당 날짜는 선택이 안되고 내일 날짜부터 선택할 수 있는 것을 볼 수 있다.

+ Recent posts