티스토리 뷰

Next.js로 어플리케이션을 만들던 중 Notion API를 통해서 기간 값을 받아오는 로직이 있습니다. 

해당 데이터는 string 타입으로 오며 "2022-11-05" 이런 식으로 넘어오게 됩니다. 

start date와 end date를 받아오는데 end date를 설정해주지않으면 null으로 담겨오게 됩니다. 

 

end date를 받아오지 않으면 임의로 날짜를 넣어주어야 하는데, 직접 넣어주는 방식보단 오늘 날짜를 넣어주고 싶어서 로직을 짜게 됐습니다. start의 경우, null 병합연산자를 통해 왼쪽 값이 null이나 undefined일 경우, 오른쪽의 2022-11-12 를 하드코딩하는 식으로 넣어주었습니다. 이 부분도 변경하고 싶지만 우선 end 의 경우를 오늘 날짜를 기준으로 year-month-date의 string 형식 데이터로 넣어주고자 altEndDateString이라는 변수를 따로 만들어주었습니다. 

null 병합 연산자(??)링크 

 

완성본

// altEndDateString : alternative EndDate String 의 축약어로 endDate가 없을 경우, 
// 대안적으로 넣어줄 String 타입의 데이터를 뜻합니다.
let altEndDateString = String(new Date().toLocaleDateString()).replaceAll(".", "-").slice(0, -1);

코드 설명: new Date 를 통해 Date객체를 만들어줍니다.

Date.prototype.toLocaleDateString()

사용자 에이전트 시간대에서 지정된 날짜의 날짜 부분을 언어에 따라 표현한 문자열을 반환하는 메서드

toLocaleDateString()
toLocaleDateString(locales)
toLocaleDateString(locales, options)

매개변수 locales와 option은 선택 사항이기 때문에 생략하셔도 됩니다. 

locales를 생략하면 사용자 지정 날짜 형식을 반환하고 options는 출력 형식을 조정하는 개체입니다. 

두 매개변수는 모든 browser에서 지원하는 것은 아니므로 try-catch문을 통해 에러 핸들링을 해줘야 합니다. 

저는 매개변수 없이 그냥 출력했을 때, 한국 형식의 날짜값인  2022. 11. 14.를 결과값으로 받았습니다.

데이터의 타입을 String으로 변경해주기 위해서 String 생성자를 통해 string 데이터로 변경해주었습니다.

이 다음부터는 String 관련 메서드를 사용할 수 있겠죠? 제가 원하는 값은 2022-11-14이므로 "."를 "-"로 변경해주었습니다(replaceAll 메서드 사용). 

String.prototype.replaceAll()

replaceAll(pattern, replacement)

pattern은 내가 바꾸고 싶은 string값이며 두번째 인자는 대체될 string값입니다. replaceAll은 대체된 새 문자열을 반환합니다. 이렇게 2022. 11. 14. -> 2022-11-14- 라는 값으로 변경했습니다. 마지막에 붙은 "-"를 제거해주고 싶어서 slice 메서드를 통해 마지막 요소를 제거했습니다. 

String.prototype.slice()

문자열의 일부를 추출하면서 새로운 문자열을 반환합니다. 

str.slice(beginIndex, [, endIndex])

 

beginIndex는 필수값이며 endIndex는 선택사항입니다. 

  • begin은 추출 시작점인 0부터 시작하는 인덱스이며, 만약 음수일 경우 beginIndex는 strLength(문자열 길이) + beginIndex로 취급됩니다. (e.g. beginIndex가 -3이라면 시작점은 strLength - 3)입니다.
  • endIndex(옵션) 0부터 시작하는 추출 종료점 인덱스로 그 직전까지 추출됩니다. 인덱스 위치의 문자는 추출에 포함되지 않습니다. 이 옵션이 생략될 경우 slice는 문자열 마지막까지 추출합니다. 만약 음수라면 endIndex는 strLength (문자열 길이) + endIndex로 취급됩니다. (e.g. endIndex가 -3이면 종료점은 strLength -3) 입니다. 
  • 매개변수의 설명에 골머리 앓는 것보다는 직접 사용해보시거나 예시를 보면서 이해하는 것이 더 빠릅니다. 
  • slice메서드는 배열에서도 같은 이름의 메서드가 있습니다 얕은 복사를 할 때 사용하며 유용하니 읽어보시길 바랍니다. 

음수 인덱스로 slice 사용 예시

var str = 'The morning is upon us.';
str.slice(-3);     // returns 'us.'
str.slice(-3, -1); // returns 'us'
str.slice(0, -1);  // returns 'The morning is upon us'

2022-11-14- 에서 처음 0인덱스부터 -1(마지막 요소 제외)까지 추출하고 싶기 때문에 .slice(0, -1)를 사용하여 마지막 - 값을 잘라내었습니다. 결과적으로 "2022-11-14" 값을 얻을 수 있었습니다. 

 

 

export default function ProjectItem({ data }) {


//위에 코드 중략
 
 const start = data.properties.workPeriod.date.start ?? "2022-11-12";
  //endDate가 없는 경우, 지정하지 않거나 빈값일 경우, 오늘 날짜로 넣어준다.
  let altEndDateString = String(new Date().toLocaleDateString())
    .replaceAll(".", "-")
    .slice(0, -1);
  const end = data.properties.workPeriod.date?.end ?? altEndDateString;

  //시간 계산하는 로직
  const calcPeriod = (start, end) => {
    // 날짜 계산하는 로직
    // start,end 형식 예시 2022-11-05
    const startDateStringArr = start.split("-");
    const endDateStringArr = end.split("-");

    // new Date(year, month, date)
    let startDate = new Date(
      startDateStringArr[0], // 2022
      startDateStringArr[1], // 11
      startDateStringArr[2] //05
    );
    let endDate = new Date(
      endDateStringArr[0],
      endDateStringArr[1],
      endDateStringArr[2]
    );

    const diffInMs = Math.abs(endDate - startDate);
    const result = diffInMs / (1000 * 60 * 60 * 24);
    // console.log(`기간 : ${result}`);
    return result;
  };
  
  return (
    <div className="project-card">
      <Image
        className="rounded-t-xl"
        src={imgSrc}
        alt="cover image"
        width="100%"
        height="60%"
        layout="responsive"
        objectFit="cover"
        quality={100}
      />
      <div className="p-4 flex flex-col">
        <h1 className="text-2xl font-bold">{title}</h1>
        <h3 className="mt-4 text-xl">{description}</h3>
        <a href={github}>깃허브 바로 가기</a>
        <a href={youtube}>유투브 바로 가기</a>
        <p className="my-1 text-xg">
          작업기간 : {start} ~ {end} ({calcPeriod(start, end)}일)
        </p>
        <div className="flex items-start mt-2">
          {tags.map((aTag) => (
            <h1
              className="px-2 py-1 mr-2 rounded-md bg-sky-200 dark:bg-sky-700"
              key={aTag.id}>
              {aTag.name}
            </h1>
          ))}
        </div>
      </div>
    </div>
  );
}
댓글