인증 빈도 authFrequency와 기간 peroid에 따라 챌린지 종료일 구하는 getChallengeEndData
함수 수정 & 리팩토링
변수명을 짧게 작성하려다 보니 어떤 값을 담는 건지 알 수 없고
함수 안에 여러 함수가 들어있고
시작일을 구하던 함수처럼 말월이 아닌 말일만을 생각해 작성함
갈아엎자ㅜㅜ
export function getChallengeEndData(af: AuthFrequency, p: string, s: string) {
const year = new Date().getFullYear();
const [m, de, dy] = s.split('.'); // string type
const [month, date, day] = [+m, +de, +dy];
function getEverydayEndData({ y, m, d }: GetEndDataParams) {
const { year, month } = getCurrentDate();
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate] = [y, m, d];
let day = getDay(y, m, d); // 시작일 요일
let leftDay = 7 - day;
tempDate += leftDay;
if (tempDate > lastDate) {
tempMonth += 1;
tempDate = Math.abs(lastDate - tempDate);
}
return [tempYear, tempMonth, tempDate];
}
function getWeekdayEndData({ y, m, d, o = false }: GetEndDataParams) {
const { year, month } = getCurrentDate();
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate] = [y, m, d];
let day = getDay(y, m, d); // 시작일 요일
if (day === 5 && o) {
day = 1;
tempDate += 3;
}
let leftDay = 5 - day;
tempDate += leftDay;
if (tempDate > lastDate) {
tempMonth += 1;
tempDate = Math.abs(lastDate - tempDate);
}
return [tempYear, tempMonth, tempDate];
}
function getWeekendEndDate({ y, m, d, o = false }: GetEndDataParams) {
const { year, month } = getCurrentDate();
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate] = [y, m, d];
let day = getDay(y, m, d); // 시작일 요일
if (day === 6) tempDate += 1;
if (o) tempDate += 7;
if (tempDate > lastDate) {
tempMonth += 1;
tempDate = Math.abs(lastDate - tempDate);
}
return [tempYear, tempMonth, tempDate];
}
function getNTimesAWeekEndData({ y, m, d, o = false }: GetEndDataParams) {
const { year, month } = getCurrentDate();
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate] = [y, m, d];
if (o) tempDate += 7;
else tempDate += 6;
if (tempDate > lastDate) {
tempMonth += 1;
tempDate = Math.abs(lastDate - tempDate);
}
return [tempYear, tempMonth, tempDate];
}
switch (af) {
case 'EVERYDAY':
const e1 = getEverydayEndData({ y: year, m: +month, d: +date });
const e2 = getEverydayEndData({ y: e1[0], m: e1[1], d: e1[2] });
const e3 = getEverydayEndData({ y: e2[0], m: e2[1], d: e2[2] });
const e4 = getEverydayEndData({ y: e3[0], m: e3[1], d: e3[2] });
if (p === 'ONEWEEK') return e1;
else if (p === 'TWOWEEK') return e2;
else if (p === 'THREEWEEK') return e3;
else return e4;
case 'WEEKDAY':
const w1 = getWeekdayEndData({ y: year, m: +month, d: +date });
const w2 = getWeekdayEndData({ y: w1[0], m: w1[1], d: w1[2], o: true });
const w3 = getWeekdayEndData({ y: w2[0], m: w2[1], d: w2[2], o: true });
const w4 = getWeekdayEndData({ y: w3[0], m: w3[1], d: w3[2], o: true });
if (p === 'ONEWEEK') return w1;
else if (p === 'TWOWEEK') return w2;
else if (p === 'THREEWEEK') return w3;
else return w4;
case 'WEEKEND':
const k1 = getWeekendEndDate({ y: year, m: +month, d: +date });
const k2 = getWeekendEndDate({ y: k1[0], m: k1[1], d: k1[2], o: true });
const k3 = getWeekendEndDate({ y: k2[0], m: k2[1], d: k2[2], o: true });
const k4 = getWeekendEndDate({ y: k3[0], m: k3[1], d: k3[2], o: true });
if (p === 'ONEWEEK') return k1;
else if (p === 'TWOWEEK') return k2;
else if (p === 'THREEWEEK') return k3;
else return k4;
default:
const n1 = getNTimesAWeekEndData({ y: year, m: +month, d: +date });
const n2 = getNTimesAWeekEndData({ y: n1[0], m: n1[1], d: n1[2], o: true });
const n3 = getNTimesAWeekEndData({ y: n2[0], m: n2[1], d: n2[2], o: true });
const n4 = getNTimesAWeekEndData({ y: n3[0], m: n3[1], d: n3[2], o: true });
if (p === 'ONEWEEK') return n1;
else if (p === 'TWOWEEK') return n2;
else if (p === 'THREEWEEK') return n3;
else return n4;
}
}
챌린지 기간 : 'ONEWEEK' | 'TWOWEEK' | 'THREEWEEK' | 'FOURWEEK'
챌린지 인증 빈도 : 'EVERYDAY' | 'WEEKDAY' | 'WEEKEND' | NWEEK ('SIXTHAWEEK' | 'FIFTHAWEEK' | 'FORTHAWEEK' | 'THIRDAWEEK' | 'TWICEAWEEK' | 'ONCEAWEEK')
// pages/CreateChallenge.tsx
function CreateChallenge() {
...
return (
...
{authFrequency && (
<div className="w-full mt-6">
<label>
<h2 className="font-bold">
시작일<span className="text-red-400">*</span>
</h2>
</label>
<div className="flex flex-wrap">
{getChallengeStartDate(authFrequency as AuthFrequency).map(
({ year, month, date, day }, i) => (
<button
type="button"
key={i}
onClick={() =>
handleChangeStartDate(`${year}.${month}.${date}.${day}`)
}
);
}
// modules/challenge/utils.ts
export function getChallengeEndData(
authFrequency: AuthFrequency,
peroid: ChallengePeroid,
startDate: string
) {
console.log('getChallengeEndData', authFrequency, peroid, startDate);
startData param 2022.11.27.2에서 년월일들을 추출하기 위해 split method를 이용
배열 디스트럭처링으로 y, m, de, dy를 가져오는데, 얘는 문자열이므로 숫자로 바꾸기
const [y, m, de, dy] = startDate.split('.'); // ['2022', '11', '27', '2']
const [year, month, date, day] = [+y, +m, +de, +dy]; // [2022, 11, 27, 2]
// => year: 2022, month: 11 (12월), date: 27, day: 2 (화욜)
수정전
매일 + 1주 => 2023.1.1 (일)
function getEverydayEndData({ year, month, date, day }: DateData) {
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate, tempDay] = [year, month, date, day];
if (day === 0) tempDate += 1;
else tempDate += 7 - day;
시작일 계산하는 함수와 동일한데, 이 로직이 많이 중복돼서 분리를 해야 함. 근데 아직 어떻게 분리하면 좋을지 생각하기 귀찮..아서 일단 작성
if (tempDate > lastDate) {
tempMonth += 1;
if (tempMonth > 11) {
tempYear += 1;
tempMonth = 0;
}
tempDate = tempDate - lastDate;
tempDay = getDay(tempYear, tempMonth, tempDate);
}
function getEverydayEndData({ year, month, date, day }: DateData) {
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate, tempDay] = [year, month, date, day];
if (day === 0) tempDate += 1;
else tempDate += 7 - day;
if (tempDate > lastDate) {
tempMonth += 1;
if (tempMonth > 11) {
tempYear += 1;
tempMonth = 0;
}
tempDate = tempDate - lastDate;
tempDay = getDay(tempYear, tempMonth, tempDate);
}
return { year: tempYear, month: tempMonth, date: tempDate, day: tempDay };
}
export function getChallengeEndData(
authFrequency: AuthFrequency,
peroid: ChallengePeroid,
startDate: string
) {
console.log('getChallengeEndData', authFrequency, peroid, startDate);
const [y, m, de, dy] = startDate.split('.');
const [year, month, date, day] = [+y, +m, +de, +dy];
const everydayEndDataTest = getEverydayEndData({ year, month, date, day });
console.log('everydayEndDataTest :', everydayEndDataTest);
예상한 결과대로 나옴! 2023.01.01 (일-0)
얘넨 저 함수에 각각 이전 주 데이터(WEEKDAY면 ONEWEEK 반환값?)를 넣어주면 된다.
앞에서 나온 {year: 2023, month: 0, date: 1, day: 0}
(2023.01.01 (0)) 이 데이터를 넣으면 2023.01.08 이 나오면 되는데,, 착각한 부분이 있다.
2주차부턴 무조건 +7 해야 함. 왜냐면 1주 차 결과가 일요일(0)로 나오니까 저렇게 작성하면 무조건 +1이 되기 때문에 결과가 이상하게 나온다. 2주 차 이상인지 확인하기 위한 로직을 작성하기 위해 opt 이름의 옵셔널 인자를 하나 더 받아서 조건문으로 체크 (전에도 작성했는데 까먹고 있었음ㅎ)
// type.ts
export interface GetEndDataParams {
year: number;
month: number;
date: number;
day: number;
opt?: boolean; // option
// { [key: string]: boolean | number; };
}
// utils.ts
function getEverydayEndData({ year, month, date, day, opt }: GetEndDataParams) {
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate, tempDay] = [year, month, date, day];
if (opt) {
tempDate += 7;
} else {
if (day === 0) tempDate += 1;
else tempDate += 7 - day;
}
...
}
export function getChallengeEndData() {
...
const oneweekEverydayDate = getEverydayEndData({ year, month, date, day });
const twoweekEverydayDate = getEverydayEndData({
year: oneweekEverydayDate.year,
month: oneweekEverydayDate.month,
date: oneweekEverydayDate.date,
day: oneweekEverydayDate.day,
opt: true,
});
console.log('twoweekEverydayDate :', twoweekEverydayDate);
2022.01.08 (일) 잘 나옴!
2023.01.15, 22일 일요일이 나오면 됨
const threeweekEverydayData = getEverydayEndData({
year: twoweekEverydayDate.year,
month: twoweekEverydayDate.month,
date: twoweekEverydayDate.date,
day: twoweekEverydayDate.day,
opt: true,
});
const foureweekEverydayData = getEverydayEndData({
year: threeweekEverydayData.year, ...
});
console.log('threeweekEverydayData :', threeweekEverydayData);
console.log('foureweekEverydayData :', foureweekEverydayData);
성..공
매일 + 1~4주 종료일 구하기 끝.
많이 적었지만 말일 말월 확인하는 로직이 중복되니 이거 수정하고, 전달해야 할 파라미터가 많아서 코드가 길어지는데 이것도 방법을 찾아봐야겠다
2주부터는 옵션 파라미터와 앞 주의 데이터까지 전달해야 해서 코드가 너무 길어서 함수를 하나 만들었다. 이름을 뭐라 해야 할지 몰라서 endDateHelper
헬퍼 함수 느낌으로 작성함
eDate라는 종료일 날짜와, 종료일 계산 함수를 받아서 그 함수에 객체스프레드 문법을 이용해 opt 프로퍼티를 추가해서 호출해서 반환된 값을 다시 반환하는 함수
// 2주이상일때데이터추출
function endDateHelper(eDate: DateData, func: (param: GetEndDataParams) => DateData) {
return func({ ...eDate, opt: true });
}
export function getChallengeEndData() {
...
const oneweekEverydayEndDate = getEverydayEndData({ year, month, date, day });
const twoweekEverydayEndDate = endDateHelper(
oneweekEverydayEndDate,
getEverydayEndData
);
console.log(twoweekEverydayEndDate); // {year: 2023, month: 0, date: 8, day: 0}
결과는 정상적으로 나오고 코드가 조금이라두 짧아졌다
const oneweekEverydayEndDate = getEverydayEndData({ year, month, date, day });
const twoweekEverydayEndDate = endDateHelper(
oneweekEverydayEndDate,
getEverydayEndData
);
const threeweekEverydayEndData = endDateHelper(
twoweekEverydayEndDate,
getEverydayEndData
);
const fourweekEverydayEndData = endDateHelper(
threeweekEverydayEndData,
getEverydayEndData
);
console.log(
oneweekEverydayEndDate,
twoweekEverydayEndDate,
threeweekEverydayEndData,
fourweekEverydayEndData
);
평일 매일 + 1주 => 2022.12.30 (금)
function getWeekdayEndData({
year,
month,
date,
day,
opt = false,
}: GetEndDataParams): DateData {
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate, tempDay] = [year, month, date, day];
tempDate += 5 - tempDay;
if (tempDate > lastDate) {
tempMonth += 1;
if (tempMonth > 11) {
tempYear += 1;
tempMonth = 0;
}
tempDate = tempDate - lastDate;
tempDay = getDay(tempYear, tempMonth, tempDate);
}
return { year: tempYear, month: tempMonth, date: tempDate, day: 5 };
}
1주 => 2022.12.30
2주 => 2023.01.06
3주 => 2023.01.13
4주 => 2023.01.20
2주 이상 (opt = true)은 앞 주의 데이터인 금요일(5)가 들어감. 그래서 3을 더해서 월요일(date += 3 && day = 1)을 만들어준다.
function getWeekdayEndData({
year,
month,
date,
day,
opt = false,
}: GetEndDataParams): DateData {
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate, tempDay] = [year, month, date, day];
//
if (opt) {
tempDate += 3;
tempDay = 1;
}
tempDate += 5 - tempDay;
...
}
export function getChallengeEndData(
authFrequency: AuthFrequency,
peroid: ChallengePeroid,
startDate: string
) {
...
// 평일 매일
const oneweekWeekdayEndDate = getWeekdayEndData({ year, month, date, day });
const twoweekWeekdayEndDate = endDateHelper(oneweekWeekdayEndDate, getWeekdayEndData);
const threeweekWeekdayEndDate = endDateHelper(twoweekWeekdayEndDate, getWeekdayEndData);
const fourweekWeekdayEndDate = endDateHelper(
threeweekWeekdayEndDate,
getWeekdayEndData
);
console.log('oneweekWeekdayEndDate :', oneweekWeekdayEndDate);
console.log('twoweekWeekdayEndDate :', twoweekWeekdayEndDate);
console.log('threeweekWeekdayEndDate :', threeweekWeekdayEndDate);
console.log('fourweekWeekdayEndDate :', fourweekWeekdayEndDate);
시작일 : 2022.12.31 (토)
토, 일 시작해서 항상 일요일에 끝
토요일(6)이면 tempDate+=1
로 일요일로 만들고, 2주 이상(opt=true)이면 +7!
function getWeekendEndDate({
year,
month,
date,
day,
opt = false,
}: GetEndDataParams): DateData {
console.log('getWeekendEndDate :', year, month, date, day);
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate, tempDay] = [year, month, date, day];
if (day === 6) tempDate += 1; // 일요일로만들고
if (opt) tempDate += 7; // opt면+7까지
if (tempDate > lastDate) {
tempMonth += 1;
if (tempMonth > 11) {
tempYear += 1;
tempMonth = 0;
}
tempDate = tempDate - lastDate;
tempDay = getDay(tempYear, tempMonth, tempDate);
}
return { year: tempYear, month: tempMonth, date: tempDate, day: 0 };
}
시작일 : 2022.1.2 (월)
월요일 시작해서 일요일에 끝
function getNTimesAWeekEndData({
year,
month,
date,
day,
opt = false,
}: GetEndDataParams): DateData {
const lastDate = getLastDate(year, month);
let [tempYear, tempMonth, tempDate, tempDay] = [year, month, date, day];
if (opt) tempDate += 7;
else tempDate += 6;
if (tempDate > lastDate) {
tempMonth += 1;
if (tempMonth > 11) {
tempYear += 1;
tempMonth = 0;
}
tempDate = tempDate - lastDate;
tempDay = getDay(tempYear, tempMonth, tempDate);
}
return { year: tempYear, month: tempMonth, date: tempDate, day: 0 };
}
export function getChallengeEndData(
authFrequency: AuthFrequency,
peroid: ChallengePeroid,
startDate: string
) {
...
// 주 n일
const n1weekWeekendEndDate = getNTimesAWeekEndData({ year, month, date, day });
const n2weekWeekendEndDate = endDateHelper(n1weekWeekendEndDate, getNTimesAWeekEndData);
const n3weekWeekendEndDate = endDateHelper(n2weekWeekendEndDate, getNTimesAWeekEndData);
const n4weekWeekendEndDate = endDateHelper(n3weekWeekendEndDate, getNTimesAWeekEndData);
console.log('n1weekWeekendEndDate :', n1weekWeekendEndDate);
console.log('n2weekWeekendEndDate :', n2weekWeekendEndDate);
console.log('n3weekWeekendEndDate :', n3weekWeekendEndDate);
console.log('n4weekWeekendEndDate :', n4weekWeekendEndDate);
}
시작일 : 2023.01.09 (월)
switch 문이냐 객체냐,, 그거시 문제로다
원래는 switch 문으로 했는데 if 문이 여러 개라 뭔가 수정할 수 있을 것 같은데.. 생각생각
export function getChallengeEndData(
authFrequency: AuthFrequency,
peroid: ChallengePeroid,
startDate: string
) {
...
switch (authFrequency) {
case 'EVERYDAY':
if (peroid === 'ONEWEEK') return oneweekEverydayEndDate;
else if (peroid === 'TWOWEEK') return twoweekEverydayEndDate;
else if (peroid === 'THREEWEEK') return threeweekEverydayEndData;
else return fourweekEverydayEndData;
case 'WEEKDAY':
if (peroid === 'ONEWEEK') return oneweekWeekdayEndDate;
else if (peroid === 'TWOWEEK') return twoweekWeekdayEndDate;
else if (peroid === 'THREEWEEK') return threeweekWeekdayEndDate;
else return fourweekWeekdayEndDate;
case 'WEEKEND':
if (peroid === 'ONEWEEK') return oneweekWeekendEndDate;
else if (peroid === 'TWOWEEK') return twoweekWeekendEndDate;
else if (peroid === 'THREEWEEK') return threeweekWeekendEndDate;
else return fourweekWeekendEndDate;
default:
if (peroid === 'ONEWEEK') return n1weekWeekendEndDate;
else if (peroid === 'TWOWEEK') return n2weekWeekendEndDate;
else if (peroid === 'THREEWEEK') return n3weekWeekendEndDate;
else return n4weekWeekendEndDate;
}
}