{"id":1168,"date":"2026-03-13T12:00:00","date_gmt":"2026-03-13T13:00:00","guid":{"rendered":"https:\/\/computercoursesonline.com\/?p=1168"},"modified":"2026-03-18T10:00:37","modified_gmt":"2026-03-18T10:00:37","slug":"moving-from-moment-js-to-the-js-temporal-api","status":"publish","type":"post","link":"https:\/\/computercoursesonline.com\/index.php\/2026\/03\/13\/moving-from-moment-js-to-the-js-temporal-api\/","title":{"rendered":"Moving From Moment.js To The JS Temporal API"},"content":{"rendered":"

Moving From Moment.js To The JS Temporal API<\/title><\/p>\n<article>\n<header>\n<h1>Moving From Moment.js To The JS Temporal API<\/h1>\n<address>Joe Attardi<\/address>\n<p> 2026-03-13T13:00:00+00:00<br \/>\n 2026-03-18T09:33:12+00:00<br \/>\n <\/header>\n<p>Almost any kind of application written in JavaScript works with times or dates in some capacity. In the beginning, this was limited to the built-in <code>Date<\/code> API. This API includes basic functionality, but is quite limited in what it can do.<\/p>\n<p>Third-party libraries like Moment.js, and later built-in APIs such as the <code>Intl<\/code> APIs and the new <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Temporal\">Temporal API<\/a>, add much greater flexibility to working with times and dates.<\/p>\n<h2 id=\"the-rise-and-fall-of-moment-js\">The Rise And Fall Of Moment.js<\/h2>\n<p><a href=\"https:\/\/momentjs.com\">Moment.js<\/a> is a JavaScript library with powerful utilities for working with times and dates. It includes missing features from the basic <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Date\">Date API<\/a>, such as time zone manipulation, and makes many common operations simpler. Moment also includes functions for formatting dates and times. It became a widely used library in many different applications.<\/p>\n<p>However, Moment also had its share of issues. It\u2019s a large library, and can add significantly to an application\u2019s bundle size. Because the library doesn\u2019t support tree shaking (a feature of modern bundlers that can remove unused parts of libraries), the entire Moment library is included even if you only use one or two of its functions.<\/p>\n<p>Another issue with Moment is the fact that the objects it creates are <em>mutable<\/em>. Calling certain functions on a Moment object has side effects and mutates the value of that object. This can lead to unexpected behavior or bugs.<\/p>\n<p>In 2020, the maintainers of Moment decided to put the library into maintenance mode. No new feature development is being done, and the maintainers recommend against using it for new projects.<\/p>\n<p>There are other JavaScript date libraries, such as <code>date-fns<\/code>, but there\u2019s a new player in town, an API built directly into JavaScript: <strong>Temporal<\/strong>. It\u2019s a new standard that fills in the holes of the original <code>Date<\/code> API as well as solves some of the limitations found in Moment and other libraries.<\/p>\n<div data-audience=\"non-subscriber\" data-remove=\"true\" class=\"feature-panel-container\">\n<aside class=\"feature-panel\">\n<div class=\"feature-panel-left-col\">\n<div class=\"feature-panel-description\">\n<p>Meet <strong><a data-instant href=\"https:\/\/www.smashingconf.com\/online-workshops\/\">Smashing Workshops<\/a><\/strong> on <strong>front-end, design & UX<\/strong>, with practical takeaways, live sessions, <strong>video recordings<\/strong> and a friendly Q&A. With Brad Frost, St\u00e9ph Walter and <a href=\"https:\/\/smashingconf.com\/online-workshops\/workshops\">so many others<\/a>.<\/p>\n<p><a data-instant href=\"smashing-workshops\" class=\"btn btn--green btn--large\">Jump to the workshops \u21ac<\/a><\/div>\n<\/div>\n<div class=\"feature-panel-right-col\"><a data-instant href=\"smashing-workshops\" class=\"feature-panel-image-link\"><\/p>\n<div class=\"feature-panel-image\">\n<img loading=\"lazy\" class=\"feature-panel-image-img lazyload\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Feature Panel\" width=\"257\" height=\"355\" data-src=\"\/images\/smashing-cat\/cat-scubadiving-panel.svg\"><\/p>\n<\/div>\n<p><\/a>\n<\/div>\n<\/aside>\n<\/div>\n<h2 id=\"what-is-temporal\">What Is Temporal?<\/h2>\n<p>Temporal is a new time and date API being added to the ECMAScript standard, which defines modern JavaScript. As of March 2026, it has reached Stage 4 of the TC39 process (the committee that oversees proposals and additions to the JavaScript language), and will be included in the next version of the ECMAScript specification. It has already been implemented in several browsers: <a href=\"https:\/\/developer.chrome.com\/release-notes\/144\">Chrome<\/a> <a href=\"https:\/\/developer.chrome.com\/release-notes\/144\">144+<\/a> and <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Firefox\/Releases\/139#javascript\">Firefox<\/a> <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Firefox\/Releases\/139#javascript\">139+<\/a>, with <a href=\"https:\/\/bugs.webkit.org\/show_bug.cgi?id=223166\">Safari expected to follow soon<\/a>. A <a href=\"https:\/\/github.com\/js-temporal\/temporal-polyfill\">polyfill is also available<\/a> for unsupported browsers and Node.js.<\/p>\n<p>The Temporal API creates objects that, generally, represent moments in time. These can be full-time and date stamps in a given time zone, or they can be a generic instance of \u201cwall clock\u201d time without any time zone or date information. Some of the main features of Temporal include:<\/p>\n<ul>\n<li><strong>Times with or without dates.<\/strong><br \/>\nA Temporal object can represent a specific time on a specific date, or a time without any date information. A specific date, without a time, can also be represented.<\/li>\n<li><strong>Time zone support.<\/strong><br \/>\nTemporal objects are fully time zone aware and can be converted across different time zones. Moment supports time zones, too, but it requires the additional <code>moment-timezone<\/code> library.<\/li>\n<li><strong>Immutability.<\/strong><br \/>\nOnce a Temporal object is created, it cannot be changed. Time arithmetic or time zone conversions do not modify the underlying object. Instead, they generate a new Temporal object.<\/li>\n<li><strong>1-based indexing.<\/strong><br \/>\nA common source of bugs with the Date API (as well as with Moment) is that months are zero-indexed. This means that January is month <code>0<\/code>, rather than month <code>1<\/code> as we all understand in real life. Temporal fixes this by using 1-based indexing — January is month <code>1<\/code>.<\/li>\n<li><strong>It\u2019s built into the browser.<\/strong><br \/>\nSince Temporal is an API in the browser itself, it adds nothing to your application\u2019s bundle size.<\/li>\n<\/ul>\n<p>It\u2019s also important to note that the Date API isn\u2019t going away. While Temporal supersedes this API, it is not being removed or deprecated. Many applications would break if browsers suddenly removed the Date API. However, also keep in mind that Moment is now considered a legacy project in maintenance mode.<\/p>\n<p>In the rest of the article, we\u2019ll look at some \u201crecipes\u201d for migrating Moment-based code to the new Temporal API. Let\u2019s start refactoring!<\/p>\n<h2 id=\"creating-date-and-time-objects\">Creating Date And Time Objects<\/h2>\n<p>Before we can manipulate dates and times, we have to create objects representing them. To create a Moment object representing the current date and time, use the <code>moment<\/code> function.<\/p>\n<pre><code class=\"language-javascript\">const now = moment();\nconsole.log(now); \n\/\/ Moment<2026-02-18T21:26:29-05:00>\n<\/code><\/pre>\n<p>This object can now be formatted or manipulated as needed.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">\/\/ convert to UTC\n\/\/ warning: This mutates the Moment object and puts it in UTC mode!\nconsole.log(now.utc()); \n\/\/ Moment<2026-02-19T02:26:29Z>\n\n\/\/ print a formatted string - note that it's using the UTC time now\nconsole.log(now.format('MM\/DD\/YYYY hh:mm:ss a')); \n\/\/ 02\/19\/2026 02:27:07 am\n<\/code><\/pre>\n<\/div>\n<p>The key thing to remember about Moment is that a Moment object always includes information about the time <em>and<\/em> the date. If you only need to work with time information, this is usually fine, but it can cause unexpected behavior in situations like Daylight Saving Time or leap years, where the date can have an effect on time calculations.<\/p>\n<p>Temporal is more flexible. You can create an object representing the current date and time by creating a <code>Temporal.Instant<\/code> object. This represents a point in time defined by the time since \u201cthe epoch\u201d (midnight UTC on January 1, 1970). Temporal can reference this instant in time with nanosecond-level precision.<\/p>\n<pre><code class=\"language-javascript\">const now = Temporal.Now.instant();\n\n\/\/ see raw nanoseconds since the epoch\nconsole.log(now.epochNanoseconds);\n\/\/ 1771466342612000000n\n\n\/\/ format for UTC\nconsole.log(now.toString());\n\/\/ 2026-02-19T01:55:27.844Z\n\n\/\/ format for a particular time zone\nconsole.log(now.toString({ timeZone: 'America\/New_York' }));\n\/\/ 2026-02-18T20:56:57.905-05:00\n<\/code><\/pre>\n<p><code>Temporal.Instant<\/code> objects can also be created for a specific time and date by using the <code>from<\/code> static method.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">const myInstant = Temporal.Instant.from('2026-02-18T21:10:00-05:00');\n\n\/\/ Format the instant in the local time zone. Note that this only controls\n\/\/ the formatting - it does not mutate the object like `moment.utc` does.\nconsole.log(myInstant.toString({ timeZone: 'America\/New_York' }));\n\/\/ 2026-02-18T21:10:00-05:00\n<\/code><\/pre>\n<\/div>\n<p>You can also create other types of Temporal objects, including:<\/p>\n<ul>\n<li><strong><code>Temporal.PlainDate<\/code><\/strong>: A date with no time information.<\/li>\n<li><strong><code>Temporal.PlainTime<\/code><\/strong>: A time with no date information.<\/li>\n<li><strong><code>Temporal.ZonedDateTime<\/code><\/strong>: A date and time in a specific time zone.<\/li>\n<\/ul>\n<p>Each of these has a <code>from<\/code> method that can be called with an object specifying the date and\/or time, or a date string to parse.<\/p>\n<pre><code class=\"language-javascript\">\/\/ Just a date\nconst today = Temporal.PlainDate.from({\n year: 2026,\n month: 2, \/\/ note we're using 2 for February\n day: 18\n});\nconsole.log(today.toString());\n\/\/ 2026-02-18\n\n\/\/ Just a time\nconst lunchTime = Temporal.PlainTime.from({\n hour: 12\n});\nconsole.log(lunchTime.toString());\n\/\/ 12:00:00 \n\n\/\/ A date and time in the US Eastern time zone\nconst dueAt = Temporal.ZonedDateTime.from({\n timeZone: 'America\/New_York',\n year: 2026,\n month: 3,\n day: 1,\n hour: 12,\n minute: 0,\n second: 0\n});\nconsole.log(dueAt.toString());\n\/\/ 2026-03-01T12:00:00-05:00[America\/New_York]\n<\/code><\/pre>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"parsing\">Parsing<\/h2>\n<p>We\u2019ve covered programmatic creation of date and time information. Now let\u2019s look at parsing. Parsing is one area where Moment is more flexible than the built-in Temporal API.<\/p>\n<p>You can parse a date string by passing it to the <code>moment<\/code> function. With a single argument, Moment expects an ISO date string, but you can use alternative formats if you provide a second argument specifying the date format being used.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">const isoDate = moment('2026-02-21T09:00:00');\nconst formattedDate = moment('2\/21\/26 9:00:00', 'M\/D\/YY h:mm:ss');\n\nconsole.log(isoDate);\n\/\/ Moment<2026-02-21T09:00:00-05:00>\n\nconsole.log(formattedDate);\n\/\/ Moment<2026-02-21T09:00:00-05:00>\n<\/code><\/pre>\n<\/div>\n<p>In older versions, Moment would make a best guess to parse any arbitrarily formatted date string. This could lead to unpredictable results. For example, is <code>02-03-2026<\/code> February 2 or March 3? For this reason, newer versions of Moment display a prominent deprecation warning if it\u2019s called without an ISO formatted date string (unless the second argument with the desired format is also given).<\/p>\n<p>Temporal will only parse a specifically formatted date string. The string must be compliant with the ISO 8601 format or its extension, RFC 9557. If a non-compliant date string is passed to a <code>from<\/code> method, Temporal will throw a <code>RangeError<\/code>.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">\/\/ Using an RFC 9557 date string\nconst myDate = Temporal.Instant.from('2026-02-21T09:00:00-05:00[America\/New_York]');\nconsole.log(myDate.toString({ timeZone: 'America\/New_York' }));\n\/\/ 2026-02-21T09:00:00-05:00\n\n\/\/ Using an unknown date string\nconst otherDate = Temporal.Instant.from('2\/21\/26 9:00:00');\n\/\/ RangeError: Temporal error: Invalid character while parsing year value.\n<\/code><\/pre>\n<\/div>\n<p>The exact requirements of the date string depend on which kind of Temporal object you\u2019re creating. In the above example, <code>Temporal.Instant<\/code> requires a full ISO 8601 or RFC 9557 date string specifying the date and time with a time zone offset, but you can also create <code>PlainDate<\/code> or <code>PlainTime<\/code> objects using just a subset of the date format.<\/p>\n<pre><code class=\"language-javascript\">const myDate = Temporal.PlainDate.from('2026-02-21');\nconsole.log(myDate.toString());\n\/\/ 2026-02-21\n\nconst myTime = Temporal.PlainTime.from('09:00:00');\nconsole.log(myTime.toString());\n\/\/ 09:00:00\n<\/code><\/pre>\n<p>Note that these strings must still comply with the expected format, or an error will be thrown.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">\/\/ Using a non-compliant time strings. These will all throw a RangeError.\nTemporal.PlainTime.from('9:00');\nTemporal.PlainTime.from('9:00:00 AM');\n<\/code><\/pre>\n<\/div>\n<blockquote><p><strong>Pro tip: Handling non-ISO strings<\/strong><\/p>\n<p>Because Temporal prioritizes reliability, it won\u2019t try to guess the format of a string like <code>02-01-2026<\/code>. If your data source uses such strings, you will need to do some string manipulation to rearrange the values into an ISO string like <code>2026-02-01<\/code> before attempting to use it with Temporal.<\/p><\/blockquote>\n<h2 id=\"formatting\">Formatting<\/h2>\n<p>Once you have a Moment or Temporal object, you\u2019ll probably want to convert it to a formatted string at some point.<\/p>\n<p>This is an instance where Moment is a bit more terse. You call the object\u2019s <code>format<\/code> method with a string of tokens that describe the desired date format.<\/p>\n<pre><code class=\"language-javascript\">const date = moment();\n\nconsole.log(date.format('MM\/DD\/YYYY'));\n\/\/ 02\/22\/2026\n\nconsole.log(date.format('MMMM Do YYYY, h:mm:ss a'));\n\/\/ February 22nd 2026, 8:18:30 pm\n<\/code><\/pre>\n<p>On the other hand, Temporal requires you to be a bit more verbose. Temporal objects, such as <code>Instant<\/code>, have a <code>toLocaleString<\/code> method that accepts various formatting options specified as properties of an object.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">const date = Temporal.Now.instant();\n\n\/\/ with no arguments, we'll get the default format for the current locale\nconsole.log(date.toLocaleString());\n\/\/ 2\/22\/2026, 8:23:36 PM (assuming a locale of en-US)\n\n\/\/ pass formatting options to generate a custom format string\nconsole.log(date.toLocaleString('en-US', {\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n}));\n\/\/ February 22, 2026 at 8:23 PM\n\n\/\/ only pass the fields you want in the format string\nconsole.log(date.toLocaleString('en-US', {\n month: 'short',\n day: 'numeric'\n}));\n\/\/ Feb 22\n<\/code><\/pre>\n<\/div>\n<p><strong>Temporal date formatting actually uses the <code>Intl.DateTimeFormat<\/code> API<\/strong> (which is already readily available in modern browsers) under the hood. That means you can create a reusable <code>DateTimeFormat<\/code> object with your custom formatting options, then pass Temporal objects to its <code>format<\/code> method. Because of this, it doesn\u2019t support custom date formats like Moment does. If you need something like <code>'Q1 2026'<\/code> or other specialized formatting, you may need some custom date formatting code or reach for a third-party library.<\/p>\n<pre><code class=\"language-javascript\">const formatter = new Intl.DateTimeFormat('en-US', {\n month: '2-digit',\n day: '2-digit',\n year: 'numeric'\n});\n\nconst date = Temporal.Now.instant();\nconsole.log(formatter.format(date));\n\/\/ 02\/22\/2026\n<\/code><\/pre>\n<p>Moment\u2019s formatting tokens are simpler to write, but they aren\u2019t locale-friendly. The format strings \u201chard code\u201d things like month\/day order. The advantage of using a configuration object, as Temporal does, is that it will automatically adapt to any given locale and use the correct format.<\/p>\n<pre><code class=\"language-javascript\">const date = Temporal.Now.instant();\n\nconst formatOptions = {\n month: 'numeric',\n day: 'numeric',\n year: 'numeric'\n};\n\n\nconsole.log(date.toLocaleString('en-US', formatOptions));\n\/\/ 2\/22\/2026\n\nconsole.log(date.toLocaleString('en-GB', formatOptions));\n\/\/ 22\/02\/2026\n<\/code><\/pre>\n<h2 id=\"date-calculations\">Date calculations<\/h2>\n<p>In many applications, you\u2019ll need to end up performing some calculations on a date. You may want to add or subtract units of time (days, hours, seconds, etc.). For example, if you have the current date, you may want to show the user the date 1 week from now.<\/p>\n<p>Moment objects have methods such as <code>add<\/code> and <code>subtract<\/code> that perform these operations. These functions take a value and a unit, for example: <code>add(7, 'days')<\/code>. One very important difference between Moment and Temporal, however, is that when performing these date calculations, the underlying object is modified and its original value is lost.<\/p>\n<pre><code class=\"language-javascript\">const now = moment();\n\nconsole.log(now);\n\/\/ Moment<2026-02-24T20:08:36-05:00>\n\nconst nextWeek = now.add(7, 'days');\nconsole.log(nextWeek);\n\/\/ Moment<2026-03-03T20:08:36-05:00>\n\n\/\/ Gotcha - the original object was mutated\nconsole.log(now);\n\/\/ Moment<2026-03-03T20:08:36-05:00>\n<\/code><\/pre>\n<p>To avoid losing the original date, you can call <code>clone<\/code> on the Moment object to create a copy.<\/p>\n<pre><code class=\"language-javascript\">const now = moment();\nconst nextWeek = now.clone().add(7, 'days');\n\nconsole.log(now);\n\/\/ Moment<2026-02-24T20:12:55-05:00>\n\nconsole.log(nextWeek);\n\/\/ Moment<2026-03-03T20:12:55-05:00>\n<\/code><\/pre>\n<p>On the other hand, Temporal objects are <em>immutable<\/em>. Once you\u2019ve created an object like an <code>Instant<\/code>, <code>PlainDate<\/code>, and so on, the value of that object will never change. Temporal objects also have <code>add<\/code> and <code>subtract<\/code> methods.<\/p>\n<p>Temporal is a little picky about which time units can be added to which object types. For example, you can\u2019t add days to an <code>Instant<\/code>:<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">const now = Temporal.Now.instant();\nconst nextWeek = now.add({ days: 7 });\n\/\/ RangeError: Temporal error: Largest unit cannot be a date unit\n<\/code><\/pre>\n<\/div>\n<p>This is because <code>Instant<\/code> objects represent a specific point in time in UTC and are calendar-agnostic. Because the length of a day can change based on time zone rules such as Daylight Saving Time, this calculation isn\u2019t available on an <code>Instant<\/code>. You <em>can<\/em>, however, perform this operation on other types of objects, such as a <code>PlainDateTime<\/code>:<\/p>\n<pre><code class=\"language-javascript\">const now = Temporal.Now.plainDateTimeISO();\nconsole.log(now.toLocaleString());\n\/\/ 2\/24\/2026, 8:23:59 PM\n\nconst nextWeek = now.add({ days: 7 });\n\n\/\/ Note that the original PlainDateTime remains unchanged\nconsole.log(now.toLocaleString());\n\/\/ 2\/24\/2026, 8:23:59 PM\n\nconsole.log(nextWeek.toLocaleString());\n\/\/ 3\/3\/2026, 8:23:59 PM\n<\/code><\/pre>\n<p>You can also calculate how much time is between two Moment or Temporal objects.<\/p>\n<p>With Moment\u2019s <code>diff<\/code> function, you need to provide a unit for granularity, otherwise it will return the difference in milliseconds.<\/p>\n<pre><code class=\"language-javascript\">const date1 = moment('2026-02-21T09:00:00');\nconst date2 = moment('2026-02-22T10:30:00');\n\nconsole.log(date2.diff(date1));\n\/\/ 91800000\n\nconsole.log(date2.diff(date1, 'days'));\n\/\/ 1\n<\/code><\/pre>\n<p>To do this with a Temporal object, you can pass another Temporal object to its <code>until<\/code> or <code>since<\/code> methods. This returns a <code>Temporal.Duration<\/code> object containing information about the time difference. The <code>Duration<\/code> object has properties for each component of the difference, and also can generate an <a href=\"https:\/\/en.wikipedia.org\/wiki\/ISO_8601#Durations\">ISO 8601<\/a> duration string representing the time difference.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">const date1 = Temporal.PlainDateTime.from('2026-02-21T09:00:00');\nconst date2 = Temporal.PlainDateTime.from('2026-02-22T10:30:00');\n\n\/\/ largestUnit specifies the largest unit of time to represent\n\/\/ in the duration calculation\nconst diff = date2.since(date1, { largestUnit: 'day' });\n\nconsole.log(diff.days);\n\/\/ 1\n\nconsole.log(diff.hours);\n\/\/ 1\n\nconsole.log(diff.minutes);\n\/\/ 30\n\nconsole.log(diff.toString());\n\/\/ P1DT1H30M\n\/\/ (ISO 8601 duration string: 1 day, 1 hour, 30 minutes)\n<\/code><\/pre>\n<\/div>\n<h2 id=\"comparing-dates-and-times\">Comparing Dates And Times<\/h2>\n<p>Moment and Temporal both let you compare dates and times to determine which comes before the other, but take different approaches with the API.<\/p>\n<p>Moment provides methods such as <code>isBefore<\/code>, <code>isAfter<\/code>, and <code>isSame<\/code> to compare two Moment objects.<\/p>\n<pre><code class=\"language-javascript\">const date1 = moment('2026-02-21T09:00:00');\nconst date2 = moment('2026-02-22T10:30:00');\n\nconsole.log(date1.isBefore(date2));\n\/\/ true\n<\/code><\/pre>\n<p>Temporal uses a static <code>compare<\/code> method to perform a comparison between two objects of the same type. It returns <code>-1<\/code> if the first date comes before the second, <code>0<\/code> if they are equal, or <code>1<\/code> if the first date comes after the second. The following example shows how to compare two <code>PlainDate<\/code> objects. Both arguments to <code>Temporal.PlainDate.compare<\/code> must be <code>PlainDate<\/code> objects.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">const date1 = Temporal.PlainDate.from({ year: 2026, month: 2, day: 24 });\nconst date2 = Temporal.PlainDate.from({ year: 2026, month: 3, day: 24 });\n\n\/\/ date1 comes before date2, so -1\nconsole.log(Temporal.PlainDate.compare(date1, date2));\n\n\/\/ Error if we try to compare two objects of different types\nconsole.log(Temporal.PlainDate.compare(date1, Temporal.Now.instant()));\n\/\/ TypeError: Temporal error: Invalid PlainDate fields provided.\n<\/code><\/pre>\n<\/div>\n<p>In particular, this makes it easy to sort an array of Temporal objects chronologically.<\/p>\n<pre><code class=\"language-javascript\">\/\/ An array of Temporal.PlainDate objects\nconst dates = [ ... ];\n\n\/\/ use Temporal.PlainDate.compare as the comparator function\ndates.sort(Temporal.PlainDate.compare);\n<\/code><\/pre>\n<h2 id=\"time-zone-conversions\">Time Zone Conversions<\/h2>\n<p>The core Moment library doesn\u2019t support time zone conversions. If you need this functionality, you also need to install the <code>moment-timezone<\/code> package. This package is not tree-shakable, and therefore can add significantly to your bundle size. Once you\u2019ve installed <code>moment-timezone<\/code>, you can convert Moment objects to different time zones with the <code>tz<\/code> method. As with other Moment operations, this mutates the underlying object.<\/p>\n<pre><code class=\"language-javascript\">\/\/ Assuming US Eastern time\nconst now = moment();\nconsole.log(now);\n\/\/ Moment<2026-02-28T20:08:20-05:00>\n\n\/\/ Convert to Pacific time.\n\/\/ The original Eastern time is lost.\nnow.tz('America\/Los_Angeles');\nconsole.log(now);\n\/\/ Moment<2026-02-28T17:08:20-08:00>\n<\/code><\/pre>\n<p>Time zone functionality is built into the Temporal API when using a <code>Temporal.ZonedDateTime<\/code> object. These objects include a <code>withTimeZone<\/code> method that returns a new <code>ZonedDateTime<\/code> representing the same moment in time, but in the specified time zone.<\/p>\n<pre><code class=\"language-javascript\">\/\/ Again, assuming US Eastern time\nconst now = Temporal.Now.zonedDateTimeISO();\nconsole.log(now.toLocaleString());\n\/\/ 2\/28\/2026, 8:12:02 PM EST\n\n\/\/ Convert to Pacific time\nconst nowPacific = now.withTimeZone('America\/Los_Angeles');\nconsole.log(nowPacific.toLocaleString());\n\/\/ 2\/28\/2026, 5:12:02 PM PST\n\n\/\/ Original object remains unchanged\nconsole.log(now.toLocaleString());\n\/\/ 2\/28\/2026, 8:12:02 PM EST\n<\/code><\/pre>\n<p><strong>Note:<\/strong> <em>The formatted values returned by <code>toLocaleString<\/code> are, as the name implies, locale-dependent. The sample code was developed in the <code>en-US<\/code> locale, so the format is like this: <code>2\/28\/2026, 5:12:02 PM PST<\/code>. In another locale, this may be different. For example, in the <code>en-GB<\/code> locale, you would get something like <code>28\/2\/2026, 17:12:02 GMT-8<\/code>.<\/em><\/p>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"a-real-world-refactoring\">A Real-world Refactoring<\/h2>\n<p>Suppose we\u2019re building an app for scheduling events across time zones. Part of this app is a function, <code>getEventTimes<\/code>, which takes an ISO 8601 string representing the time and date of the event, a local time zone, and a target time zone. The function creates formatted time and date strings for the event in both time zones.<\/p>\n<p>If the function is given an input string that\u2019s not a valid time\/date string, it will throw an error.<\/p>\n<p>Here\u2019s the original implementation, using Moment (also requiring use of the <code>moment-timezone<\/code> package).<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">import moment from 'moment-timezone';\n\nfunction getEventTimes(inputString, userTimeZone, targetTimeZone) {\n const timeFormat = 'MMM D, YYYY, h:mm:ss a z';\n\n \/\/ 1. Create the initial moment in the user's time zone\n const eventTime = moment.tz(\n inputString,\n moment.ISO_8601, \/\/ Expect an ISO 8601 string\n true, \/\/ Strict parsing\n userTimeZone\n );\n \n \/\/ Throw an error if the inputString did not represent a valid date\n if (!eventTime.isValid()) {\n throw new Error('Invalid date\/time input');\n }\n\n \/\/ 2. Calculate the target time\n \/\/ CRITICAL: We must clone, or 'eventTime' changes forever!\n const targetTime = eventTime.clone().tz(targetTimeZone);\n\n return {\n local: eventTime.format(timeFormat),\n target: targetTime.format(timeFormat),\n };\n}\n\nconst schedule = getEventTimes(\n '2026-03-05T15:00-05:00',\n 'America\/New_York',\n 'Europe\/London',\n);\n\nconsole.log(schedule.local);\n\/\/ Mar 5, 2026, 3:00:00 pm EST\n\nconsole.log(schedule.target); \n\/\/ Mar 5, 2026, 8:00:00 pm GMT\n<\/code><\/pre>\n<\/div>\n<p>In this example, we\u2019re using an expected date format of ISO 8601, which is helpfully built into Moment. We\u2019re also using strict parsing, which means Moment won\u2019t try to guess with a date string that doesn\u2019t match the format. If a non-ISO date string is passed, it will result in an invalid date object, and we throw an error.<\/p>\n<p>The Temporal implementation looks similar, but has a few key differences.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-javascript\">function getEventTimes(inputString, userTimeZone, targetTimeZone) {\n \/\/ 1. Parse the input directly into an Instant, then create\n \/\/ a ZonedDateTime in the user's zone.\n const instant = Temporal.Instant.from(inputString);\n const eventTime = instant.toZonedDateTimeISO(userTimeZone);\n\n \/\/ 2. Convert to the target zone\n \/\/ This automatically returns a NEW object; 'eventTime' is safe.\n const targetTime = eventTime.withTimeZone(targetTimeZone);\n\n \/\/ 3. Format using Intl (built-in)\n const options = {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n second: '2-digit',\n timeZoneName: 'short'\n };\n\n return {\n local: eventTime.toLocaleString(navigator.language, options),\n target: targetTime.toLocaleString(navigator.language, options)\n };\n}\n\nconst schedule = getEventTimes(\n '2026-03-05T15:00-05:00',\n 'America\/New_York',\n 'Europe\/London',\n);\n\nconsole.log(schedule.local);\n\/\/ Mar 5, 2026, 3:00:00 PM EST\n\nconsole.log(schedule.target);\n\/\/ Mar 5, 2026, 8:00:00 PM GMT\n<\/code><\/pre>\n<\/div>\n<p>With Moment, we have to explicitly specify a format string for the resulting date strings. Regardless of the user\u2019s location or locale, the event times will always be formatted as <code>Mar 5, 2026, 3:00:00 pm EST<\/code>.<\/p>\n<p>Also, we don\u2019t have to explicitly throw an exception. If an invalid string is passed to <code>Temporal.Instant.from<\/code>, Temporal will throw the exception for us. One thing to note is that even with strict parsing, the Moment version is still more lenient. Temporal requires the time zone offset at the end of the string.<\/p>\n<p>You should also note that since we\u2019re using <code>navigator.language<\/code>, this code will only run in a browser environment, as <code>navigator<\/code> is not defined in a Node.js environment.<\/p>\n<p>The Temporal implementation uses the browser\u2019s current locale (<code>navigator.language<\/code>), so the user will automatically get event times formatted in their local time format. In the <code>en-US<\/code> locale, this is <code>Mar 5, 2026, 3:00:00 pm EST<\/code>. However, if the user is in London, for example, the event times will be formatted as <code>5 Mar 2026, 15:00:00 GMT-5<\/code>.<\/p>\n<h2 id=\"summary\">Summary<\/h2>\n<table class=\"tablesaw break-out\">\n<thead>\n<tr>\n<th>Action<\/th>\n<th>Moment.js<\/th>\n<th>Temporal<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Current time<\/td>\n<td><code>moment()<\/code><\/td>\n<td><code>Temporal.Now.zonedDateTimeISO()<\/code><\/td>\n<\/tr>\n<tr>\n<td>Parsing ISO<\/td>\n<td><code>moment(str)<\/code><\/td>\n<td><code>Temporal.Instant.from(str)<\/code><\/td>\n<\/tr>\n<tr>\n<td>Add time<\/td>\n<td><code>.add(7, 'days')<\/code> (mutates)<\/td>\n<td><code>.add({ days: 7 })<\/code> (new object)<\/td>\n<\/tr>\n<tr>\n<td>Difference<\/td>\n<td><code>.diff(other, 'hours')<\/code><\/td>\n<td><code>.since(other).hours<\/code><\/td>\n<\/tr>\n<tr>\n<td>Time zone<\/td>\n<td><code>.tz('Zone\/Name')<\/code><\/td>\n<td><code>.withTimeZone('Zone\/Name')<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>At first glance, the difference may be slightly different (and in the case of Temporal, sometimes more verbose and more strict) syntax, but there are several key advantages to using Temporal over Moment.js:<\/p>\n<ul>\n<li>Being more explicit means <strong>fewer surprises and unintended bugs<\/strong>. Moment may appear to be more lenient, but it involves \u201cguesswork,\u201d which can sometimes result in incorrect dates. If you give Temporal something invalid, it throws an error. If the code runs, you know you\u2019ve got a valid date.<\/li>\n<li>Moment can add significant size to the application\u2019s bundle, particularly if you\u2019re using the <code>moment-timezone<\/code> package. Temporal adds nothing (once it\u2019s shipped in your target browsers).<\/li>\n<li><strong>Immutability<\/strong> gives you the confidence that you\u2019ll never lose or overwrite data when performing date conversions and operations.<\/li>\n<li><strong>Different representations of time<\/strong> (<code>Instant<\/code>, <code>PlainDateTime<\/code>, <code>ZonedDateTime<\/code>) depending on your requirements, where Moment is always a wrapper around a UTC timestamp.<\/li>\n<li>Temporal uses the <strong><code>Intl<\/code> APIs for date formatting<\/strong>, which means you can have locale-aware formatting without having to explicitly specify tokens.<\/li>\n<\/ul>\n<h2 id=\"notes-on-the-polyfill\">Notes On The Polyfill<\/h2>\n<p>As mentioned earlier, there is a Temporal polyfill available, distributed as an npm package named <code>@js-temporal\/polyfill<\/code>. If you want to use Temporal today, you\u2019ll need this polyfill to support browsers like Safari that haven\u2019t shipped the API yet. The bad news with this is that it will add to your bundle size. The good news is that it still adds significantly less than <code>moment<\/code> or <code>moment-timezone<\/code>. Here is a comparison of the bundle sizes as reported by Bundlephobia.com, a website that presents information on npm package sizes (click on each package name to see the Bundlephobia analysis):<\/p>\n<table class=\"tablesaw break-out\">\n<thead>\n<tr>\n<th>Package<\/th>\n<th>Minified<\/th>\n<th>Minified & gzipped<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><a href=\"https:\/\/bundlephobia.com\/package\/@js-temporal\/polyfill\"><code>@js-temporal\/polyfill<\/code><\/a><\/td>\n<td>154.1 kB<\/td>\n<td>44.1 kB<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/bundlephobia.com\/package\/moment\"><code>moment<\/code><\/a><\/td>\n<td>294.4 kB<\/td>\n<td>75.4 kB<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/bundlephobia.com\/package\/moment-timezone\"><code>moment-timezone<\/code><\/a><\/td>\n<td>1 MB<\/td>\n<td>114.2 kB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The polyfill also has historically had some performance issues around memory usage, and at the time of writing, it\u2019s considered to be in an alpha state. Because of this, you may not want to use it in production until it reaches a more mature state.<\/p>\n<p>The other good news is that hopefully the polyfill won\u2019t be needed much longer (unless you need to support older browsers, of course). At the time of writing, Temporal has shipped in Chrome, Edge, and Firefox. It\u2019s not quite ready in Safari yet, though it appears to be available with a runtime flag on the latest Technology Preview.<\/p>\n<div class=\"signature\">\n <img src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Smashing Editorial\" width=\"35\" height=\"46\" loading=\"lazy\" class=\"lazyload\" data-src=\"https:\/\/www.smashingmagazine.com\/images\/logo\/logo--red.png\"><br \/>\n <span>(gg, yk)<\/span>\n<\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>Moving From Moment.js To The JS Temporal API Moving From Moment.js To The JS Temporal API Joe Attardi 2026-03-13T13:00:00+00:00 2026-03-18T09:33:12+00:00 Almost any kind of application written in JavaScript works with times or dates in some capacity. In the beginning, this was limited to the built-in Date API. This API includes basic functionality, but is quite…<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[14],"tags":[],"_links":{"self":[{"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts\/1168"}],"collection":[{"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/comments?post=1168"}],"version-history":[{"count":1,"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts\/1168\/revisions"}],"predecessor-version":[{"id":1169,"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts\/1168\/revisions\/1169"}],"wp:attachment":[{"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/media?parent=1168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/categories?post=1168"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/tags?post=1168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}