함정 시리즈

[JavaScript] new Date('YYYY-MM-DD')

노새두마리 2023. 12. 28. 02:24
new Date('2024-1-1') !== new Date('2024-01-01')

Date의 날짜 파싱

MDN 문서는 Date 생성자를 이용한 날짜 파싱이 일관적이지 않고 브라우저별로 동작이 상이하므로 사용하지 않을 것을 권장하고 있습니다. 위의 예시는 일관적이지 않은 파싱의 한 예시입니다.

비교 연산의 왼쪽 식은 우리나라의 시간대를 기준으로 2024년 1월 1일 0시가 됩니다. 우리나라 시간대는 그리니치 표준시(GMT)보다 9시간이 빠르므로 실제 반환되는 타임스탬프는 2023년 12월 31일 15시입니다.

new Date('2024-1-1').toISOString(); // 2023-12-31T15:00:00.000Z

node.js 환경에서 'YYYY'를 고정한 채로 1월 1일 ~ 12월 31일까지 확인하였을 때, 'YYYY-M-D', 'YYYY-MM-D', 'YYYY-M-DD' 형식은 위와 같음을 확인하였습니다.


반면에 오른쪽 식은 그리니치 표준시를 기준으로 2024년 1월 1일 0시입니다. 타임스탬프는 별도의 조정없이 2024년 1월 1일 0시 그대로 반환됩니다.

new Date('2024-01-01').toISOString(); // 2024-01-01T00:00:00.000Z

'YYYY-MM-DD' 형식일 때에는 이와 같이 반환되었습니다. 이와 같이 생성한 날짜는 우리나라 시각으로 오전 9시가 되어 버립니다.


예기치 못한 오차를 피하려면?

1. 문자열 이외의 방식으로 날짜 객체를 초기화합니다.

연, 월, 일, 시, 분, 초, 밀리초의 순서대로 전달인자를 이용하여 날짜를 생성할 수 있습니다. 연과 월은 필수로 전달해야 하며 나머지 인자는 옵션입니다.

여기에도 함정은 있으니 1월이 0부터 시작한다는 점입니다.

new Date(2024, 0, 1, 3, 28).toISOString(); // 2023-12-31T18:28:00.000Z

실행 결과, 이 방식은 위에서 살펴본 식의 왼쪽 식과 마찬가지로 우리나라 표준시가 반영되어 있습니다.


2. 문자열의 포맷을 전부 통일합니다.

const date = '2024-1-1';

date.split('-').map(str => str.padStart(2, '0')).join('-'); // '2024-01-01'

날짜 문자열을 'YYYY-MM-DD' 형식으로 변환할 수 있도록 하는 예시입니다.

  1. split: 주어진 date를 하이픈(-)을 기준으로 나누어 배열로 만듭니다. (['2024', '1', '1'])
  2. map: 배열의 요소를 순회하며 문자열의 길이가 2보다 작은 경우, 문자열의 길이가 2가 될 때까지 문자열 앞에 0을 채웁니다. (['2024', '01', '01'])
  3. join: 배열의 요소를 연결하여 하나의 문자를 만듭니다. 이 때, 요소의 사이사이에 하이픈이 삽입되도록 합니다. ('2024-01-01')

 


https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Date/Date

https://school.programmers.co.kr/questions/64951?referer=collection-of-questions