ECMAScript에 추가된 변화 중 가장 마음에 드는 것은 Temporal 제안입니다. 이 제안은 매우 진보된 기능을 제공하며, 이미 FullCalendar 팀에서 제공하는 폴리필을 통해 사용할 수 있습니다.
이번 포스트에서는 "Zoned Date Time"이라는 개념을 설명하는 데 중점을 두겠습니다.
"Zoned Date Time"은 무엇일까요?
우리는 보통 시간을 얘기할 때 시간대를 생략하곤 합니다. 이는 대화 상대가 서로 어느 시간대를 기준으로 말하고 있는지 알고 있기 때문에 가능한 일입니다.
그러나 아쉽게도 컴퓨터에서는 자바스크립트의 Date 객체를 사용할 때 숫자로만 처리됩니다.
공식 specification 에서는 이렇게 명시합니다.
"An ECMAScript time value is a Number, either a finite integral Number representing an instant in time to millisecond precision or NaN representing no specific instant"
"ECMAScript 시간 값은 밀리초 단위로 특정 순간을 나타내는 유한한 정수 또는 특정 순간을 나타내지 않는 NaN 값으로 정의된 숫자입니다."
이 때문에 시간대 정보가 없어지며, 날짜의 원래 의미가 손실됩니다. 이는 동일한 자바스크립트 날짜 객체를 다른 시간대로 읽으면 서로 다른 시간으로 해석될 수 있다는 문제를 야기합니다.
자바스크립트의 날짜는 UTC가 아닌 POSIX 표준을 따르며, 윤초를 무시한다는 중요한 사실 외에도, 숫자로만 날짜를 표현할 때 원래의 의미가 손실됩니다.
예를 들어, 브라우저가 CET 시간대에 있을 때, 특정 날짜와 시간을 기록하려면 Date 객체가 해당 시간대에서 경과한 밀리초를 계산합니다. 하지만 동일한 객체를 다른 시간대에서 읽으면 다른 시간이 표시됩니다.
이로 인해, Date 객체는 항상 동일한 의미를 전달하지 못합니다.
예를 들어 CET timezone 에서 입력한 하기 날짜는
const paymentDate = new Date('2024-07-20T10:30:00');
CET 에 따라 아래와 같이 변환됩니다.
paymentDate.getTime(); // 1721464200000
이를 CET 시간에서 읽으면 10:30분이 되고,
d.toLocaleString() // '20/07/2024, 10:30:00'
ISO 형식으로 읽으면 8:30이 됩니다.
d.toISOString()// '2024-07-20T08:30:00.000Z'
ISO 형식으로 날짜를 저장할 때 오프셋을 포함하더라도, 그 날짜를 표시할 때는 UNIX epoch 이후로 경과된 밀리초와 오프셋만 알 수 있습니다. 그러나 이 정보만으로는 결제가 이루어진 정확한 시간대와 인간이 인식하는 시점을 알 수 없습니다. 예를 들어, 동일한 타임스탬프를 기준으로 여러 개의 인간이 읽을 수 있는 날짜가 존재할 수 있습니다.
다시 말해, 타임스탬프를 인간이 읽을 수 있는 날짜로 변환하는 함수는 일대일 대응(injective)이 아닙니다. 즉, 동일한 타임스탬프는 여러 개의 인간 날짜로 해석될 수 있습니다. 이는 타임스탬프와 인간이 인식하는 날짜 사이의 불일치를 의미합니다.
ISO 날짜를 저장할 때도, 타임스탬프와 ISO 형식은 같은 순간을 나타내는 두 가지 표현일 뿐입니다. 서로 다른 시간대가 동일한 오프셋을 가질 수 있기 때문에, 오프셋을 사용해도 문제가 발생합니다.
...은행이 모든 거래를 UTC로 저장하고, 애플리케이션이 이를 휴대폰의 시간대로 변환한다는 사실을 알게 된 것입니다. 이러한 상황이 우스꽝스럽게 들릴 수도 있지만, 하루에 한 번 무료 인출 프로모션이 있다면, 그 날이 언제 시작되고 끝나는지가 복잡해질 수 있습니다. 이러한 타임스탬프 문제는 이제 해결책이 있습니다.
새로운 Temporal API는 Temporal.ZonedDateTime 객체를 도입하여 시간대 정보를 포함한 날짜와 시간을 정확하게 표현할 수 있도록 설계되었습니다. 또한, RFC 3339의 확장을 제안하여 날짜 문자열의 직렬화와 역직렬화를 표준화합니다. 이 객체는 전 세계적으로 일관된 시간 관리를 가능하게 하며, 다양한 시간대와 달력을 다루는 데 유용한 도구입니다.

1996-12-19T16:39:57-08:00[America/Los_Angeles]
예를 들어, 위 문자열은 1996년 12월 19일 오후 4시 39분 57초를 나타내며, UTC에서 -08:00의 오프셋을 가지는 시간대("태평양 표준시")를 포함한 문자열입니다. 이 문자열은 시간대 인식을 필요로 하는 애플리케이션에서 사용됩니다.
추가로, 이 API 는 아래와 같은 다른 시간대에 적용이 가능합니다.
buddhist, chinese, coptic, dangi, ethioaa, ethiopic, gregory, hebrew, indian, islamic, islamic-umalqura, islamic-tbla, islamic-civil, islamic-rgsa, japanese, persian, roc
이 중에서 가장 일반적으로 사용될 것은 ISO 8601입니다. 이는 그레고리력의 표준화된 형태로, 대부분의 경우에 사용됩니다. 이 표준은 날짜와 시간을 명확하게 표현하는 데 널리 사용되며, 다양한 애플리케이션에서 일관된 시간 관리를 위해 주로 활용됩니다.