Google Calender를 보게 되면 달력이 있고 월을 선택할 수 있으며 선택한 월에 대한 달력이 표시된다. 이것을 구현해 보기로 하였다.
첫째 주에서 1일이 무슨 요일인지 알아야 한다. 위에 이미지에서는 1일이 금요일이다. 즉 1일 => 금요일 (5)를 얻는 함수를 구현해보자
달력을 구하는 알고리즘 중 처음으로 시작하는 로직이다. year, month는 state변수로써 인자로 입력을 받는다. 그리고 Date객체를 만들어야 하는데 month가 10보다 작으면 0을 붙혀준다. 왜냐하면 "yyyy-mm-dd'형식으로 맞춰야 정상적으로 Date객체를 생성하기 때문이다.
ex) 1 => 01, ... 9 => 09
그리고 원하는 것은 1일 이고 이것도 dd형식으로 써야하기 때문에 01로 하였다.
ex) 2023-09-01
이제 getDay()를 하게 되면 해당 요일에 맞는 숫자를 리턴해준다.
ex) 일요일 => 0, 월요일 => 1 ...
2월달에는 윤년이라는 게 존재한다. 윤년일 때에는 29일이 된다. 이 조건을 체크하는 함수를 구현해보자
윤년 조건식은 검색하면 쉽게 찾을 수 있었다.
앞서 구현한 함수들을 통해 변수를 초기화 하자
month_day는 월에 맞는 요일 수이다.
윤년체크를 통해 윤년이면 2월달 요일 수를 29로 맞춰준다.
first_day_of_week는 1일이 무슨 요일인지 나타내는 숫자가 담겨져 있다.
빈 공백을 넣자
위에 이미지를 보게 되면 1일 이전에 3개의 날짜 (29, 30, 31)가 있는 것을 볼 수 있다. 본 프로젝트에서는 이전 날짜를 출력하는 것이 아니라 공백을 출력하도록 할 것이다.
드디어 first_day_of_week 변수를 쓸 차례이다.!!! first_day_of_week은 첫째 날 몇 번째 요일인지 숫자가 담겨져 있다고 알고 있다.
만약 first_day_of_week = 3(수요일)이라고 가정해보자.
빈 공백은 일, 월, 화 이렇게 3개만 넣으면 될 것이다. 그 이유는 일요일 부터 시작하기 때문이다. 일요일은 0이고 수요일은 3이니 0,1,2만 넣으면 되는 것이 아닌가?
그리고 해당 월에 맞는 요일을 arr_calendar에 넣자.
결국 최종결과는 다음과 같다. (2023년 11월 기준)
=> ['', '', '', 1, 2, 3, 4, 5 ....., 29, 30]이 된다.
빈 공백을 마지막에 넣자
앞에서 빈공백을 넣은 것처럼 뒤에도 남는 자리에 빈 공백을 넣어야 할 것을 짐작했을 것이다.
물론 Date('yyyy-mm-마지막날')로 요일을 구할 수 있지만 수학적으로도 계산할 수 있다.
이전 로직에서 첫째 날 이전에 남는 요일을 공백으로 채웠다.
즉 첫째 주는 7로 나누어 떨어질 것이고 두번 째 주도 7로 나누어 떨어진 것이고 세번 째 주도 7로 나누어 떨어질 것이다.
마지막 주는 7로 나누어 떨어진 수만큼 채워질 것이다.
위에 이미지를 통해 이해해보자
5개의 주가 있는 것을 볼 수 있다. 첫째 주에는 빈 공백을 채웠으므로 나누어 떨어지고 마찬가지로 두번 째, 세번 째, 네 번째 주도 나누어 떨어질 것이다. 반면에 다섯 번째 주에는 7로 나눈 나머지가 채워질 것이다.
이것을 코드로 구현해보자
remain_day는 결국 빈 공백을 채워야 할 갯수가 들어갈 것이고 해당 갯수만큼 arr_calendar배열에 공백을 넣어주면 된다. 이렇게 하여 달력을 표현할 데이터는 준비가 된 것이다.
주 단위로 자르기
일자로 쭉 저장된 arr_calendar배열을 주 단위로 잘라 2차원 배열로 저장하자.
그 이유는 나중에 쉽게 렌더링 하기 위해서이다.
최종 코드
앞서서 주단위로 잘라 2차원 배열로 만들었다. 이중 map을 사용하여 렌더링 한 것이다. 추후에 이중 map과 클릭 css 효과에 대해 설명할 것이다.