datePicker & timePicker 직접 구현하기 - 2탄

D uuu·2024년 1월 9일
0

project

목록 보기
1/10

지난 1탄에 이어서

datePicker & timePicker 직접 구현하기 1탄 에 이어서 datePicker 와 timePicker 를 직접 구현해보기로 했다. 우선 기본적인 달력의 모습을 갖춘 다음에 필요한 기능들을 하나씩 추가할 것이다.


달력 기본 틀 잡기

우선 기본적인 달력 틀을 잡고 나서 필요한 기능을 하나씩 추가하기로 했다.
아래와 같은 모양의 달력을 구현하기 위해 어떻게 구성되어 있는지 하나씩 적어보았다.

🔸 달력의 header 부분에는 해당 년도와 월이 표시되어 있다.

🔸 요일을 표시하는 부분이 있다. (일요일 ~ 토요일)

🔸 행x열(7x6) 으로 총 42개 cell 로 되어있다.

🔸 매 월마다 마지막 날짜가 다르다. 1월은 31일까지있고, 2월은 28일 or 29일, 3월은 31일.... 이처럼 매 월마다 마지막 날짜가 다르다.

🔸 아래 2024년 1월 달력을 보면 2023년 12월 31일부터 2024년 2월 10일까지의 전 월과 다음 월의 날짜가 일부 포함되어 있다.

🔸 <<, >> 버튼을 클릭하면 이전 월과 다음 월로 넘어갈 수 있다.

🔸 오늘 날짜(8일) 를 표시해준다.


달력의 header 부분 만들기 (년, 월, 버튼)

  • CalendarHeader 라는 컴포넌트를 생성했다.

  • useState 를 사용해 현재 연도와 월을 초깃값으로 설정했다.

const [curYear, setCurYear] = useState(new Date().getFullYear())
const [curMonth, setCurMonth] = useState(new Date().getMonth())
  • React Icons 라는 라이브러리를 통해 버튼 아이콘을 가져왔다. 그리고 < 버튼을 누르면 이전 월로 이동, > 버튼을 누르면 다음 월로 이동하는 함수를 등록해준다.
  • < 버튼에 등록해놓은 이벤트 함수에 if 문을 사용해 curMonth === 0 이면, 즉 1월달이면 (curYear - 1) 를 해주고, 월은 12월달이 되도록 바꿔준다. 그 외에는 (curMonth - 1) 을 해서 이전 월로 이동하도록 코드를 작성했다.
const handlePrevButton = (e : React.MouseEvent) => {
    
    if(curMonth === 0 ) {
    	setCurYear(curYear - 1);
        setCurMonth(11);
    } else {
    	setCurMonth(curMonth - 1);
    }
 }
  • 마찬가지로 > 버튼에 등록해놓은 이벤트 함수에 if 문을 사용해 curMonth === 11 이면, 즉 12월달이면 (curYear + 1) 를 해주고, 월은 1월달이 되도록 바꿔준다. 그 외에는 (curMonth + 1) 을 해서 다음 월로 이동하도록 코드를 작성해준다.

  • 아래와 같이 기본적인 달력의 header 모습을 만들었다.




달력의 요일 표시하기

  • 달력의 요일을 나타내는 DayOfWeek 라는 간단한 컴포넌트를 만들었다.

  • <thead> , <tr>, <th> 태그를 사용해 요일을 나타내는 열을 만들어줬다.

const DayOfWeek = () => {
  return (
    <thead>
      <tr>
        <th></th>
        <th></th>
        <th></th>
        <th></th>
        <th></th>
        <th></th>
        <th></th>
      </tr>
    </thead>
  );
};

export default DayOfWeek;



행x열(7x6) 총 42개 cell 틀 잡기

이 부분에서는 어떻게 구현해야 할지 고민이 많이 필요했다. 우선, 매 월마다 마지막 날짜가 다르기 때문에 선택한 월의 마지막 날짜를 구한 다음, 1일부터 마지막 날짜가 될 때까지 1씩 더해주면 되겠다는 생각이 들었다. 이를 for문으로 표현하면 다음과 같다.

