프로그래밍/Node.js

[javascript] Intl.DateTimeFormat 클래스 이용 시, 발생한 RangeError

채윤아빠 2024. 6. 3. 00:31
728x90
반응형

문제점 및 증상

현재 시각을 지정한 로케일 및 시간대에 맞게 문자열로 변환하기 위하여 Intl.DateTimeFormat 클래스를 이용하던 중 다음과 같은 오류가 발생하였습니다.

$ node demo/locale_datetime_string.js
/app/modules/common/Consts.js:503
                }).format(date);
                   ^

RangeError: Provided date is not in valid range.
    at DateTimeFormat.__boundformat__ (native)
    at Object.getCurrentDateTimeString (/home/pi/JDTeckServer/app/modules/common/Consts.js:503:6)
    at Object. (/home/pi/JDTeckServer/demo/locale_datetime_string.js:3:28)
    at Module._compile (module.js:577:32)
    at Object.Module._extensions..js (module.js:586:10)
    at Module.load (module.js:494:32)
    at tryModuleLoad (module.js:453:12)
    at Function.Module._load (module.js:445:3)
    at Module.runMain (module.js:611:10)
    at run (bootstrap_node.js:394:7)

원인 분석 및 디버깅

다음은 문제가 된 Consts 소스 예시입니다.

var Consts = {
    /**
     * 현재 시각을 지정된 로케일 및 시간대를 반영하여 문자열로 반환합니다.
     * @param {string} locale 지역 정보 ; 로케일 ; 기본 = 미국
     * @param {string} timezone 시간대 ; timezone ; 기본 = 미국/동부표준시 EDT
     */
    getCurrentDateTimeString: function(locale = 'en-US', timezone = 'America/New_York') {
        const date_utc = Date();
        // console.log(`date_utc = ${date_utc} / locale = ${locale} / timezone = ${timezone}`);
        const dateFormatter = new Intl.DateTimeFormat(locale, {
            // dateStyle: 'full',
            timeStyle: 'long',
            weekday: 'long',
            year: 'numeric',
            month: 'long',
            day: 'numeric',
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit',
            timeZoneName: 'short',
            timeZone: timezone,
        });
        const date_str = dateFormatter.format(date_utc);
        return date_str;
    },

    USB:      "USB",
    ETHERNET: "ETHERNET",
};


특이한 점은 위 getCurrentDateTimeString() 함수가 거의 매번 "RangeError"가 발생하지만, 어떤 경우에는 또 발생하지 않는 경우도 있었습니다.

console.log() 함수를 이용하여 전달되는 매개변수를 출력해봐도 날짜는 이상이 없었고, 디버거로 watch 하여 변수 내용을 봐도 날짜는 이상이 없었습니다. (눈이 삐었었습니다.)

이렇게도 바꾸고 저렇게도 바꾸고 했는데, 아주 간단한 것이 원인이었습니다. ㅠ.ㅠ

결과적으로 문제는 Intl.DateTimeFormat 클래스의 format() 함수로 전달하는 매개변수가 Date 클래스의 객체였어야만 하는데, string 객체가 전달되어서 발생한 것이었습니다.

조금 더 직관적으로 살펴보자면, 다음 코드를 보시면 바로 알 수 있습니다.

d1 = Date();
console.log(`d1 = ${d1}. d1's type is ${typeof(d1)}`);
d2 = new Date();
console.log(`d2 = ${d2}. d2's type is ${typeof(d2)}`);


위 코드의 실행 결과는 다음과 같습니다.

d1 = Mon Aug 12 2024 21:05:00 GMT+0900 (한국 표준시). d1's type is string
d2 = Mon Aug 12 2024 21:05:00 GMT+0900 (한국 표준시). d2's type is object

변수의 내용만 보면 동일한 날짜라 문제가 없는 줄 알고 왜 안되지 하고 헤맸던 것이었습니다. ㅠ.ㅠ

변명을 하자만, 파이썬을 쓰다가 이렇게 자바스크립트를 쓰면 "new" 지시자가 안적혀 있는 것도 정상으로 인식하게 되는 문제가... 

아무튼 이 문제로 몇 시간을 삽질을 했는지... VS code에서 "new" 지시자가 안적혀 있는 경우 warning이라도 표시해 주었다면 조금 더 빨리 찾았을 것인데... 하는 아쉬움이 있었습니다.

이상 Date 객체에 대한 삽질기였습니다. ^^;


참고자료