What is the Temporal API and why is it proposed as a replacement for Date?
Assesses fundamental understanding of JavaScript conventions, runtime behavior, and memory/performance considerations.
Hiring managers look for precision, avoidance of ambiguous jargon, and ability to explain trade-offs under real production conditions.
The Temporal API is a modern proposal (Stage 3) to replace JavaScript's problematic Date object. It provides a better, more intuitive way to work with dates and times in JavaScript.
Problems with Date:
// 1. Months are 0-indexed (January = 0, December = 11)
const date1 = new Date(2024, 0, 15); // January 15, 2024 (confusing!)
const date2 = new Date(2024, 12, 15); // Actually January 15, 2025 (overflow!)
// 2. Mutable (can lead to bugs)
const original = new Date('2024-01-15');
const modified = original;
modified.setMonth(5);
console.log(original); // Also changed! (unexpected)
// 3. Time zone confusion
const date3 = new Date('2024-01-15'); // Interprets as UTC
const date4 = new Date('2024-01-15T00:00:00'); // Interprets as local time!
// 4. Poor API design
date1.getYear(); // Returns 124 (not 2024!) - deprecated
date1.getFullYear(); // Returns 2024 (correct, but confusing naming)
// 5. No support for different calendar systems
// Can't work with Islamic, Hebrew, Chinese calendars, etc.
// 6. Limited date arithmetic
// Adding months is problematic
const jan31 = new Date(2024, 0, 31);
jan31.setMonth(jan31.getMonth() + 1); // Feb 31 -> Mar 2 (unexpected!)
Temporal API Types:
The Temporal API provides several specialized types:
Temporal.PlainDate- Date without time (e.g., birthdays, holidays)Temporal.PlainTime- Time without date (e.g., daily alarm)Temporal.PlainDateTime- Date and time without time zoneTemporal.ZonedDateTime- Date, time, and time zoneTemporal.Instant- Exact moment in time (like timestamps)Temporal.Duration- Length of timeTemporal.PlainYearMonth- Year and month (e.g., credit card expiry)Temporal.PlainMonthDay- Month and day (e.g., recurring anniversary)
Basic Examples:
// 1. Creating dates (intuitive month numbering!)
const date = Temporal.PlainDate.from('2024-01-15');
const date2 = Temporal.PlainDate.from({ year: 2024, month: 1, day: 15 });
console.log(date.toString()); // "2024-01-15"
console.log(date.month); // 1 (January is 1, not 0!)
// 2. Immutable (returns new instance)
const original = Temporal.PlainDate.from('2024-01-15');
const modified = original.add({ months: 1 });
console.log(original.toString()); // "2024-01-15" (unchanged)
console.log(modified.toString()); // "2024-02-15" (new instance)
// 3. Time zones (explicit and clear)
const zonedDateTime = Temporal.ZonedDateTime.from({
timeZone: 'America/New_York',
year: 2024,
month: 1,
day: 15,
hour: 10,
minute: 30
});
console.log(zonedDateTime.toString());
// "2024-01-15T10:30:00-05:00[America/New_York]"
// Convert to different time zone
const tokyo = zonedDateTime.withTimeZone('Asia/Tokyo');
console.log(tokyo.toString());
// "2024-01-16T00:30:00+09:00[Asia/Tokyo]"
// 4. Date arithmetic (smart handling)
const jan31 = Temporal.PlainDate.from('2024-01-31');
const nextMonth = jan31.add({ months: 1 });
console.log(nextMonth.toString()); // "2024-02-29" (handles leap year!)
// Different overflow strategies
const constrain = jan31.add({ months: 1 }, { overflow: 'constrain' });
console.log(constrain.toString()); // "2024-02-29"
const reject = jan31.add({ months: 1 }, { overflow: 'reject' });
// Throws RangeError: date doesn't exist
// 5. Duration calculations
const start = Temporal.PlainDate.from('2024-01-15');
const end = Temporal.PlainDate.from('2024-03-20');
const duration = start.until(end);
console.log(duration.toString()); // "P2M5D" (2 months, 5 days)
console.log(duration.total({ unit: 'days' })); // 65
Real-World Use Cases:
// 1. Birthday calculator
function getAge(birthDate) {
const today = Temporal.Now.plainDateISO();
const birth = Temporal.PlainDate.from(birthDate);
const age = birth.until(today, { largestUnit: 'years' });
return age.years;
}
console.log(getAge('1990-05-15')); // Current age
// 2. Business days calculation
function addBusinessDays(date, days) {
let current = Temporal.PlainDate.from(date);
let remaining = days;
while (remaining > 0) {
current = current.add({ days: 1 });
const dayOfWeek = current.dayOfWeek;
if (dayOfWeek !== 6 && dayOfWeek !== 7) { // Not weekend
remaining--;
}
}
return current;
}
console.log(addBusinessDays('2024-01-15', 5).toString());
// 3. Meeting scheduler (with time zones)
function scheduleMeeting(localTime, attendeeTimeZones) {
const meeting = Temporal.ZonedDateTime.from(localTime);
return attendeeTimeZones.map(tz => ({
timeZone: tz,
time: meeting.withTimeZone(tz).toString()
}));
}
const times = scheduleMeeting(
'2024-01-15T14:00:00[America/New_York]',
['America/Los_Angeles', 'Europe/London', 'Asia/Tokyo']
);
console.log(times);
// [
// { timeZone: 'America/Los_Angeles', time: '2024-01-15T11:00:00-08:00[America/Los_Angeles]' },
// { timeZone: 'Europe/London', time: '2024-01-15T19:00:00+00:00[Europe/London]' },
// { timeZone: 'Asia/Tokyo', time: '2024-01-16T04:00:00+09:00[Asia/Tokyo]' }
// ]
// 4. Recurring events
function getNextOccurrence(monthDay, fromDate) {
const target = Temporal.PlainMonthDay.from(monthDay);
const current = Temporal.PlainDate.from(fromDate);
let next = target.toPlainDate({ year: current.year });
if (Temporal.PlainDate.compare(next, current) <= 0) {
next = target.toPlainDate({ year: current.year + 1 });
}
return next;
}
console.log(getNextOccurrence('12-25', '2024-01-15').toString());
// "2024-12-25" (next Christmas)
// 5. Duration formatting
function formatDuration(start, end) {
const duration = Temporal.Instant.from(start)
.until(Temporal.Instant.from(end));
const hours = Math.floor(duration.total({ unit: 'hours' }));
const minutes = Math.floor(duration.total({ unit: 'minutes' }) % 60);
return `${hours}h ${minutes}m`;
}
console.log(formatDuration(
'2024-01-15T10:00:00Z',
'2024-01-15T13:45:00Z'
)); // "3h 45m"
// 6. Calendar systems
const gregorian = Temporal.PlainDate.from('2024-01-15');
const islamic = gregorian.withCalendar('islamic');
const hebrew = gregorian.withCalendar('hebrew');
console.log(gregorian.toString()); // "2024-01-15"
console.log(islamic.toString()); // "1445-07-04[u-ca=islamic]"
console.log(hebrew.toString()); // "5784-10-04[u-ca=hebrew]"
Comparison with Date:
// Date (old way)
const date = new Date();
date.setMonth(date.getMonth() + 1); // Mutates original
// Temporal (new way)
const temporal = Temporal.Now.plainDateISO();
const next = temporal.add({ months: 1 }); // Immutable
// Time zone conversions
// Date: Complex and error-prone
const dateNY = new Date('2024-01-15T10:00:00');
const dateUTC = new Date(dateNY.toISOString());
// Messy and unreliable
// Temporal: Clear and explicit
const temporalNY = Temporal.ZonedDateTime.from({
timeZone: 'America/New_York',
year: 2024, month: 1, day: 15,
hour: 10, minute: 0
});
const temporalUTC = temporalNY.withTimeZone('UTC');
Current Status and Usage:
// As of 2026, Temporal is Stage 3 (not yet in browsers by default)
// Use with a polyfill:
// npm install @js-temporal/polyfill
import { Temporal } from '@js-temporal/polyfill';
// Or use in browsers with feature detection:
if (typeof Temporal === 'undefined') {
// Fall back to Date or load polyfill
console.warn('Temporal not supported, using Date');
} else {
// Use Temporal
const date = Temporal.Now.plainDateISO();
}
Benefits of Temporal:
- ✅ Immutable: Safer, predictable behavior
- ✅ Intuitive API: Months start at 1, not 0
- ✅ Time Zone Aware: First-class time zone support
- ✅ Type Safe: Different types for different use cases
- ✅ Calendar Support: Works with non-Gregorian calendars
- ✅ Better Arithmetic: Smart date calculations
- ✅ ISO 8601: Native support for standard date format
- ✅ No Legacy Baggage: Clean slate, modern design
Candidate Response Strategy & Interview Tips
- Start with a concise one-sentence summary: Deliver a direct, confident answer first before expanding into nuances.
- Demonstrate real-world trade-offs: Discuss where this approach excels and when you would avoid it in production systems.
- Discuss complexity & edge cases: Proactively explain time/space complexity or boundary conditions (null values, scale limits).
- Prepare for interviewer follow-ups: Technical hiring panels frequently probe deeper into concurrency, backward compatibility, or alternative libraries.