본문 바로가기

모바일 개발/React Native-이론

캘린더 앱 클론코딩(2) - 달력 내부 날짜 데이터 만들기

<들어가며>

달력 내부에는 다음과 같이 날짜가 있어야 한다. 

우리는 이번 4월달의 날짜 데이터를 만들 것이다. 

위에서 보면 알 수 있듯이, 달력에는 해당 월의 날짜 뿐만 아니라, 빈 공간을 채우는 전월, 내월의 날짜가 조금씩 들어가 있다. 이 부분도 얼마나 필요한지 계산 해내어서 데이터에 추가할 것이다. 

 

1. getCanlendarColumns

// 딴 파일에서 import될 최종본
// now를 선언하지 않았는데 왜 돌아갈까? 
// now를 선언하지 않은 것이 맞다. 근데 그냥 dayjs()에 파라미터 안 넣은 경우, dayjs()는 최신 날짜를 반환한다.
// 이걸 이용한 것이다. 그냥 now 다 지워버려도 동작한다.
export const getCalendarColumns = (now) => { // now는 무조건 현재 시각이 들어감. 
  const start = dayjs(now).startOf("month"); // 11.1
  const end = dayjs(now).endOf("month");     // 11.30
  const endDate = dayjs(end).get("date");    // end는 위에서 나온 걸로 11월 30일이 들어갔고 여기서 우리는 30만 쓴다. -> 달의 length 

  const columns = [];
  for (let i = 0; i < endDate; i += 1) {
    const date = dayjs(start).add(i, "day"); // start날짜에서 일 단위로 i만큼 더한다. 11월 1일에서 11월 (i+1)일로 
    columns.push(date); // 해당 값을 배열에 넣는다. 
  }
  
  const filledColumns = fillEmptyColumns(columns, start, end);

  return filledColumns;
};

2.fillEmptyColumns 

import dayjs from "dayjs";

// 달력에 빈 부분은 전원이나 내월의 날짜를 조금씩  포함한다. 
// 그걸 나타내주기 위한 함수, 딱 해당 월 날짜만 받아서, 시작 날짜, 끝 날짜로 앞 뒤 채워줌 
export const fillEmptyColumns = (columns, start, end) => {
  const filledColumns = columns.slice(0); 
  // slice는 부분 복사인데 (시작 인자, 복사할 끝인자) 혹은 (시작인자)로 적는다. 이건 두 번째 경우로 처음부터 끝까지 복사해 넣겠다는 소리이다.

  // 1. 첫날 이전 공백 채우기
  const startDay = dayjs(start).get("day"); // 시작 날짜의 요일만큼 뒷 공백이 필요함 일: 0~ 토: 6으로 day.js가 계산함을 잊지 말자 
  for (let i = 1; i <= startDay; i += 1) {
    const date = dayjs(start).subtract(i, "day");
    filledColumns.unshift(date);
  }
  // ["10.30","10.31","11.1",... "11.31"]

  // 2. 마지막날 이후 공백 채우기
  const endDay = dayjs(end).get("day");
  /**
    0 -> 6 // 마지막 날이 일요일이면 뒤로 6개를 채워야 한다.
    1 -> 5 // 마지막 날이 월요일이면 뒤로 5개를 채워야 한다.
    2 -> 4 // 마지막 날이 화요일이면 뒤로 4개를 채워야 한다.
    endDay + ? = 6
   */
  for (let i = 1; i <= 6 - endDay; i += 1) { // 마지막 날이 화요일이면, 맨 막줄이 일월화 3개 적히고 4칸 빈 거임 6-2(화요일의 숫자값)=4
    const date = dayjs(end).add(i, "day"); // end가 4.30일이면 다음 달로 넘어감 5.1, 5월 31일일 경우도 다음 달로 넘어감
    filledColumns.push(date);
  }

  return filledColumns;
};

 

** 잡다 지식 **

(1) unShift 함수 

[1,2,3].unshift(333);
// [333,1,2,3]

해당 함수로 배열 안에 넣으면, 배열의 젤 앞자리 index: 0번에 들어간다. 

만약 2개 이상의 인수를 넣었을 경우 그 순서 그대로 index 0번 부터 들어간다.

(2) [ ].push(0)

unshift랑 반대로 0이란 값을 맨 끝 index에 집어넣는다.

 

(3) [ ]. slice(A,B)

해당 배열의 A 값부터 B값 직전까지 잘라서 부분 배열을 만들어 반환한다. 

[ ].slice(A) 와 같이 하나의 인자만 적으면 A 값부터 맨 끝 배열 값까지 잘라서 부분 배열 만들어 반환한다. 

 

 

3. 스스로 해보기 

(1)

어떤 시간 변수에 format을 써버리면 해당 변수는 더 이상 dayjs () 로 묶어도 day.js의 함수를 쓸 수가 없다. 

