1/17/2024

날짜 비교

발단

Redis 강의에서 상품의 날짜와 오늘을 비교해서 날짜를 비교하는 연산을 어떻게 수행해야 하는지를 보여주는데 갑자기 Wevre가 떠올랐다. 경매방은 오늘과 상품의 경매 시작 날짜와 경매 종료 날짜를 기반으로 크론 작업으로 자동으로 생성되고 삭제된다. 처음에는 그냥 단순하게 Moment 패키지의 메서드를 사용했는데 강의의 방법이 훨씬 더 간편하고 효율적인 것 같아서 바로 수정했다!


Moment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
async create() {
  ...
 
  try {
    const items = await this.itemsModel.find();
 
    for (const item of items) {
      // 타입은 Date
      const startDate = item.startDate;
      const endDate = item.endDate;
      
      ...
      
      const today = moment(new Date());
      // Moment 패키지의 isBetween() 메서드로 날짜를 비교한다.
      if (today.isBetween(startDate, endDate)) {
        
          ...
      }
    }
 
    ...
  } catch (error) {
    ...
  } finally {
    ...
  }
}
cs
코드를 보면 알 수 있듯이 Date 타입인 시작 날짜와 종료 날짜를 데이터베이스에서 가져오고 Moment 패키지의 isBetween() 메서드로 날짜를 비교한다. 하지만 만약 Moment 패키지를 사용할 수 없다면 어떻게 해야할까? 데이터베이스에 저장된 날짜는 ISO 8601 형식(yyyy-MM-dd'T'HH:mm:ss.SSS'Z', 2024-01-16T14:25:12.800Z)을 가진다. 연, 월, 일, 시간과 같이 하나씩 비교하는 구현하기에 힘들고 무엇보다 오류가 발생할 가능성이 매우 높다. 

날짜를 특정 값을 가지는 숫자로 변환하고 숫자끼리 비교하는 것이 훨씬 간편하고 효율적일 것이다. 그런데 날짜를 어떻게 숫자로 변환할까? 바로 UNIX 시대(epoch)를 사용한다! UNIX 시대는 1970년 1월 1일 자정 UTC를 말하면 대부분의 프로그래밍 언어는 이 날을 기준점으로 날짜를 계산한다. 즉, UNIX 시대 이후 경과한 시간을 밀리초로 표시하여 날짜를 표현한다. 이렇게 변환된 타임스탬프는 시간대에 독립적이며 특정 순간을 고유하게 식별한다. JavaScript의 Date 객체가 getTime() 메서드가 날짜를 숫자로 변환한다.


Date.getTime()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
async create() {
  ...
 
  try {
    const { items } = await this.itemsRepository.findAll();
 
    for (const item of items) {
 
      const startDate = item.startDate;
      const endDate = item.endDate;
 
      // 타입은 number
      const todayMs = Date.now();
      const startDateMs = startDate.getTime();
      const endDateMs = endDate.getTime();
 
      if (startDateMs <= todayMs && todayMs <= endDateMs) {
        const filter = buildFilter('item._id', item._id);
        let room = await this.findOne(filter);
        ...
      }
    }
 
    ...
  } catch (error) {
    ...
  } finally {
    ...
  }
}
cs
수정된 코드를 보면 훨씬 간단하다! getTime() 메서드로 날짜를 숫자로 변환하고 비교 연산자를 사용해서 비교 연산을 수행한다. 사실 강의를 듣기 전에는 이러한 방법 자체가 생각나지 않았다. 앞서 말한것처럼 단순하게 연, 월, 일과 같이 날짜를 구성하는 요소를 하나씩 비교해야 한다고 생각했다. 쉽지는 않지만 항상 다른 관점에서 생각하는 것이 중요하다!

update: 2024.01.17

댓글 없음:

댓글 쓰기