문제 정의
첫 번째 인수로 숫자(연중 몇 번째 날인지), 두 번째 인수로 불리언 값(윤년 여부)을 받는 JavaScript 함수를 작성해야 합니다. 두 번째 인수가 true이면 해당 연도는 윤년을 의미하며, 이때 2월은 29일까지 있습니다. 이 정보를 바탕으로 함수는 연중 n번째 날에 해당하는 실제 날짜(월과 일)를 문자열로 반환해야 합니다.
예를 들어 윤년의 60번째 날이라면 결과는 'Feb, 29'가 되어야 합니다. 평년이라면 같은 60번째 날은 'Mar, 1'에 해당합니다.
예제 코드
다음은 위 문제를 해결하는 코드입니다.
const day = 60;
const isLeap = true;
const findDate = (day = 1, isLeap = false) => {
// 윤년은 최대 366일이므로 그 이상은 유효하지 않음
if(day > 366){
return undefined;
};
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// 윤년이면 2월의 일수를 29로 변경
if(isLeap){
days[1]++;
};
let i = -1, count = 0;
// 누적 일수가 목표 일수를 넘어설 때까지 월 단위로 순회
while(count < day){
i++;
count += days[i];
};
// 해당 월 이전까지의 총 일수
const upto = days.slice(0, i).reduce((acc, val) => acc + val);
const month = months[i];
// 그 달의 며칠째인지 계산
const d = count - upto;
return `${month}, ${d}`;
};
console.log(findDate(day, isLeap));
코드 동작 원리
이 함수의 핵심 로직은 다음과 같이 정리할 수 있습니다.
1. 입력값 검증: 한 해는 평년 기준 365일, 윤년 기준 366일이므로 입력된 일수가 366을 초과하면 undefined를 반환해 잘못된 입력을 처리합니다.
2. 월별 일수 배열 준비: 각 월의 이름과 일수를 배열로 저장하고, 윤년인 경우 2월의 일수를 28에서 29로 1 증가시킵니다.
3. 월 탐색: while 루프를 돌며 월별 일수를 하나씩 누적합니다. 누적합이 목표 일수(day)에 도달하거나 넘어서는 시점의 월이 바로 찾고자 하는 월입니다.
4. 일(day) 계산: 해당 월까지의 누적 일수에서 그 월 이전까지의 총 일수를 빼면, 그 달 안에서 몇 번째 날인지 알 수 있습니다.
5. 결과 반환: '월, 일' 형식의 문자열로 조합해 반환합니다.
출력 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
Feb, 29
입력값이 윤년의 60번째 날이었기 때문에, 1월(31일)을 지나고 2월의 29번째 날, 즉 2월 29일이 올바른 결과로 반환됩니다. 만약 isLeap를 false로 전달하면 같은 60번째 날이 'Mar, 1'로 계산되어 윤년과 평년의 차이가 정확히 반영됨을 확인할 수 있습니다.