const a = dayjs(start).get(date)
console.log(a)

 

a는 NaN (계산 할 수 없는 값)이 나온다.

 

(2) 

1번 getCalendarColumns에서 변수를 만들었으면 그걸 가져다 쓰자. 

난 지금 fillEmptyColumn 에서  달 첫일과 말일을 만드는 함수를 또 이용해서 변수를 만들어 코드가 중복됐다. 

 

import dayjs from "dayjs";
import isBetween from "dayjs";
import isSameOrBefore from "dayjs";
import isSameOrAfter from "dayjs";
dayjs.extend(isBetween);
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);

export const getCalendarColumns = (now) => {
    const start = dayjs(now).startOf("month");
    const end = dayjs(now).endOf("Month");
    const monthLength = dayjs(end).get("date");

    let columns = [];

    for(i=0 ; i < monthLength; i +=1) {

      columns[i] = i+1; 
    }

    const filledColumn = fillEmptyColumn(columns, now)

    console.log("----------Test-----------")
    console.log("now", now)
    console.log("startof",start)
    console.log ("endof", end)
    console.log("Length", monthLength)
    console.log("columns", columns)

    return filledColumn;
}


export const fillEmptyColumn = (columns, now) => {
  let tempColumns = columns.slice(0);

  const firstDay = dayjs(now).startOf("month").get("day");
  const lastDay = dayjs(now).endOf("month").get("day");

  console.log("lastDay", lastDay)

  for(i=0; i< firstDay; i +=1) {
    const a = dayjs(now).subtract(1,"month").endOf("month").get("date")
    tempColumns.unshift(a - i)
  }

  for(i=0;i<6-lastDay; i +=1) {
    const b = dayjs(now).add(1, "month").startOf("month").get("date")
    console.log("b",b)
    tempColumns.push(b + i)
  }

  console.log("tempcolumns",tempColumns)

  return tempColumns;



}

 

(3)

     const date = dayjs(start).add(i, "day").get("date")

일수를 추가할 때는 "date" 가 아닌 "day"를 써야 한다. 

.get("date")는 일자 이고 .get("day") 는 요일에 해당하는 숫자를 반환했으나

add나 substract 에서는 .add(i,"day") 해야지 일자가 추가되서 나온다.

 

또한 해당함수는 2023.04.30 에서 day로 1을 더하면은 2023.05.01로 바꿔준다. smart 하다.

 

(4) Columns 자체를 년월일 시분초 값으로 줘야 한다!!! 

내가 만든 함수는 년월일 시분초 형태가 아니라 일 수만 보내줬다. 

이러면 Columns를 본 컴포넌트에서 받아서 dayjs 내장 함수를 쓸 수가 없다. 

import dayjs from "dayjs";
import isBetween from "dayjs/plugin/isBetween";
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
import isSameOrAfter from "dayjs/plugin/isSameOrAfter";
dayjs.extend(isBetween);
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);

export const getCalendarColumns = (now) => { 
  const start = dayjs(now).startOf("month");
  const end = dayjs(now).endOf("month");
  const length = dayjs(end).get("date");

  console.log("---------------test----------------")
  console.log("start", start)
  console.log("end", end) 
  console.log("length", length)

  let columns = []

  for(let i = 1 ; i <= length ; i += 1) {
    let temp = dayjs(start).add(i, "day")
    columns.push(temp)
  }
  console.log(columns)

  const finalColumns = fillEmptyColumn(start,end,columns)

  console.log("finalcolumn", finalColumns)

  return finalColumns
}

const fillEmptyColumn = (start, end, columns) => {

  let tempcolumns = columns.slice(0);

  const firstDay = dayjs(start).get("day")
  console.log("시작요일", firstDay)

  const lastDay = dayjs(end).get("day")
  console.log("끝요일", lastDay)

  for(let i=0; i < firstDay ; i +=1){
    const date = dayjs(start).subtract(i, "day")
    tempcolumns.unshift(date)
  }

  for(let i=0; i < 6-lastDay ; i +=1){
    const date = dayjs(end).add(i, "day")
    tempcolumns.push(date)
  }

  console.log(tempcolumns)

  return tempcolumns

}

요런식으로 App.js 에 보내줘야 한다.

 

(5) 한시간만에 찾은 것

이런 식으로 나와야 함. 

처음에 그냥 컬럼값 계산할 때, 나는 4월달만 뽑아달라고 했는데, 자꾸 3.31~부터 4.29일까지 뽑아주길래 잘못 된 줄 알고 

for 루프 돌릴 때, +1씩 해서 4.1부터 4.30일까지 돌렸음. 

이게 잘못 되었음. 왜냐하면 00:00 은 오전 12시니까 3.31 00: 00 은 4.1일의 start를 의미하는 것이였음