Contents
see ListJavaScript 개발자를 오랫동안 괴롭혀온 Date 객체의 시대가 드디어 저물고 있습니다. ES2026에서 정식 도입되는 Temporal API는 불변 객체, 타임존 퍼스트 클래스 지원, 비그레고리력 캘린더 등 현대적인 날짜/시간 처리의 모든 것을 제공합니다. moment.js나 date-fns 같은 라이브러리 없이도 복잡한 날짜 연산을 정확하게 수행할 수 있습니다.
Date 객체의 한계
기존 Date 객체는 1995년 Java의 java.util.Date를 그대로 복사한 것으로, 태생적 결함이 많습니다.
// Date 객체의 문제점들
const date = new Date(2026, 0, 1); // 월이 0부터 시작 (0 = 1월)
date.setMonth(12); // 13월? -> 다음 해 1월로 자동 변환
// 뮤터블 - 원본이 변경됨
const original = new Date('2026-04-04');
const modified = original;
modified.setDate(10);
console.log(original.getDate()); // 10 - 원본도 변경!
// 타임존 처리 불가
// UTC나 로컬 타임존만 지원, 임의 타임존 변환 불가능Temporal API 핵심 타입
Temporal은 용도에 따라 명확하게 구분된 여러 타입을 제공합니다.
Temporal.PlainDate - 날짜만
// 날짜만 다루기 (시간 정보 없음)
const today = Temporal.PlainDate.from('2026-04-04');
const birthday = Temporal.PlainDate.from({ year: 1990, month: 3, day: 15 });
// 불변 - 항상 새 객체 반환
const nextWeek = today.add({ days: 7 });
console.log(today.toString()); // 2026-04-04 (원본 유지)
console.log(nextWeek.toString()); // 2026-04-11
// 날짜 비교
console.log(Temporal.PlainDate.compare(today, nextWeek)); // -1
console.log(today.equals(nextWeek)); // false
// 유용한 속성들
console.log(today.dayOfWeek); // 6 (토요일)
console.log(today.daysInMonth); // 30 (4월)
console.log(today.daysInYear); // 365
console.log(today.weekOfYear); // 14Temporal.PlainTime - 시간만
const lunchTime = Temporal.PlainTime.from('12:30:00');
const meetingEnd = lunchTime.add({ hours: 1, minutes: 30 });
console.log(meetingEnd.toString()); // 14:00:00
// 나노초 정밀도 지원
const precise = Temporal.PlainTime.from('10:30:00.123456789');
console.log(precise.nanosecond); // 789Temporal.PlainDateTime - 날짜 + 시간 (타임존 없음)
const appointment = Temporal.PlainDateTime.from('2026-04-04T14:30:00');
const rescheduled = appointment.add({ hours: 2, days: 1 });
console.log(rescheduled.toString()); // 2026-04-05T16:30:00Temporal.ZonedDateTime - 타임존 포함 완전한 시간
// 타임존 지정 - IANA 타임존 이름 사용
const seoulMeeting = Temporal.ZonedDateTime.from({
year: 2026, month: 4, day: 4,
hour: 14, minute: 0,
timeZone: 'Asia/Seoul'
});
// 다른 타임존으로 변환
const nyTime = seoulMeeting.withTimeZone('America/New_York');
console.log(nyTime.toString());
// 2026-04-04T01:00:00-04:00[America/New_York]
const londonTime = seoulMeeting.withTimeZone('Europe/London');
console.log(londonTime.toString());
// 2026-04-04T06:00:00+01:00[Europe/London]
// DST(서머타임) 자동 처리
const beforeDST = Temporal.ZonedDateTime.from(
'2026-03-08T01:30:00[America/New_York]'
);
const afterAdd = beforeDST.add({ hours: 2 });
// 서머타임 전환을 자동으로 처리기간과 차이 계산
// Temporal.Duration - 기간 표현
const projectDuration = Temporal.Duration.from({
months: 3, weeks: 2, days: 5
});
console.log(projectDuration.total({ unit: 'days' }));
// 두 날짜 사이의 차이
const start = Temporal.PlainDate.from('2026-01-15');
const end = Temporal.PlainDate.from('2026-04-04');
const diff = start.until(end);
console.log(diff.toString()); // P2M17D (2개월 17일)
console.log(diff.months); // 2
console.log(diff.days); // 17
// 가장 큰 단위 지정
const diffInDays = start.until(end, { largestUnit: 'day' });
console.log(diffInDays.days); // 79
// since는 반대 방향
const ago = end.since(start);
console.log(ago.toString()); // P2M17D실전: D-Day 카운터 구현
function getDDay(targetDateStr) {
const today = Temporal.Now.plainDateISO();
const target = Temporal.PlainDate.from(targetDateStr);
const diff = today.until(target, { largestUnit: 'day' });
if (diff.sign === -1) {
return `D+${Math.abs(diff.days)}`;
} else if (diff.days === 0) {
return 'D-Day';
} else {
return `D-${diff.days}`;
}
}
console.log(getDDay('2026-12-25')); // D-265
console.log(getDDay('2026-01-01')); // D+93실전: 글로벌 미팅 스케줄러
function scheduleMeeting(dateTime, hostTimeZone, attendeeTimeZones) {
const meeting = Temporal.ZonedDateTime.from({
...Temporal.PlainDateTime.from(dateTime),
timeZone: hostTimeZone
});
const schedule = attendeeTimeZones.map(tz => {
const local = meeting.withTimeZone(tz);
const hour = local.hour;
const isWorkHours = hour >= 9 && hour < 18;
return {
timezone: tz,
localTime: local.toPlainDateTime().toString().slice(0, 16),
isWorkHours
};
});
return schedule;
}
const result = scheduleMeeting(
'2026-04-04T10:00',
'Asia/Seoul',
['America/New_York', 'Europe/London', 'Asia/Tokyo']
);
console.log(result);
// [
// { timezone: 'America/New_York', localTime: '2026-04-03T21:00', isWorkHours: false },
// { timezone: 'Europe/London', localTime: '2026-04-04T02:00', isWorkHours: false },
// { timezone: 'Asia/Tokyo', localTime: '2026-04-04T10:00', isWorkHours: true }
// ]폴리필 및 마이그레이션
브라우저 네이티브 지원이 완료되기 전에 @js-temporal/polyfill 패키지로 즉시 사용할 수 있습니다.
npm install @js-temporal/polyfill
// 사용
import { Temporal } from '@js-temporal/polyfill';
const now = Temporal.Now.zonedDateTimeISO();Temporal API는 JavaScript의 가장 오래된 약점 중 하나였던 날짜/시간 처리를 완전히 새롭게 재설계한 것입니다. 불변성, 타입 안전성, 타임존 퍼스트 클래스 지원은 모든 JavaScript 개발자가 오래 기다려온 기능입니다. 새 프로젝트에서는 Temporal API를 기본으로 채택하는 것을 강력히 권장합니다.