이번 글은 월별 최대 일 수를 구하는 방법을 구현해 보고자 합니다.
사실 Date 객체를 활용하여 아래 코드처럼 간단하게 구할 수 있습니다.
(() => {
const year = 2024;
const month = 10;
const day = new Date(year, month, 0).getDate();
console.log(day); // 31
})();
하지만, 저는 이러한 수동적인 코드를 원하는 것이 아닌, 입력에 따라 필요한 최대 일 수를 계산해 내는 함수를 구현해 보고자 합니다.
최대 일 수와 연속된 숫자를 만들어 보자.
최대 일 수를 구하고 연속된 숫자를 생성하여 캘린더 로직에도 사용할 수 있는 함수를 만들어 보려고 합니다.
저는 Array 객체로 size 를 가져와 배열을 생성하고 0을 채워 index 값을 활용하여 연속된 숫자를 가진 배열을 만들어 보고자 합니다.
export function getMaxDate(year: number, month: number): number {
return new Date(year, month, 0).getDate();
}
export function getDates(size: number): number {
return new Array(size).fill(0).map((_, i) => i + 1);
}
(() => {
const date = new Date();
const year = date.getFullYear();
const month = 10;
const maxDate = getMaxDate(year, month);
const dates = getDates(maxDate); // [1 ... 31]
})();
결과
월별 최대 일 수를 구하고 연속된 숫자를 가져올 수 있게 되었다.
그러면 이제 뭐가 필요할까? ..
바로 주말을 구분하고 각 일에 맞는 요일을 알아보는 작업입니다. 요약하자면 ..
1. 각 일 수마다 어떤 요일인지 알아내기
2. 주말인지 유효성 체크하기
이 두가지가 필수로 필요할 것이라고 생각이 듭니다.
요일 구하기
이것도 마찬가지로 요일을 구분하는 방법은 Date 객체로 간단하게 구현이 가능했습니다.
Date 객체를 new 생성자로 생성하고 getDay() 메서드를 호출하여 값을 반환한다면 0 ~ 6 까지 숫자로 반환되도록 되어있습니다.
이 숫자의 의미는 요일의 순서입니다.
만약, 내가 2024 | 10 | 5 를 Date 객체 constructor() 로 전달한다면 Date 객체는 getDay() 메서드를 사용했을 때,
해당 날짜를 기억하고 있다가 일치하는 요일을 순서대로 숫자로 표현하여 전달해 줍니다.
예를 들어
(() => {
const year = 2024;
const month = 10;
const date = 5;
const day = new Date(year, month, date).getDay(); // 6
})();
이런 식으로 6번째 요일 "토요일" 을 나타내게 됩니다. 6인 이유는 일요일이 첫 번째로 0번째 위치하기 때문입니다.
그럼 본격적으로 요일을 나타내기 위한 enum 과 상수 요일 객체를 만들어 줍니다.
enum Day {
SUNDAY,
MONDAY,
TUESDAY,
WENDESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
const DAYS: { [key in Day]: string } = {
[Day.SUNDAY]: "일요일",
[Day.MONDAY]: "월요일",
[Day.TUESDAY]: "화요일",
[Day.WENDESDAY]: "수요일",
[Day.THURSDAY]: "목요일",
[Day.FRIDAY]: "금요일",
[Day.SATURDAY]: "토요일",
}
enum으로 필요한 요일들을 Date 객체에서의 getDay() 메서드 반환 방법과 동일하게 열거해 줍니다.
이렇게 열거된 값은 개발자가 코드로 보기엔 SUNDAY, MONDAY 이런 식으로 보이지만 실제론 0 ~ 6 으로 이루어진 키입니다.
이런 방법을 가지고 DAYS 상수 요일 객체를 만들고 문자열로 만들어진 값을 가져올 수 있도록 처리합니다.
export function getDay(year: number, month: number, date: number): string {
const day = new Date(year, month - 1, date).getDay() as Day;
return DAYS[day];
}
(() => {
const year = 2024;
const month = 10;
const date = 5;
const day = getDay(year, month, date) // "토요일"
})();
주의할 점은 Date 객체의 getDay() 메서드를 활용하는 경우 month 도 마찬가지로 0 ~ 11 로 나뉘기 때문에,
그냥 10월로 기입할 경우, 11월 달의 날짜를 확인하게 됩니다.
이 경우를 해결하기 위해 해당 함수에서의 처리는 month - 1 로 1을 빼 주는 방법으로 처리할 수 있습니다.
이제 주말인지 구분을 해 보자.
달력엔 주말인 지 아닌 지를 정확히 알 수가 있어야 합니다.
이것도 이미 열거해 둔 요일 정보를 가지고 구분이 가능하기 때문에, 기존 상수 요일 객체를 활용하겠습니다.
export function validWeekend(day: string): boolean {
return day === DAYS[Day.SUNDAY] || day === DAYS[Day.SATURDAY];
}
(() => {
const year = 2024;
const month = 10;
const date = 5;
const day = getDay(year, month, date) // "토요일"
const isWeekend = validWeekend(day); // true
})();
자 이렇게 해서 valid 함수를 작성하여 주말인 지 구분하고 달력에 필요한 객체를 생성할 준비가 되었습니다.
달력에 필요한 객체를 생성해 보자.
이번 함수는 저의 개인적인 가계부 작성 프로젝트를 위해 연습해 본 내용입니다.
실제로 쓰일 수 있을 지는 모르겠으나, 어느정도 필요한 부분은 떼서 개량해서 사용하거나 할 것으로 예상됩니다.
자 이제 객체를 생성해 보겠습니다.
const year = 2024;
const month = 10;
const date = 5;
export function createCalendar(date: number) {
const day = getDay(date);
return {
date: date,
day: day,
isWeekend: validWeekend(day)
}
}
(() => {
const maxDate = getMaxDate(year, month);
const dates = getDates(maxDate);
const calendar = dates.map(createCalendar);
})();
이렇게 해서 최대 일 수를 구하고 요일과 주말을 구분하는 함수들을 작성해 보았습니다.
결과물은 아래와 같이 나오고 이런 식으로 날짜를 알아보는 방식이 있다는 것을 알게 되었습니다.
이제 앞으로 가계부 프로젝트를 만들면서 로직은 자연스럽게 수정이 되겠지만,
얼추 모양을 잡아 두었으니, 어떤 식으로 날짜를 구하면 될 지, 구분은 어떻게 할 지 앞으로의 방향성을 정하기 쉬워졌습니다.
[
{ date: 1, day: '화요일', isWeekend: false },
{ date: 2, day: '수요일', isWeekend: false },
{ date: 3, day: '목요일', isWeekend: false },
{ date: 4, day: '금요일', isWeekend: false },
{ date: 5, day: '토요일', isWeekend: true },
{ date: 6, day: '일요일', isWeekend: true },
{ date: 7, day: '월요일', isWeekend: false },
{ date: 8, day: '화요일', isWeekend: false },
{ date: 9, day: '수요일', isWeekend: false },
{ date: 10, day: '목요일', isWeekend: false },
{ date: 11, day: '금요일', isWeekend: false },
{ date: 12, day: '토요일', isWeekend: true },
{ date: 13, day: '일요일', isWeekend: true },
{ date: 14, day: '월요일', isWeekend: false },
{ date: 15, day: '화요일', isWeekend: false },
{ date: 16, day: '수요일', isWeekend: false },
{ date: 17, day: '목요일', isWeekend: false },
{ date: 18, day: '금요일', isWeekend: false },
{ date: 19, day: '토요일', isWeekend: true },
{ date: 20, day: '일요일', isWeekend: true },
{ date: 21, day: '월요일', isWeekend: false },
{ date: 22, day: '화요일', isWeekend: false },
{ date: 23, day: '수요일', isWeekend: false },
{ date: 24, day: '목요일', isWeekend: false },
{ date: 25, day: '금요일', isWeekend: false },
{ date: 26, day: '토요일', isWeekend: true },
{ date: 27, day: '일요일', isWeekend: true },
{ date: 28, day: '월요일', isWeekend: false },
{ date: 29, day: '화요일', isWeekend: false },
{ date: 30, day: '수요일', isWeekend: false },
{ date: 31, day: '목요일', isWeekend: false }
]
출력 결과물이 정말 아름답게 처리된 것 같습니다.
혹시나 필요하신 분들은 참고해 주셔도 너무나 감사하고 영광이며, 피드백도 환영합니다.
감사합니다.
'생각하는 시간 > 타입스크립트' 카테고리의 다른 글
서로소 유니온 타입으로 축약하는 과정 (0) | 2024.12.06 |
---|---|
tRPC를 활용한 타입 세이프 백엔드 API 구현 (0) | 2024.06.04 |
타입스크립트 컴파일러 옵션 설정 (0) | 2024.05.05 |
타입스크립트의 동작 원리 (0) | 2024.05.04 |
자바스크립트의 한계점과 타입스크립트 (0) | 2024.04.15 |