lastDate 는 해당 월의 마지막 날짜를 의미한다.
year, month 는 매개변수로 받아서 처리한다.

for(let i=1; i<= lastDate; i++) {
	console.log(new Date(year, month, i))
 }

이렇게 하면 한달에 해당 되는 날짜는 구현할 수 있지만, 행x열(7x6) 으로 총 42개의 cell 로 되어있어 이전 월과 다음 월의 날짜 일부가 포함되어야 한다.

예를들어 2024년 1월 달력을 보면, 2023년 12월 31일2024년 2월 1~10일까지의 날짜가 포함되어 있다.

즉, 날짜를 렌더링 하기 위해서는 12/31일 부터 날짜를 하나씩 더해주면 된다는 생각이 들었다.
그럼 어떻게 하면 처음 시작값(여기선 12/31일) 을 알 수 있을까 고민이 되었는데, 달력을 계속 들여다 보다가 규칙을 하나 발견했다. 해당 월의 1일에 해당 되는 요일만큼 뒤로 가면 시작값을 구할 수 있을 것 같았다.

예를들어 1/1일은 월요일이므로 getDay() 를 통해 요일을 구하면 1 이 나온다. 1/1 일에서 1만큼 뒤로 가면 즉, 하루 전은 12월31일이 된다!

2024년 2월 달력으로도 실험해보니, 2월 1일은 목요일로 getDay() 를 통해 숫자 4 를 얻었다. 2/1일에서 4일만큼 뒤로 가면 1월 28일이 나온다.
이런식으로 1일에 해당 되는 요일을 구하고 그 숫자만큼 날짜를 빼주면 된다는 규칙이 있었다.



Today I Learned 💡

1. toLocaleString() 메서드

  • Date.prototype.toLocaleString(locales, [options])

  • 날짜를 읽기 쉬운 문자열로 변환하는 메서드이다.

  • locale과 opitons 파라미터를 받는다.

  • 사용 예시

new Date().toLocaleString("en", {month : "short"})  /// "Jan"
new Date().toLocaleString("en", {month : "long"})  /// "January"
  • 현재는 한국어 버전으로만 달력을 만들 예정이지만, 나중에 영어 or 다른 언어가 추가 되면 이 옵션을 활용할 수 있을 것 같다.

2. new Date() 의 다양한 메서드

  • new Date().getDate() 는 날짜를 출력
new Date().getDate() ///  10  (오늘 날짜 2024-1-10)

  • new Date().getDay() 는 요일을 출력
new Date().getDay()  /// 3 (오늘 요일 수요일) 

❗매우 헷갈림❗ : 요일은 일요일을 시작으로 0 부터 시작해서 토요일 6 으로 끝난다.


  • new Date().getMonth() 는 월을 출력
new Date().getMonth()  /// 0 (현재 1월달)

❗매우 헷갈림❗ : 월은 1월을 0으로 시작해서 12월이 11로 끝난다.


  • new Date(year, month) 으로 day 를 생략할 경우 👉 해당 월의 1일을 반환한다.
new Date(2024,0) /// Mon Jan 01 2024 00:00:00 GMT+0900 (한국 표준시)
new Date(2024,1) /// Thu Feb 01 2024 00:00:00 GMT+0900 (한국 표준시)

  • new Date(year, month, -day) 으로 day 값을 음수로 줄 경우 👉 전 월을 -day 만큼 계산해서 반환한다.
new Date(2024,0,-2)  /// Fri Dec 29 2023 00:00:00 GMT+0900 (한국 표준시)
new Date(2024,1,-3)  /// Sun Jan 28 2024 00:00:00 GMT+0900 (한국 표준시)

❗주의할 점❗ : 일자에 0 을 포함하기 때문에 -2 인 경우, 0, -1, -2 즉 3을 빼는 것과 같다.

profile
배우고 느낀 걸 기록하는 공간

0개의 댓글

관련 채용 정보