[React] 학습 - day3

jiseong·2021년 9월 18일
0

T I Learned

목록 보기
75/291

달력 만들기

중요 !!!
new Date().getMonth()는 0부터 시작하기 때문에 주의해야 한다.

윤년 체크

4로 나누어 떨어지는 해는 윤년
4로 나눠 떨어지지만 100으로도 나누어 떨어지는 해는 평년
4로 나눠 떨어지지만 100으로도 나누어 떨어지고 400으로 나누어 떨어지는 해는 윤년

const isLeapYear = year => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;

console.log(isLeapYear(2016)); // true
console.log(isLeapYear(2100)); // false
console.log(isLeapYear(2400)); // true

월의 첫째 날에 해당하는 요일, 마지막 날

해당 하는 월의 첫 번째 요일을 알기 위해서는 new Date(year, month - 1, 1)로 설정하여 해당 월의 1일을 만든 후 getDay() 메서드를 이용하면 첫 번째 해당하는 요일을 알 수 있다.

마지막 날은 new Date(year, month, 0)을 하면... (윤달을 계산 할 필요가 없다.) 마지막에 해당하는 날짜를 알 수 있다.

여기서 주의할 점은 new Date에 month를 이용할 땐 0 ~ 11 값을 이용해야하고 눈에 보이는 값은 1 ~ 12로 해야한다.
그렇다면 new Date(2021, 12, 0)에서 문제가 생기지 않을까? 라는 생각이 들었는데 month자리에 11이상 값이 들어가면 다시 0부터 시작하여 1월이 나오지만 day 자리를 0으로 설정했기 때문에 12월이 나오게 된다.

const getFirstDay = (year, month) => new Date(year, month - 1, 1).getDay();
const getLastDate = (year, month) => new Date(year, month, 0).getDate();

const year = date.getFullYear();
const month = date.getMonth() + 1;

const firstDay = getFirstDay(year, month);
const lastDate = getLastDate(year, month);
const arr = Array.from(new Array(lastDate), (x, i) => i + 1);

console.log(firstDay);
console.log(arr);

2021년 9월 기준 1일은 수요일부터 시작하며 마지막 날짜는 30일에 해당한다.

하지만 여기서 끝내버리면 달력 UI관련 컴포넌트에서 앞에 몇칸을 건너 띄우고 1일부터 시작할지를 모르기 때문에 unshift() 메서드를 이용하여 firstDay 길이만큼 배열의 앞쪽에 공백을 넣어준다.

arr.unshift(...new Array(firstDay));

이제 이걸 UI관련 컴포넌트에 뿌려주면 다음과 같이 나타낼 수 있다.

좌우 버튼 클릭 시 날짜 이동

우선, 버튼 클릭에 따라 리렌더링해주기 위해 state로 관리해야 한다.

const [moveMonth, setMoveMonth] = useState(0);

const setMonth = type => {
  if (type === 'left') setMoveMonth(moveMonth - 1);
  else if (type === 'right') setMoveMonth(moveMonth + 1);
};

그 후, 해당 setMonth 함수를 하위 컴포넌트에 넘기고 하위 컴포넌트에서 클릭 시 해당 state를 변경하여 달을 바꿀 수 있었다.

이전 날짜 체크

new date(year-month-day)양식으로 new date에 넣어주면 0시 0분 0초로 되어 년 월 날을 기준으로 비교할 수 있다.

const date1 = new Date('2021-09-18');
const date2 = new Date('2021-09-17');

console.log(date1 > date2); // true

해당 코드에서 적용하기 위해 첫날부터 마지막날짜까지 사이의 값을 배열로 만들어주는 곳에서 날짜를 비교하여 객체형식으로 만들어줬다.

const isBeforeDay = (year, month, day) => {
  const padding = value => `00${value}`.slice(-2);

  const currentDay = new Date(
    `${today.getFullYear()}-${padding(today.getMonth() + 1)}-${padding(today.getDate())}`,
  );

  const checkDay = new Date(`${year}-${padding(month)}-${padding(day)}`);

  return currentDay > checkDay;
};


const arr = Array.from(new Array(lastDate), (x, i) => {
      const day = i + 1;

      return {
        day,
        beforeDay: isBeforeDay(year, month, day),
      };
});

💻 최종 코드

function CalendarContainer() {
  const [moveMonth, setMoveMonth] = useState(0);
  const today = new Date();
  const leftDate = new Date(today.getFullYear(), today.getMonth() + moveMonth, 1);
  const nextDate = new Date(leftDate.getFullYear(), leftDate.getMonth() + 1, 1);

  const setMonth = type => {
    if (type === 'left') setMoveMonth(moveMonth - 1);
    else if (type === 'right') setMoveMonth(moveMonth + 1);
  };

  const getFirstDay = (year, month) => new Date(year, month - 1, 1).getDay();
  const getLastDate = (year, month) => new Date(year, month, 0).getDate();

  const isBeforeDay = (year, month, day) => {
    const padding = value => `00${value}`.slice(-2);

    const currentDay = new Date(
      `${today.getFullYear()}-${padding(today.getMonth() + 1)}-${padding(today.getDate())}`,
    );

    const checkDay = new Date(`${year}-${padding(month)}-${padding(day)}`);

    return currentDay > checkDay;
  };

  const getMonthData = date => {
    const year = date.getFullYear();
    const month = date.getMonth() + 1;

    const firstDay = getFirstDay(year, month);
    const lastDate = getLastDate(year, month);

    const arr = Array.from(new Array(lastDate), (x, i) => {
      const day = i + 1;

      return {
        day,
        beforeDay: isBeforeDay(year, month, day),
      };
    });
    arr.unshift(...new Array(firstDay));

    return { year, month, firstDay, lastDate, arr };
  };

  const leftMonth = getMonthData(leftDate);
  const rightMonth = getMonthData(nextDate);

  return <Calendar leftMonth={leftMonth} rightMonth={rightMonth} setMonth={setMonth} />;
}

🔖 demo

0개의 댓글