Created
March 19, 2025 15:13
-
-
Save rkdgusrnrlrl/79b2b28d95c51bf41e99a9c0b0cd597f to your computer and use it in GitHub Desktop.
기간을 기준으로 기준 날짜, 비교할 날짜
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import moment from 'moment'; | |
| import { adjustDateWithDuration } from './date-utils'; | |
| describe('date-utils', () => { | |
| describe('adjustDateWithDuration', () => { | |
| it('차이가 duration 이내인 경우 원래 targetDate를 유지해야 한다', () => { | |
| // Arrange | |
| const baseDate = '20250315'; // YYYYMMDD 형식 | |
| const targetDate = '20250325'; // 10일 차이 | |
| const duration = moment.duration(14, 'days'); // 14일 기간 | |
| // Act | |
| const result = adjustDateWithDuration(baseDate, targetDate, duration); | |
| // Assert | |
| expect(result).toBe('20250325'); | |
| }); | |
| it('차이가 duration보다 큰 경우(양의 방향) 기준 날짜 + duration 값을 반환해야 한다', () => { | |
| // Arrange | |
| const baseDate = new Date(2025, 2, 15); // Date 객체 (2025-03-15) | |
| const targetDate = new Date(2025, 3, 15); // Date 객체 (2025-04-15), 31일 차이 | |
| const duration = moment.duration(14, 'days'); // 14일 기간 | |
| // Act | |
| const result = adjustDateWithDuration(baseDate, targetDate, duration); | |
| // Assert | |
| expect(result).toBe('20250329'); | |
| }); | |
| it('차이가 duration보다 큰 경우(음의 방향) 기준 날짜 - duration 값을 반환해야 한다', () => { | |
| // Arrange | |
| const baseDate = '20250415'; // YYYYMMDD 형식 | |
| const targetDate = '20250315'; // -31일 차이 | |
| const duration = moment.duration(-14, 'days'); // -14일 기간 | |
| // Act | |
| const result = adjustDateWithDuration(baseDate, targetDate, duration); | |
| // Assert | |
| expect(result).toBe('20250401'); | |
| }); | |
| it('두 날짜가 동일한 경우 원래 날짜를 유지해야 한다', () => { | |
| // Arrange | |
| const baseDate = '20250315'; // YYYYMMDD 형식 | |
| const targetDate = '20250315'; // YYYYMMDD 형식, 0일 차이 | |
| const duration = moment.duration(14, 'days'); // 14일 기간 | |
| // Act | |
| const result = adjustDateWithDuration(baseDate, targetDate, duration); | |
| // Assert | |
| expect(result).toBe('20250315'); | |
| }); | |
| it('duration이 0이면 항상 baseDate를 반환해야 한다', () => { | |
| // Arrange | |
| const baseDate = new Date(2025, 2, 15); // Date 객체 (2025-03-15) | |
| const targetDate = new Date(2025, 3, 15); // Date 객체 (2025-04-15), 31일 차이 | |
| const duration = moment.duration(0); // 0일 기간 | |
| // Act | |
| const result = adjustDateWithDuration(baseDate, targetDate, duration); | |
| // Assert | |
| expect(result).toBe('20250315'); | |
| }); | |
| it('복합 기간(년, 월, 일 등)도 처리할 수 있어야 한다', () => { | |
| // Arrange | |
| const baseDate = '20250315'; // YYYYMMDD 형식 | |
| const targetDate = '20260525'; // YYYYMMDD 형식, 1년 2개월 10일 차이 | |
| const duration = moment.duration({ months: 3, days: 15 }); // 3개월 15일 기간 | |
| // Act | |
| const result = adjustDateWithDuration(baseDate, targetDate, duration); | |
| // Assert | |
| expect(result).toBe('20250630'); | |
| }); | |
| it('음수 duration(년)을 처리할 수 있어야 한다', () => { | |
| // Arrange | |
| const baseDate = '20240102'; // YYYYMMDD 형식 | |
| const targetDate = '20221102'; // YYYYMMDD 형식, 1년 2개월 전 | |
| const duration = moment.duration({ years: -1, days: 1 }); // 1년 하루 전 | |
| // Act | |
| const result = adjustDateWithDuration(baseDate, targetDate, duration); | |
| // Assert | |
| expect(result).toBe('20230103'); | |
| }); | |
| it('잘못된 형식의 날짜 문자열을 거부해야 한다', () => { | |
| // Arrange | |
| const baseDate = '20250315'; // 올바른 형식 | |
| const targetDate = '2025-03-15'; // 잘못된 형식 (하이픈 포함) | |
| const duration = moment.duration(14, 'days'); | |
| // Act & Assert | |
| expect(() => { | |
| adjustDateWithDuration(baseDate, targetDate, duration); | |
| }).toThrow('날짜는 YYYYMMDD 형식의 문자열 또는 Date 객체여야 합니다.'); | |
| }); | |
| it('moment.Duration이 아닌 duration을 거부해야 한다', () => { | |
| // Arrange | |
| const baseDate = '20250315'; | |
| const targetDate = '20250325'; | |
| const duration = { days: 14 } as any; // moment.Duration이 아님 | |
| // Act & Assert | |
| expect(() => { | |
| adjustDateWithDuration(baseDate, targetDate, duration); | |
| }).toThrow('duration은 moment.Duration 객체여야 합니다.'); | |
| }); | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import moment from 'moment'; | |
| /** | |
| * 'YYYYMMDD' 형식의 문자열인지 확인하는 함수 | |
| * @param value 확인할 값 | |
| * @returns 'YYYYMMDD' 형식이면 true, 아니면 false | |
| */ | |
| const isValidYYYYMMDD = (value: string): boolean => { | |
| return /^\d{8}$/.test(value) && moment(value, 'YYYYMMDD', true).isValid(); | |
| }; | |
| /** | |
| * 'YYYYMMDD' 문자열 또는 Date 객체를 받아 Moment 객체로 변환 | |
| * @param date 'YYYYMMDD' 형식의 문자열 또는 Date 객체 | |
| * @returns Moment 객체 | |
| * @throws 유효하지 않은 입력 형식일 경우 에러 발생 | |
| */ | |
| const toMoment = (date: string | Date): moment.Moment => { | |
| if (date instanceof Date) { | |
| return moment(date); | |
| } | |
| if (typeof date === 'string' && isValidYYYYMMDD(date)) { | |
| return moment(date, 'YYYYMMDD'); | |
| } | |
| throw new Error('날짜는 YYYYMMDD 형식의 문자열 또는 Date 객체여야 합니다.'); | |
| }; | |
| /** | |
| * 두 날짜와 기간(duration)을 받아서 조건에 따라 날짜를 조정하는 함수 | |
| * @param baseDate 기준 날짜 (YYYYMMDD 형식의 문자열 또는 Date 객체) | |
| * @param targetDate 비교할 날짜 (YYYYMMDD 형식의 문자열 또는 Date 객체) | |
| * @param duration 기간 (moment.Duration 객체) | |
| * @returns 조정된 날짜 (YYYYMMDD 형식의 문자열) | |
| * @throws 유효하지 않은 입력 형식일 경우 에러 발생 | |
| */ | |
| export const adjustDateWithDuration = ( | |
| baseDate: string | Date, | |
| targetDate: string | Date, | |
| duration: moment.Duration | |
| ): string => { | |
| // 입력된 날짜들을 Moment 객체로 변환 | |
| const base = toMoment(baseDate); | |
| const target = toMoment(targetDate); | |
| // duration이 moment.Duration 객체인지 확인 | |
| if (!moment.isDuration(duration)) { | |
| throw new Error('duration은 moment.Duration 객체여야 합니다.'); | |
| } | |
| // duration이 0이면 항상 baseDate 반환 | |
| if (duration.asMilliseconds() === 0) { | |
| return base.format('YYYYMMDD'); | |
| } | |
| // 두 날짜 사이의 difference를 moment duration으로 계산 | |
| const diffDuration = moment.duration(target.diff(base)); | |
| // 날짜 차이(절대값)와 입력된 duration(절대값)을 비교 | |
| if (Math.abs(diffDuration.asMilliseconds()) > Math.abs(duration.asMilliseconds())) { | |
| // 날짜 차이가 duration보다 크면, 기준 날짜에 duration 적용 | |
| return base.clone().add(duration).format('YYYYMMDD'); | |
| } | |
| // 날짜 차이가 duration 이내라면 원래 targetDate 반환 | |
| return target.format('YYYYMMDD'); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment