Skip to content

Commit

Permalink
feat(utils): isDateInRange 함수 추가 (#654)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssi02014 authored Jan 3, 2025
1 parent cd87aec commit 7db2d20
Show file tree
Hide file tree
Showing 4 changed files with 517 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/swift-bananas-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@modern-kit/utils': minor
---

feat(utils): isDateInRange 함수 추가 - @ssi02014
84 changes: 84 additions & 0 deletions docs/docs/utils/date/isDateInRange.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# isDateInRange

타겟 날짜가 주어진 날짜 범위 내에 있는지 확인합니다.

타겟 날짜(targetDate)가 없을 경우 `현재 날짜`를 사용합니다.

<br />

## Code
[🔗 실제 구현 코드 확인](https://github.com/modern-agile-team/modern-kit/blob/main/packages/utils/src/validator/isDateInRange/index.ts)

## Interface
```ts title="typescript"
interface IsDateInRangeParams {
targetDate?: Date | string | number;
fromDate?: Date | string | number;
toDate?: Date | string | number;
inclusive?: 'both' | 'from' | 'to' | 'none';
}
```
```ts title="typescript"
function isDateInRange({
targetDate = new Date(),
fromDate,
toDate,
inclusive = 'from',
}: IsDateInRangeParams): boolean;
```

## Usage
### 기본 동작
- 타겟 날짜가 있다면 `타겟 날짜`가 범위 내에 있는지 확인하며, 타겟 날짜가 없다면 `현재 날짜`가 범위 내에 있는지 확인합니다.
```ts title="typescript"
import { isDateInRange } from '@modern-kit/utils';

// 현재 날짜가 2025년 01월 01일 기준
isDateInRange({ fromDate: new Date('2024-01-01'), toDate: new Date('2024-12-31') }); // false

isDateInRange({ fromDate: '2025-01-01', toDate: '2025-12-31' }); // true
isDateInRange({ targetDate: '2025-01-02', fromDate: '2025-01-01', toDate: '2025-01-03' }); // true
```

### 시작 날짜만 지정
- 시작 날짜만 지정하여 `타겟 날짜(or 현재 날짜)`가 시작 날짜 이후인지 확인합니다.
```ts title="typescript"
import { isDateInRange } from '@modern-kit/utils';

// 현재 날짜가 2025년 01월 01일 기준
isDateInRange({ fromDate: new Date('2025-01-02') }); // true
isDateInRange({ fromDate: '2024-12-31' }); // false

isDateInRange({ targetDate: '2025-01-02', fromDate: '2025-01-01' }); // true
```

### 종료 날짜만 지정
- 종료 날짜만 지정하여 `타겟 날짜(or 현재 날짜)`가 종료 날짜 이전인지 확인합니다.
```ts title="typescript"
import { isDateInRange } from '@modern-kit/utils';

// 현재 날짜가 2025년 01월 01일 기준
isDateInRange({ toDate: new Date('2025-01-02') }); // true
isDateInRange({ toDate: '2024-12-31' }); // false

isDateInRange({ targetDate: '2024-12-31', toDate: '2025-01-01' }); // true
```

### 경계값 포함 여부 지정
- `inclusive` 옵션에 따라 경계값 포함 여부를 확인합니다.
```ts title="typescript"
import { isDateInRange } from '@modern-kit/utils';

// 현재 날짜가 2025년 01월 01일 기준
isDateInRange({ fromDate: '2025-01-01', toDate: '2025-01-01', inclusive: 'both' }); // true
isDateInRange({ targetDate: '2025-01-01', fromDate: '2025-01-01', toDate: '2025-01-01', inclusive: 'both' }); // true

isDateInRange({ fromDate: '2025-01-01', toDate: '2025-01-02', inclusive: 'from' }); // true
isDateInRange({ targetDate: '2025-01-01', fromDate: '2025-01-01', toDate: '2025-01-02', inclusive: 'from' }); // true

isDateInRange({ fromDate: '2024-12-31', toDate: '2025-01-01', inclusive: 'to' }); // true
isDateInRange({ targetDate: '2025-01-01', fromDate: '2024-12-31', toDate: '2025-01-01', inclusive: 'to' }); // true

isDateInRange({ fromDate: '2024-12-31', toDate: '2025-01-02', inclusive: 'none' }); // true
isDateInRange({ targetDate: '2025-01-01', fromDate: '2024-12-31', toDate: '2025-01-02', inclusive: 'none' }); // true
```
130 changes: 130 additions & 0 deletions packages/utils/src/date/isDateInRange/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { isNil } from '../../validator/isNil';
import { isAfterDate } from '../isAfterDate';
import { isBeforeDate } from '../isBeforeDate';

interface IsDateInRangeParams {
targetDate?: Date | string | number;
fromDate?: Date | string | number;
toDate?: Date | string | number;
inclusive?: 'both' | 'from' | 'to' | 'none';
}

/**
* @description 타겟 날짜가 주어진 날짜 범위 내에 있는지 확인합니다. 타겟 날짜(targetDate)가 없을 경우 `현재 날짜`를 사용합니다.
*
* 1. 시작 날짜만 주어 질 경우 타겟 날짜(or 현재 날짜)가 시작 날짜 이후인지 확인합니다.
* 2. 종료 날짜만 주어 질 경우 타겟 날짜(or 현재 날짜)가 종료 날짜 이전인지 확인합니다.
* 3. 시작 날짜와 종료 날짜가 모두 주어 질 경우 타겟 날짜(or 현재 날짜)가 시작 날짜와 종료 날짜 사이에 있는지 확인합니다.
*
* @param {IsDateInRangeParams} params - 날짜 범위를 지정하는 파라미터 객체
* @param {Date | string | number} [params.targetDate=new Date()] - 타겟 날짜, 없을 경우 현재 날짜를 사용합니다.
* @param {Date | string | number} [params.fromDate] - 범위의 시작 날짜
* @param {Date | string | number} [params.toDate] - 범위의 종료 날짜
* @param {'both' | 'from' | 'to' | 'none'} [params.inclusive='from'] - 시작 날짜와 종료 날짜의 경계를 포함 할 지 여부를 결정합니다.
* - 'both': 시작 날짜와 종료 날짜 모두 포함합니다.
* - 'from': 시작 날짜만 포함합니다. (기본 값)
* - 'to': 종료 날짜만 포함합니다.
* - 'none': 시작 날짜와 종료 날짜 모두 포함하지 않습니다.
* @returns {boolean} 타겟 날짜가 범위 내에 있으면 true, 그렇지 않으면 false를 반환
* @throws {Error} 유효하지 않은 날짜 형식이 입력된 경우
*
* @example
* // 현재 날짜가 2025년 01월 01일 기준
* // 타겟 날짜가 있다면 타겟 날짜가 범위 내에 있는지 확인하며, 타겟 날짜가 없다면 현재 날짜가 범위 내에 있는지 확인합니다.
* isDateInRange({ fromDate: new Date('2024-01-01'), toDate: new Date('2024-12-31') }); // false
* isDateInRange({ fromDate: '2025-01-01', toDate: '2025-12-31' }); // true
* isDateInRange({ targetDate: '2025-01-02', fromDate: '2025-01-01', toDate: '2025-01-03' }); // true
*
* @example
* // 현재 날짜가 2025년 01월 01일 기준
* // 시작 날짜만 지정하여 타겟 날짜(or 현재 날짜)가 시작 날짜 이후인지 확인합니다.
* isDateInRange({ fromDate: new Date('2025-01-02') }); // true
* isDateInRange({ fromDate: '2024-12-31' }); // false
* isDateInRange({ targetDate: '2025-01-02', fromDate: '2025-01-01' }); // true
*
* @example
* // 현재 날짜가 2025년 01월 01일 기준
* // 종료 날짜만 지정하여 타겟 날짜(or 현재 날짜)가 종료 날짜 이전인지 확인합니다.
* isDateInRange({ toDate: new Date('2025-01-02') }); // true
* isDateInRange({ toDate: '2024-12-31' }); // false
* isDateInRange({ targetDate: '2024-12-31', toDate: '2025-01-01' }); // true
*
* @example
* // 현재 날짜가 2025년 01월 01일 기준
* // inclusive 옵션에 따른 경계값 포함 여부를 확인합니다.
* isDateInRange({ fromDate: '2025-01-01', toDate: '2025-01-01', inclusive: 'both' }); // true
* isDateInRange({ targetDate: '2025-01-01', fromDate: '2025-01-01', toDate: '2025-01-01', inclusive: 'both' }); // true
*
* isDateInRange({ fromDate: '2025-01-01', toDate: '2025-01-02', inclusive: 'from' }); // true
* isDateInRange({ targetDate: '2025-01-01', fromDate: '2025-01-01', toDate: '2025-01-02', inclusive: 'from' }); // true
*
* isDateInRange({ fromDate: '2024-12-31', toDate: '2025-01-01', inclusive: 'to' }); // true
* isDateInRange({ targetDate: '2025-01-01', fromDate: '2024-12-31', toDate: '2025-01-01', inclusive: 'to' }); // true
*
* isDateInRange({ fromDate: '2024-12-31', toDate: '2025-01-02', inclusive: 'none' }); // true
* isDateInRange({ targetDate: '2025-01-01', fromDate: '2024-12-31', toDate: '2025-01-02', inclusive: 'none' }); // true
*/
export function isDateInRange({
targetDate = new Date(),
fromDate,
toDate,
inclusive = 'from',
}: IsDateInRangeParams): boolean {
const fromDateToUse = fromDate ? new Date(fromDate) : null;
const toDateToUse = toDate ? new Date(toDate) : null;
const targetDateToUse = new Date(targetDate);

// 에러 케이스 대응
if (isNaN(targetDateToUse.getTime())) {
throw new Error('타겟 날짜가 유효하지 않은 날짜 형식입니다.');
}
if (!isNil(fromDateToUse) && isNaN(fromDateToUse.getTime())) {
throw new Error('시작 날짜가 유효하지 않은 날짜 형식입니다.');
}
if (!isNil(toDateToUse) && isNaN(toDateToUse.getTime())) {
throw new Error('종료 날짜가 유효하지 않은 날짜 형식입니다.');
}

// 날짜 비교 내부 함수
const compareDate = (date: Date, type: 'from' | 'to'): boolean => {
const isFrom = type === 'from';
const inclusiveToUse =
inclusive === 'both' ||
(isFrom ? inclusive === 'from' : inclusive === 'to');

// inclusive 옵션에 따라 날짜 범위 비교
if (isFrom) {
return isAfterDate({
targetDate: targetDateToUse,
compareDate: date, // fromDate
inclusive: inclusiveToUse,
});
}
return isBeforeDate({
targetDate: targetDateToUse,
compareDate: date, // toDate
inclusive: inclusiveToUse,
});
};

// 1. 시작 날짜만 주어 질 경우 타겟 날짜(or 현재 날짜)가 시작 날짜 이후인지 확인
if (fromDateToUse && !toDateToUse) {
return compareDate(fromDateToUse, 'from');
}

// 2. 종료 날짜만 주어 질 경우 타겟 날짜(or 현재 날짜)가 종료 날짜 이전인지 확인
if (!fromDateToUse && toDateToUse) {
return compareDate(toDateToUse, 'to');
}

// 3. 시작 날짜와 종료 날짜가 모두 주어 질 경우 타겟 날짜(or 현재 날짜)가 시작 날짜와 종료 날짜 사이에 있는지 확인
if (fromDateToUse && toDateToUse) {
if (isAfterDate({ targetDate: fromDateToUse, compareDate: toDateToUse })) {
throw new Error('시작 날짜가 종료 날짜보다 늦을 수 없습니다.');
}

return compareDate(fromDateToUse, 'from') && compareDate(toDateToUse, 'to');
}

return false;
}
Loading

0 comments on commit 7db2d20

Please sign in to comment.