같은 주인지 확인하기
🕒 읽는 데 0분 예상forest_articles
forest_날짜
forest_분류
문서
예를 들어, 아래와 같이 달력이 있다고 해보자.

3월 31일은 ‘3월 N주차’라 할 수 있고, 4월 1일은 ‘4월 1주차’라고 할 수 있을 것이다.
그런데 문제는 3월 31일과 4월 1일이 같은 주인지를 어떻게 확인할 수 있는지이다. 위에서 생성한
M월 N주차
형식만으로는 달이 넘어가는 시기에 대해서는 제대로 계산할 수 없다.const getCurrentWeekLabel = (date: Date): string => { const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7)); const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); const weekNo = Math.ceil((((d.getTime() - yearStart.getTime()) / 86400000) + 1) / 7); return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`; };
이 JavaScript 코드는 ISO 8601 표준에 따라 주어진 날짜의 주차(week number)를 계산하여
YYYY-W16
형태(이번 년도 16주차라는 뜻)의 문자열로 반환하는 함수를 정의한다. 여기서는 '월요일'을 한 주의 시작으로 간주한다. 코드를 단계별로 자세히 살펴보자.1. 함수 정의:
const getCurrentWeekLabel = (date: Date): string => { ... };
getCurrentWeekLabel
이라는 이름의 상수(const) 함수를 선언한다.
- 이 함수는
Date
객체 형태의 날짜를 입력 인자(date
)로 받는다. TypeScript 타입 정의에 따라date
는Date
타입이다.
- 함수는 문자열(
string
)을 반환한다. TypeScript 타입 정의에 따라 함수의 반환 값은string
타입이다.
2. UTC 기준 날짜 생성:
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
- 입력된 날짜(
date
)를 기반으로 새로운Date
객체d
를 생성한다.
Date.UTC()
메서드를 사용하여 날짜를 UTC(Coordinated Universal Time, 협정 세계시) 기준으로 생성한다. 이는 시간대 문제를 방지하고 일관된 결과를 얻기 위함이다.
date.getFullYear()
,date.getMonth()
,date.getDate()
메서드를 사용하여 입력 날짜의 년, 월, 일을 각각 가져온다.
3. ISO 8601 주차 기준일 설정 (목요일):
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7)); // 목요일로 이동
- ISO 8601 표준은 해당 주의 목요일이 속하는 날짜를 기준으로 주차를 결정한다. 따라서 주어진 날짜
d
를 해당 주의 목요일로 이동시킨다.
d.getUTCDay()
는 UTC 기준 요일(0: 일요일, 1: 월요일, ..., 6: 토요일)을 반환한다.
(d.getUTCDay() || 7)
은d.getUTCDay()
가 0(일요일)일 경우 7로 대체한다. JavaScript에서||
연산자는 왼쪽 값이 falsy(null, undefined, 0, '', NaN, false)일 경우 오른쪽 값을 반환한다.
4 - (d.getUTCDay() || 7)
는 현재 날짜에서 목요일까지 며칠을 더해야 하는지 계산한다. 예를 들어, 현재 날짜가 월요일(1)이면4 - 1 = 3
이 되므로 3일을 더하여 목요일로 이동한다. 일요일(0)이면4 - 7 = -3
이 되므로 3일을 빼서 목요일로 이동한다.
d.setUTCDate()
메서드를 사용하여d
의 날짜를 조정한다.
4. 해당 연도의 시작일 설정:
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
- 해당 연도(목요일 날짜
d
의 연도)의 1월 1일을 UTC 기준으로yearStart
라는Date
객체로 생성한다. 이 날짜는 주차 계산의 기준점이 된다.
d.getUTCFullYear()
메서드를 사용하여d
의 연도를 가져온다.
- 월은 0부터 시작하므로 1월은 0으로 지정한다.
5. 주차 계산:
const weekNo = Math.ceil((((d.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);
- 주차 번호(
weekNo
)를 계산한다.
d.getTime() - yearStart.getTime()
은 목요일 날짜d
와 해당 연도의 시작일yearStart
간의 밀리초 차이를 계산한다.
/ 86400000
는 밀리초를 일(day) 단위로 변환한다 (86400000 밀리초 = 1일).
+ 1
은 연도의 첫 날을 포함하기 위해 1을 더한다.
/ 7
은 일 수를 주 수로 나눈다.
Math.ceil()
은 결과를 올림하여 주차 번호를 얻는다. ISO 8601 표준에서는 1월 1일이 있는 주부터 1주차로 시작하며, 4일 이상이 해당 연도에 속해야 그 주를 해당 연도의 첫 주로 간주한다.
6. 주차 레이블 반환:
return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;
YYYY-Www
형태의 주차 레이블 문자열을 생성하여 반환한다.
d.getUTCFullYear()
는 해당 연도를 가져온다.
W
는 연도와 주차 번호를 구분하는 문자열이다.
String(weekNo).padStart(2, '0')
는 주차 번호(weekNo
)를 문자열로 변환하고, 길이가 2자리가 안 될 경우 앞자리를 '0'으로 채운다.padStart(2, '0')
메서드는 문자열의 길이가 지정된 길이보다 짧을 경우, 문자열의 시작 부분에 다른 문자열을 반복하여 채워준다.
이제, 이렇게 생성된 Label이 같은 지를 비교하면, 두 날짜가 같은 주에 속하는 지를 확인할 수 있다.
물론, 외부 라이브러리를 사용하거나 위에서 Label을 생성하는 과정 없이 아이디어만 가져와서 직접 계산해주면 더 쉽거나 효율적으로 구현할 수 있을 것이다. 하지만 필자의 경우 특정 날짜가 몇 주차 인지까지 계산해야 했기 때문에 프로젝트에 쓰인 코드를 그대로 사용해 설명했다.