The Temporal API - a new era in JavaScript date and time handling
Published on
Updated on
The Temporal API is a feature that many
developers have been eagerly awaiting. It fixes many
problems and inconveniences of the old
Date
object.
What's wrong with JavaScript's Date object?
Before jumping into the Temporal API, let's first dig a little bit into the history of the Date
object and understand what problems it has.
JavaScript's original Date class was introduced in 1995 as part of the initial release of the
language. Under intense time pressure (reportedly only 10 days to create JavaScript), Brendan Eich based its design
on Java's early java.util.Date class to fulfill the requirement for date/time handling. This decision
was made to "make it like Java", but Java's date implementation at the time was deeply flawed. Many of
java.util.Date's date-component methods were deprecated in Java 1.1 (1997) in favor of
Calendar. JavaScript, however, became stuck with this inherited API for decades, as web compatibility
concerns prevented drastic changes.
From the start, the JavaScript Date object had a number of quirks and design mistakes. One
notorious example was
the
getYear()
method, which returned the year minus 1900 (so the year 2000 would return 100, and 1995 returned 95).
This odd behavior, a remnant of the Java API, led to confusion and potential Year-2000 bugs. It was later
effectively replaced by
getFullYear()
(which returns the full year), and getYear() was deprecated. This early mishap was a sign of deeper issues that would continue
to plague
date-handling in JavaScript.
Major limitations and inconsistencies of the Date class
Over the years, developers identified numerous limitations, inconsistencies, and bugs in the Date
API. Many of
these stem from the API's original design and have proven very difficult to fix without breaking the web. Some
of the major issues are outlined below:
- Limited time zone support. A
Datestores only a timestamp. When reading or changing its date/time components through its built-in methods, developers can work only in the user's local system time or UTC (Coordinated Universal Time). ADatecannot retain or manipulate an arbitrary IANA time zone (like "America/New_York" or "Asia/Tokyo"), althoughIntl.DateTimeFormatcan format it for display in one. Zone-aware construction, arithmetic, and future scheduling therefore require additional logic or external libraries. The lack of first-class time zone support is one of the biggest problems with theDateAPI.
-
Daylight saving time (DST) pitfalls. Related to time zones, daylight saving time transitions
are notoriously problematic with the
DateAPI. When clocks shift forward or back, certain local times either do not exist or occur twice, andDateprovides no option for choosing how those ambiguities are resolved. As a result, local-time arithmetic across DST boundaries can yield surprising results. For example, adding one calendar day withsetDate()may advance the underlying timestamp by 23 or 25 hours, although adding exactly 24 hours in milliseconds always advances it by 24 hours. A local time that does not exist is automatically shifted to a valid time, while a time during the repeated "fall back" hour is ambiguous. DST-related bugs therefore remain common in real-world usage due to the lack of high-level, explicit support inDate.
-
Mutability and side effects. JavaScript
Dateinstances are mutable objects. All "setter" methods (such assetHours(),setDate(), etc.) modify the originalDateobject in place. This mutability frequently leads to unintended side effects. For instance, if aDateobject is passed into a function or stored in multiple places, callingsetMonth()orsetSeconds()on it will change the value everywhere, often causing bugs that are hard to trace. A common pitfall is accidentally modifying a date that should have been cloned. For example, a function meant to schedule a notification might dodate.setHours(date.getHours() + 1)internally. If the original date object was passed in, it is now changed, impacting code elsewhere. Modern programming practices often favor immutable date/time values (as seen in libraries like Luxon or in languages like Python'sdatetimeand Java'sjava.time), precisely to avoid these issues. However, theDateAPI's design predates these conventions and thus can introduce subtle bugs when dates are inadvertently mutated.
-
Inconsistent and unreliable parsing. The behavior of
Date.parse()and the Date string constructor is notoriously inconsistent across environments. While the ECMAScript spec defines certain formats (e.g. a simplified ISO 8601 format) that should parse uniformly, many other date string formats are either implementation-dependent or outright discouraged. For example,new Date("2025-02-06")is a standardized date-only form and is interpreted as UTC, whilenew Date("2025-02-06T12:00")is interpreted in the local time zone because it has a time but no offset. A similar string with slashes,new Date("2025/02/06"), is non-standard and may be interpreted differently or rejected across browsers. A format like "06-02-2025" is similarly ambiguous and implementation-dependent. Because of these quirks, parsing anything but a strictly specified format becomes a gamble. The spec itself once left parsing of non-standard formats largely up to the implementation, resulting in web incompatibilities.
-
API design quirks (zero-based months, etc.). The
DateAPI includes several design choices that consistently trip up developers. One well-known quirk is that month numbers are zero-indexed - e.g., January is month 0 and December is 11. This is unlike how months are usually represented in human contexts (1 through 12) and has been a source of off-by-one errors for countless developers. The day of the month is one-based while the month is zero-based, an inconsistency one must memorize. Another historical quirk, as mentioned earlier, was the now-deprecatedgetYear()method (which returned an offset from 1900) vs.getFullYear()- a confusing split that exists only becausegetYear()behaved incorrectly by design. Additionally, performing date arithmetic with the old API is clunky: there are no straightforward methods for adding days or months, so developers had to write code likedate.setDate(date.getDate() + 7)just to add a week. This unwieldy API for computations makes code harder to read and can introduce errors (for example, forgetting thatsetDate()mutates the object, or that adding days might cause month wraparound). These design flaws reflect the rush of the initial implementation and have been cemented by backward compatibility requirements.
How does the Temporal API solve these problems?
The Temporal API is designed as a comprehensive replacement for Date, tackling its deficiencies
head-on. It
introduces a suite of new immutable date/time objects and utility methods that cover a wide range of use cases.
Some of the key goals and improvements of Temporal include:
- First-class time zone support.
- Immutability.
- Consistent parsing and ISO 8601 support.
- Finer precision and extended range.
The Temporal API separates date and time concepts and introduces the following main classes and concepts:
-
Temporal.PlainDate. A calendar date with no time or time zone attached. -
Temporal.PlainTime. A wall-clock time with no associated date or time zone. -
Temporal.PlainMonthDay. A month and day of a calendar date, without a year or time zone. -
Temporal.PlainYearMonth. A year and month of a calendar date, without a day (no day-of-month) or time zone. -
Temporal.PlainDateTime. A date and time (together) without a time zone. -
Temporal.ZonedDateTime. A date and time with an associated time zone. -
Temporal.Instant. A specific point on the global timeline. -
Temporal.Duration. A time span or difference between two temporal points. - Calendar systems.
Temporal.PlainDate
Temporal.PlainDate represents just a year-month-day date on the calendar (for example, a birthday
or holiday date) without any clock time. This can be used when you need to work with dates in an abstract sense,
without scheduling to a specific hour or tying it to a particular time zone.
In the code below, we create a Temporal.PlainDate for May 23, 2025. We then add 7 days to it to get
the date one
week later, demonstrating date arithmetic. Notice that adding days does not affect any time (since none is
present) and the result is a new PlainDate (Temporal objects are immutable):
const date = Temporal.PlainDate.from("2025-05-23"); // Create a date (YYYY-MM-DD)
console.log(date.toString()); // "2025-05-23"
const oneWeekLater = date.add({ days: 7 }); // Add 7 days to the date
console.log(oneWeekLater.toString()); // "2025-05-30"
If we want the current Temporal.PlainDate, we can get it via
Temporal.Now.plainDateISO():
const currentPlainDate = Temporal.Now.plainDateISO();
console.log(currentPlainDate.toString()); // Current date without time (current time zone)
const currentPlainNewYorkDate = Temporal.Now.plainDateISO("America/New_York");
console.log(currentPlainNewYorkDate.toString()); // Current New York date without time
Temporal.PlainTime
Temporal.PlainTime represents a time of day (hours, minutes, seconds, fractions) independent of any
specific
date. It can be used for daily or clock-based times that recur every day or for representing a specific time of
day in an abstract sense.
In the code below we create two Temporal.PlainTime instances for a start and end time, then
calculate the
duration between them. This might represent a work day or the length of an event in hours and minutes:
const startTime = Temporal.PlainTime.from("09:00:00"); // 9:00 AM
const endTime = Temporal.PlainTime.from("17:30:00"); // 5:30 PM
// Calculate the duration between the two times:
const workedDuration = endTime.since(startTime);
console.log(workedDuration.toString()); // "PT8H30M" (8 hours 30 minutes)
Temporal.PlainMonthDay
Temporal.PlainMonthDay is the month and day of a calendar date, without a year or time zone. In
other words, it is essentially the month-day portion of a full date (like July 4 or December 25) with no
associated year. PlainMonthDay is useful for scenarios like:
- Yearly recurring events: birthdays, anniversaries, holidays (e.g. December 25th) that occur on the same month/day each year.
- Month-day patterns: any date that should be treated without regard to year (for example, a schedule that repeats every year on 07-04).
Because it has no year, a PlainMonthDay is a partial date and has some limitations: it cannot be
directly added
to or subtracted from (no arithmetic like "+ 1 day") and cannot be meaningfully ordered without a reference
year.
Here are a few examples of using Temporal.PlainMonthDay:
// Month code + day
const md = Temporal.PlainMonthDay.from({ monthCode: "M05", day: 2 });
console.log(md.toString()); // 05-02
// Month + day (only for ISO calendar)
const md2 = Temporal.PlainMonthDay.from({ month: 7, day: 1 });
console.log(md2.toString()); // 07-01
// Year + month + day
const md3 = Temporal.PlainMonthDay.from({ year: 2021, month: 7, day: 1 });
console.log(md3.toString()); // 07-01
Temporal.PlainYearMonth
Temporal.PlainYearMonth represents the year and month of a calendar date, without a day (no
day-of-month) or
time zone. In other words, it is essentially the year-month portion of a date. For example, "2025-07" would
represent
July 2025 as a whole, with no specific day included. This type is useful for cases where you want to work with
or refer to an entire month or a year-month combination, rather than a specific date.
PlainYearMonth is useful for scenarios like:
- Monthly periods or schedules: representing an entire month in a given year (e.g. a billing period of June 2024, or a monthly report period).
- Recurring yearly month-based events: something that happens every year in a particular month regardless of day (e.g. a fiscal year starting in July each year, or a sale that lasts the whole December each year).
- Storing year-month data: cases like credit card expiration dates (which are often just month/year), or UI inputs where a user selects a month and year without a specific day.
Here are some examples of using Temporal.PlainYearMonth:
// Create a PlainYearMonth for July 2023 (2023-07) in the ISO calendar
const ym = Temporal.PlainYearMonth.from({ year: 2023, month: 7 });
console.log(ym.toString());
// → "2023-07"
// Access year and month properties
console.log(`Year: ${ym.year}, Month: ${ym.month}`);
// → "Year: 2023, Month: 7"
// Query calendar information
console.log(`Days in month: ${ym.daysInMonth}`);
// → "Days in month: 31" (July 2023 has 31 days)
console.log(`Is leap year? ${ym.inLeapYear}`);
// → "Is leap year? false" (2023 is not a leap year)
// Add and subtract to navigate through months/years
console.log(ym.add({ months: 1 }).toString());
// → "2023-08" (one month later is August 2023)
console.log(ym.add({ years: 1 }).toString());
// → "2024-07" (one year later is July 2024)
console.log(ym.subtract({ months: 7 }).toString());
// → "2022-12" (seven months earlier, wrapping into the previous year)
// Compare two YearMonth values
const dec2021 = Temporal.PlainYearMonth.from("2021-12");
const jan2022 = Temporal.PlainYearMonth.from("2022-01");
console.log(Temporal.PlainYearMonth.compare(dec2021, jan2022));
// → -1 (2021-12 comes before 2022-01)
console.log(dec2021.equals(jan2022));
// → false (they are different year-months)
// Converting a PlainYearMonth to a full date by specifying a day:
const firstOfMonth = ym.toPlainDate({ day: 1 });
console.log(firstOfMonth.toString());
// → "2023-07-01" (PlainDate for July 1, 2023)
Temporal.PlainDateTime
Temporal.PlainDateTime combines a calendar date and a wall-clock time into a single object. It's
a time-zone-unaware local date-time (year, month, day, hour, minute, second, etc.), not anchored to a
specific time zone. For example, it could represent "2025-12-31T23:30" as a local date-time, without saying
whether that is 11:30 PM in New York, London, or Tokyo. PlainDateTime is useful for scenarios where
you need
a complete
date-and-time but in a generic or local sense. This is ideal for scheduled events whose actual moment in time
depends on a time zone context.
In the code below, we create a Temporal.PlainDateTime for December 31, 2025 at 23:30 (11:30 PM). We
then add 1
hour to it. Because PlainDateTime isn't aware of time zones, the arithmetic is simple: adding an
hour rolls the
time into the next day (January 1, 2026). This shows how date and time components interact in a
PlainDateTime:
const localDateTime = Temporal.PlainDateTime.from("2025-12-31T23:30:00");
console.log(localDateTime.toString()); // "2025-12-31T23:30:00"
const plusOneHour = localDateTime.add({ hours: 1 });
console.log(plusOneHour.toString()); // "2026-01-01T00:30:00"
Similarly to Temporal.PlainDate, if we want the current Temporal.PlainDateTime, we can
get it via
Temporal.Now.plainDateTimeISO():
const currentPlainDateTime = Temporal.Now.plainDateTimeISO();
console.log(currentPlainDateTime.toString()); // Current date + time (current time zone)
const currentPlainNewYorkDateTime = Temporal.Now.plainDateTimeISO("America/New_York");
console.log(currentPlainNewYorkDateTime.toString()); // Current New York date + time
Temporal.ZonedDateTime
Temporal.ZonedDateTime is a timestamp that includes a time zone and calendar, effectively
pinpointing a unique
instant in time while also providing the local date/time representation for a specific zone. Internally, it
combines three pieces: an exact Instant in time, a time zone (like America/New_York or Asia/Tokyo), and a
calendar system
. For example, "2025-12-31T23:30:00-05:00[America/New_York]" is a ZonedDateTime for 11:30
PM in New York time,
which corresponds to a specific moment (which would be 04:30 UTC on Jan 1, 2026 in this case). Use
ZonedDateTime
when you need to represent or compute with exact moments in time with respect to a specific time zone. This is
crucial for scheduling systems, calendar events, or any situation where the local time and actual timeline must
be coordinated. For example, a flight departure at 9:00 AM Tokyo time on a certain date should be a
ZonedDateTime - it knows the exact instant globally, and you can convert it to the local time in another zone if
needed.
In this example, we create a Temporal.ZonedDateTime in one time zone and then convert it to
another time zone. This demonstrates how a ZonedDateTime carries an absolute time that can be
expressed in
different zones:
// Create date/time in Tokyo time zone:
const tokyoTime = Temporal.ZonedDateTime.from({
timeZone: "Asia/Tokyo",
year: 2025,
month: 5,
day: 24,
hour: 10,
minute: 0,
second: 0,
});
console.log(tokyoTime.toString());
// "2025-05-24T10:00:00+09:00[Asia/Tokyo]"
// Convert the same instant to London time:
const sameLondonTime = tokyoTime.withTimeZone("Europe/London");
console.log(sameLondonTime.toString());
// "2025-05-24T02:00:00+01:00[Europe/London]"
console.log(tokyoTime.toInstant().toString());
console.log(sameLondonTime.toInstant().toString());
// Both will output "2025-05-24T01:00:00Z" as an ISO 8601 instant string
// since their underlying Instant is the same
The local clock time changed from 10:00 to 02:00 because London is 8 hours behind Tokyo in this scenario. Both
tokyoTime and sameLondonTime represent the same moment (same Instant
under the hood), just in different
regional contexts. This shows how Temporal.ZonedDateTime can be used to convert and compare times
across time
zones easily.
Like Temporal.PlainDate and Temporal.PlainDateTime, if we want the current
Temporal.ZonedDateTime, we can
get it via
Temporal.Now.zonedDateTimeISO():
const currentZonedDateTime = Temporal.Now.zonedDateTimeISO();
console.log(currentZonedDateTime.toString()); // Current date + time + time zone (current time zone)
const currentZonedNewYorkDateTime = Temporal.Now.zonedDateTimeISO("America/New_York");
console.log(currentZonedNewYorkDateTime.toString()); // Current New York date + time + time zone
Temporal.Instant
Temporal.Instant represents a unique moment in time, with up to nanosecond precision. It's
essentially an absolute time value independent of calendars or time zones. It is stored as a count of
nanoseconds since the Unix epoch (1970-01-01T00:00:00Z). Instant can be used when you need to work
with
absolute times or timestamps, such as logging events, measuring time intervals, or interfacing with systems that
use epoch-based times.
Below we create an Instant from a known epoch-based value, and also get the current instant. We then demonstrate converting an instant to a time zone for display, and accessing its epoch time properties:
// Create an Instant one second after the Unix epoch (1970-01-01T00:00:00Z)
const oneSecondAfterEpoch = Temporal.Instant.fromEpochMilliseconds(1000);
console.log(oneSecondAfterEpoch.toString()); // "1970-01-01T00:00:01Z"
console.log(oneSecondAfterEpoch.epochMilliseconds); // 1000 (milliseconds since epoch)
// Create another instant and show its value and a time zone conversion:
const someInstant = Temporal.Instant.from("2025-05-23T00:00:00Z");
console.log(someInstant.toString()); // "2025-05-23T00:00:00Z"
const nycTime = someInstant.toZonedDateTimeISO("America/New_York");
console.log(nycTime.toString()); // "2025-05-22T20:00:00-04:00[America/New_York]"
And, as you expected, we can also get the current Temporal.Instant via
Temporal.Now.instant():
const currentInstant = Temporal.Now.instant();
console.log(currentInstant.toString()); // Current instant as an ISO 8601 string
Temporal.Duration
Temporal.Duration represents an amount of time in terms of years, months, weeks, days, hours,
minutes, seconds,
milliseconds, microseconds, and nanoseconds. It's an immutable object that you can use for date/time math - for
example, "5 days" or "PT3H20M". You can use Duration whenever you need to represent an amount of
time or do arithmetic with Temporal objects.
Here are examples of arithmetic operations with Temporal objects that involve Temporal.Duration:
const duration1 = Temporal.Duration.from({ hours: 1, minutes: 30 });
const duration2 = Temporal.Duration.from({ days: 2 });
const duration3 = duration2.add(duration1);
const duration4 = Temporal.Duration.from({ days: -2 });
console.log(duration1.toString()); // "PT1H30M"
console.log(duration2.toString()); // "P2D"
console.log(duration3.toString()); // "P2DT1H30M"
console.log(duration4.toString()); // "-P2D"
console.log(duration1.total({ unit: 'minutes' })); // 90
console.log(duration2.total({ unit: 'minutes' })); // 2880
console.log(duration3.total({ unit: 'minutes' })); // 2970
console.log(duration4.total({ unit: 'minutes' })); // -2880
const plainTime = Temporal.PlainTime.from('00:20:25');
const plainDate = Temporal.PlainDate.from('2025-05-23');
const plainDateTime = Temporal.PlainDateTime.from('2025-12-31T23:30:00');
const zonedDateTime = Temporal.ZonedDateTime.from({
timeZone: "Asia/Tokyo",
year: 2025,
month: 5,
day: 24,
hour: 10,
minute: 30,
second: 0,
});
const instantDateTime = Temporal.Instant.from("2025-05-23T00:00:00Z");
console.log(plainTime.add(duration1).toString());
// "01:50:25"
console.log(plainTime.add(duration2).toString());
// "00:20:25", after 2 days it's the same time
console.log(plainDate.add(duration1).toString());
// "2025-05-23", because the fractional day is ignored
console.log(plainDate.add(duration2).toString());
// "2025-05-25"
console.log(plainDate.subtract(duration2).toString());
// "2025-05-21"
console.log(plainDate.add(duration4).toString());
// "2025-05-21"
console.log(plainDateTime.add(duration1).toString());
// "2026-01-01T01:00:00"
console.log(zonedDateTime.add(duration1).toString());
// "2025-05-24T12:00:00+09:00[Asia/Tokyo]"
console.log(instantDateTime.add(duration1).toString());
// "2025-05-23T01:30:00Z"
const plainTime2 = plainTime.add(duration1);
const plainDate2 = plainDate.add(duration2);
const plainDateTime2 = plainDateTime.add(duration1);
const zonedDateTime2 = zonedDateTime.add(duration1);
const instantDateTime2 = instantDateTime.add(duration1);
console.log(plainTime.since(plainTime2).toString()); // -PT1H30M
console.log(plainDate.since(plainDate2).toString()); // -P2D
console.log(plainDateTime.since(plainDateTime2).toString()); // -PT1H30M
console.log(zonedDateTime.since(zonedDateTime2).toString()); // -PT1H30M
console.log(instantDateTime.since(instantDateTime2).toString()); // -PT5400S
console.log(plainTime.until(plainTime2).toString()); // PT1H30M
console.log(plainDate.until(plainDate2).toString()); // P2D
console.log(plainDateTime.until(plainDateTime2).toString()); // PT1H30M
console.log(zonedDateTime.until(zonedDateTime2).toString()); // PT1H30M
console.log(instantDateTime.until(instantDateTime2).toString()); // PT5400S
Calendar systems
Calendar systems are used for interpreting dates. They represent different calendar conventions (ISO 8601, Hebrew, Islamic, Japanese, etc.) that can be used with Temporal dates and date-times.
Here is an example:
const indianDate = Temporal.PlainDate.from({
year: 2025,
month: 11,
day: 27,
calendar: 'indian'
});
console.log(indianDate.toString()); // "2104-02-16[u-ca=indian]"
console.log(indianDate.calendarId); // "indian"
Rounding
The Temporal API has a lot of features, and it's impossible to list all of them here. One
important feature worth mentioning is rounding. Temporal.Instant,
Temporal.ZonedDateTime, Temporal.PlainDateTime, Temporal.PlainTime and
Temporal.Duration support the round() method. For all of them round()
returns a new object (Temporal objects are immutable). This is how rounding works:
const plainTime = Temporal.PlainTime.from("10:33:00");
const plainDateTime = Temporal.PlainDateTime.from("2025-05-23T10:33:00");
const zonedDateTime = Temporal.ZonedDateTime.from("2025-05-23T10:33:00+01:00[Europe/London]");
const instant = Temporal.Instant.from("2025-05-23T10:33:00+01:00");
const duration = Temporal.Duration.from({ hours: 10, minutes: 33, days: 2 });
console.log(plainTime.round("hour").toString());
// "11:00:00", smallestUnit is "hour" and default roundingMode is "halfExpand"
// "halfExpand" rounds to the nearest value, with ties away from zero
console.log(plainTime.round({
smallestUnit: "hour",
roundingMode: "trunc", // rounds toward zero
}).toString()); // "10:00:00"
console.log(plainTime.round({
smallestUnit: "minute",
roundingIncrement: 4, // roundingIncrement is 1 by default, but we can choose a larger value.
// Note: the next larger unit (in this case, an hour = 60 minutes) must be divisible
// by roundingIncrement, and roundingIncrement must be less than that larger unit.
// So, in this case the allowed values are: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30
roundingMode: "trunc",
}).toString());
// "10:32:00", 10:33:00 would not align with 4-minute increments, so it was rounded down to 10:32:00
console.log(plainTime.round({
smallestUnit: "minute",
roundingIncrement: 4,
roundingMode: "expand", // rounds away from zero
}).toString());
// "10:36:00", 10:33:00 would not align with 4-minute increments, so it was rounded up to 10:36:00
console.log(plainDateTime.round("hour").toString()); // "2025-05-23T11:00:00", similar logic
console.log(plainDateTime.round({
smallestUnit: "minute",
roundingIncrement: 4,
roundingMode: "expand",
}).toString()); // 2025-05-23T10:36:00
console.log(plainDateTime.round("day").toString());
// 2025-05-23T00:00:00, day is the largest unit that can be used for rounding
console.log(zonedDateTime.round("hour").toString());
// "2025-05-23T11:00:00+01:00[Europe/London]", similar logic
console.log(zonedDateTime.round({
smallestUnit: "minute",
roundingIncrement: 4,
roundingMode: "expand",
}).toString()); // "2025-05-23T10:36:00+01:00[Europe/London]"
console.log(zonedDateTime.round("day").toString()); // "2025-05-23T00:00:00+01:00[Europe/London]"
console.log(instant.round("hour").toString());
// "2025-05-23T10:00:00Z", hour is the largest unit for rounding
console.log(duration.round("hour").toString()); // "P2DT11H"
console.log(duration.round({
smallestUnit: "minute",
roundingIncrement: 4,
roundingMode: "expand",
}).toString()); // "P2DT10H36M"
console.log(duration.round({
smallestUnit: "minute",
largestUnit: "hour", // we can cap the largest unit for durations
}).toString()); // "PT58H33M" (the largest unit is capped to hour)
Browser support
As of July 2026, Temporal is natively supported in Firefox 139+ and Chromium 144+ browsers, including Chrome and Edge, but not Safari. It is therefore not yet a Baseline feature, so projects should check their target browsers or use a polyfill where needed. You can currently use the temporal-polyfill package.
Conclusion
After years of coping with the old Date API, JavaScript developers finally have a path to a better
future with
dates and times. The historical limitations - from the lack of first-class time zone support to DST pitfalls,
parsing woes, and mutable dates - had real costs in development time and application correctness. These issues prompted action from TC39
to create something new rather than continue patching the old. The Temporal API represents that new solution: it
brings JavaScript's date handling up to par with modern needs and aligns it with the kind of rich date/time
support found in other languages' standard libraries. Crucially, Temporal was built with the lessons of the past
in mind, directly addressing the pain points that developers encountered with Date.
With Temporal's introduction, working with dates and times in JavaScript is becoming more intuitive, reliable, and powerful, enabling developers to build time-sensitive features with greater confidence and less frustration.