<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><id>tag:dnevnik.fabon.info,2026:feed</id><title>fabon&apos;s blog</title><author><name>fabon</name></author><link rel="self" type="application/atom+xml" href="https://dnevnik.fabon.info/feed.xml"/><updated>2026-04-29T18:47:45.131Z</updated><entry><id>tag:dnevnik.fabon.info,2026:entry:2026-04-30/temporal-polyfill-lite</id><title>I made another Temporal polyfill from scratch</title><link href="https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/" /><content type="html">&lt;p&gt;It&apos;s because existing polyfills were insufficient for me.&lt;/p&gt;&#10;&lt;h2&gt;Brief summary&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;I created &lt;a href=&quot;https://npmx.dev/package/temporal-polyfill-lite&quot;&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt;&lt;/a&gt;, a lightweight Temporal polyfill.&lt;/li&gt;&#10;&lt;li&gt;It supports the final spec of Temporal and is compatible with the official TypeScript type definition.&lt;/li&gt;&#10;&lt;li&gt;For the majority of developers (those who only need the Gregorian calendar), it&apos;s the smallest Temporal polyfill available as of April 2026.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;The state of ECMAScript Temporal&lt;/h2&gt;&#10;&lt;p&gt;The Temporal proposal recently reached Stage 4. Firefox shipped it in May of last year, and Chrome followed suit this January. Node.js is planning to ship Temporal in its next major version (v26), which is set for release this May&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. Safari is lagging a bit behind, but implementation is underway, so it&apos;s only a matter of time&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;. We can finally start using Temporal!&lt;/p&gt;&#10;&lt;p&gt;Well, we still need a polyfill for now. Until recently, there were only two polyfills: &lt;a href=&quot;https://npmx.dev/package/@js-temporal/polyfill&quot;&gt;&lt;code&gt;@js-temporal/polyfill&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://npmx.dev/package/temporal-polyfill&quot;&gt;&lt;code&gt;temporal-polyfill&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2&gt;Existing polyfills&lt;/h2&gt;&#10;&lt;h3&gt;&lt;code&gt;@js-temporal/polyfill&lt;/code&gt;&lt;/h3&gt;&#10;&lt;p&gt;&lt;code&gt;@js-temporal/polyfill&lt;/code&gt; is based on the reference polyfill from the &lt;a href=&quot;https://github.com/tc39/proposal-temporal&quot;&gt;Temporal proposal repository&lt;/a&gt; and is maintained by some of the proposal&apos;s champions. The reference polyfill itself is mainly for spec verification and doesn&apos;t aim to be production-ready, so several performance optimizations were added to make it suitable for real-world use. Sounds good so far, right?&lt;/p&gt;&#10;&lt;p&gt;The downside, however, is the massive bundle size: 160 kB minified and 45 kB gzipped. For comparison, the core of Moment.js is 60 kB minified and 18.5 kB gzipped. Compared to other date and time libraries, this polyfill is excessively large for frontend projects. The original code is a literal, word-for-word reference implementation of the spec and wasn&apos;t built with bundle size in mind. While it&apos;s relatively easy to optimize performance later, optimizing bundle size is much more difficult.&lt;/p&gt;&#10;&lt;p&gt;Moreover, while the upstream reference polyfill is actively maintained, &lt;code&gt;@js-temporal/polyfill&lt;/code&gt; wasn&apos;t for a while. The champions always fix reported bugs quickly and reflect spec changes immediately in the proposal repository, but those changes hadn&apos;t been merged into &lt;code&gt;@js-temporal/polyfill&lt;/code&gt; for ten months (though merging has recently resumed, e.g., &lt;a href=&quot;https://github.com/js-temporal/temporal-polyfill/pull/361&quot;&gt;js-temporal/temporal-polyfill#361&lt;/a&gt;). I want to clarify that &lt;strong&gt;I am not blaming the maintainers&lt;/strong&gt;. Maintaining both the upstream and the fork is tough work, and the champions have a massive number of tasks to handle during the standardization process.&lt;/p&gt;&#10;&lt;h3&gt;&lt;code&gt;temporal-polyfill&lt;/code&gt;&lt;/h3&gt;&#10;&lt;p&gt;On the other hand, &lt;code&gt;temporal-polyfill&lt;/code&gt; has a much smaller bundle size: 57 kB minified and 20 kB gzipped. It&apos;s still a bit large but acceptable, considering the Temporal spec is over 10,000 lines long. Unfortunately, like &lt;code&gt;@js-temporal/polyfill&lt;/code&gt;, it refers to an outdated version of the spec. Consequently, various bugs and confusing behaviors that were resolved in the final spec have remained for months (note: updates seem to be &lt;a href=&quot;https://github.com/fullcalendar/temporal-polyfill/issues/94&quot;&gt;in progress&lt;/a&gt; now, but aren&apos;t finished yet). Some issues are rare edge cases, but others can bite anyone using Temporal in the real world. Here are a few examples:&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// regular DST change:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Temporal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;ZonedDateTime&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2025-11-02T01:01:00-07:00[America/Vancouver]&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;until&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2025-11-02T01:00:00-08:00[America/Vancouver]&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  largestUnit&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;days&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Throws `RangeError` in both polyfills,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// but should be PT59M (59 minutes) per the final spec&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Temporal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;PlainYearMonth&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2024-02&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; years&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; overflow&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;reject&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Throws `RangeError` in both polyfills,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// but should be 2023-02 (February 2023) per the final spec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;In particular, era definitions for calendars were finalized relatively recently, and existing polyfills haven&apos;t caught up yet. Developers working with non-ISO calendars will likely run into trouble here:&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Temporal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;PlainDate&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2026-04-01[u-ca=gregory]&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;era&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Returns &quot;gregory&quot; in both polyfills, but &quot;ce&quot; per the final spec&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Temporal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;PlainDate&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2026-04-01[u-ca=hebrew]&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;era&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Returns undefined in both polyfills, but &quot;am&quot; per the final spec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill&lt;/code&gt; also has some bugs related to time zones and date arithmetic. While bugs are inevitable, they haven&apos;t been fixed for a while, which can hinder the adoption of Temporal. For me, these were deal-breakers; I believe that reliable date arithmetic and time zone calculations are exactly the reason for being of Temporal. I didn&apos;t want to implement workarounds just because of a polyfill.&lt;/p&gt;&#10;&lt;p&gt;Once again, &lt;strong&gt;I don&apos;t want to blame the maintainer&lt;/strong&gt;. Maintaining a Temporal polyfill is incredibly hard work (likely harder than you&apos;d imagine), and criticizing OSS maintainers for a lack of bandwidth or time goes against the spirit of open source.&lt;/p&gt;&#10;&lt;h2&gt;Why is it so hard to implement a polyfill?&lt;/h2&gt;&#10;&lt;p&gt;Generally, while writing a polyfill requires specialized knowledge, it is not as hard as you might think: read the spec and implement it word for word. If you&apos;re interested in ECMAScript, writing a polyfill is usually a great place to start.&lt;/p&gt;&#10;&lt;p&gt;Temporal, however, is a clear exception. It&apos;s a gigantic proposal with 13,000 lines of spec text. For context, ECMA-262 (the core JS spec) is 53,000 lines, and ECMA-402 (the i18n spec) is 10,000 lines before Temporal is merged. It is the largest addition in the history of ECMAScript. Let alone implementation, even understanding the structure of such a huge spec is difficult. It requires deep knowledge of ECMA-402 and i18n, especially time zones, calendars, and &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt;, in addition to knowledge necessary for typical polyfill authors.&lt;/p&gt;&#10;&lt;h2&gt;The options&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill&lt;/code&gt; was virtually my only option, but it had critical issues, and it seemed like nobody was working on them at the time. Literally nobody. That&apos;s understandable because not many developers have the ability, willingness, and time to fix &lt;code&gt;temporal-polyfill&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;I&apos;m just a graduate student&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; who loves web technologies; I don&apos;t belong to any standards bodies or browser vendors. However, to make a long story short, I had some knowledge of Temporal and i18n, the ability to dive into the spec, and plenty of enthusiasm for the JavaScript ecosystem. I felt like I had an obligation to do something useful instead of just posting &amp;quot;any updates?&amp;quot; comments on GitHub.&lt;/p&gt;&#10;&lt;p&gt;At first, I tried to fix the bugs in &lt;code&gt;temporal-polyfill&lt;/code&gt; and sent &lt;a href=&quot;https://github.com/fullcalendar/temporal-polyfill/pull/79&quot;&gt;a pull request&lt;/a&gt;. Unfortunately, it&apos;s been open for six months and hasn&apos;t been merged yet. I wanted to fix the remaining time zone bugs too, but I found it hard to do so while respecting the original author&apos;s architectural decisions. It would have been even harder to debate design on GitHub for me. Furthermore, the project&apos;s structure differed from the spec, making it difficult for me to track down the root cause of the arithmetic bugs. I just wasn&apos;t smart enough to map the spec text to the existing code.&lt;/p&gt;&#10;&lt;p&gt;Eventually, I started considering a &amp;quot;crazier&amp;quot; option: building a polyfill from scratch. It was not only because there was no other option for me. I had been curious to see how small a polyfill could be if it only supported the Gregorian calendar. I suspected that a lot of the bulk in existing polyfills came from complex non-Gregorian calendars that only a tiny fraction of developers actually need.&lt;/p&gt;&#10;&lt;h2&gt;Requirements and design decisions&lt;/h2&gt;&#10;&lt;p&gt;I started building &lt;code&gt;temporal-polyfill-lite&lt;/code&gt; with a different set of design principles.&lt;/p&gt;&#10;&lt;h3&gt;Project structure&lt;/h3&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt; is almost a word-for-word implementation of the spec. This allows the project to benefit directly from the work of spec writers and implementers.&lt;/p&gt;&#10;&lt;p&gt;The spec text is extremely well-maintained pseudocode that has been reviewed and debugged by many people (including myself). Following it closely reduces bugs. It also makes debugging easier because I can compare my code directly to the reference polyfill.&lt;/p&gt;&#10;&lt;p&gt;If the spec text is simplified upstream, I can easily apply those simplifications to my code. Conversely, if I find a way to simplify my code, I might even be able to contribute that change back to the spec.&lt;/p&gt;&#10;&lt;h3&gt;No protection against global namespace mutation&lt;/h3&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt; won&apos;t work if built-in methods (like &lt;code&gt;String.prototype.replace&lt;/code&gt; or &lt;code&gt;Array.prototype.map&lt;/code&gt;) are deleted or modified. While this isn&apos;t strictly spec-compliant, does it really matter? If someone invasively mutates the global namespace, your entire application is going to break anyway. Protecting a polyfill from such mutations (using the &amp;quot;primordials&amp;quot; trick) sacrifices both bundle size and performance for very little practical gain.&lt;/p&gt;&#10;&lt;p&gt;For more on this, I recommend the excellent article &amp;quot;&lt;a href=&quot;https://43081j.com/2026/03/three-pillars-of-javascript-bloat&quot;&gt;The Three Pillars of JavaScript Bloat&lt;/a&gt;&amp;quot;.&lt;/p&gt;&#10;&lt;h3&gt;Bundle size&lt;/h3&gt;&#10;&lt;p&gt;From the start, &lt;code&gt;temporal-polyfill-lite&lt;/code&gt; was built with bundle size as a priority. I&apos;ve applied various reduction techniques throughout the codebase.&lt;/p&gt;&#10;&lt;h3&gt;Internal representation of large integers&lt;/h3&gt;&#10;&lt;p&gt;Temporal supports timestamps and durations with nanosecond precision. &amp;quot;Epoch nanoseconds&amp;quot; and &amp;quot;time durations&amp;quot; can exceed JavaScript&apos;s maximum safe integer (53-bit) or even a 64-bit integer.&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt; represents these large integers as an array of two numbers (a quotient and a remainder of &lt;code&gt;x / 8.64e13&lt;/code&gt;) internally, rather than using &lt;code&gt;BigInt&lt;/code&gt;. I borrowed this clever idea from &lt;code&gt;temporal-polyfill&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h3&gt;Browser support&lt;/h3&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt; works in any browser released after 2020 (it uses features from &amp;quot;Baseline 2020&amp;quot;).&lt;/p&gt;&#10;&lt;p&gt;Since it doesn&apos;t rely on &lt;code&gt;BigInt&lt;/code&gt; internally, it could work in older browsers if you transpile &lt;code&gt;temporal-polyfill-lite&lt;/code&gt; and inject polyfills for APIs used internally (since code using &lt;code&gt;BigInt&lt;/code&gt; can&apos;t be transpiled or polyfilled at all).&lt;/p&gt;&#10;&lt;h3&gt;Time zones&lt;/h3&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt; supports all time zones. This is definitely a long-awaited feature. Who wants to use Temporal without proper time zone support?&lt;/p&gt;&#10;&lt;h3&gt;Calendars&lt;/h3&gt;&#10;&lt;p&gt;By default, it only supports &lt;code&gt;iso8601&lt;/code&gt; and &lt;code&gt;gregory&lt;/code&gt; calendars, which keeps the bundle small for most developers. Support for &lt;code&gt;gregory&lt;/code&gt; is actually required if you want to format &lt;code&gt;Temporal.PlainMonthDay&lt;/code&gt; or &lt;code&gt;Temporal.PlainYearMonth&lt;/code&gt; using &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; or &lt;code&gt;toLocaleString&lt;/code&gt;, due to some quirks in those classes:&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Temporal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;PlainYearMonth&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2026-04&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;toLocaleString&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;en-US&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  dateStyle&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Throws a confusing &quot;calendar mismatch&quot; error&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Temporal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;PlainYearMonth&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2026-04&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;toLocaleString&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;en-US&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  calendar&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;iso8601&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  dateStyle&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Returns &quot;2026 April&quot; in Chrome/Firefox, which isn&apos;t usually what you want&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// (this format is not used in America).&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Node.js v25 returns a broken result: &quot;2026 &quot;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Temporal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;PlainYearMonth&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;2026-04-01[u-ca=gregory]&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;toLocaleString&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;en-US&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; dateStyle&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// &quot;April 2026&quot; (exactly what you&apos;d expect)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h2&gt;Implementation&lt;/h2&gt;&#10;&lt;p&gt;It was a long, tough journey.&lt;/p&gt;&#10;&lt;p&gt;I started the project in June 2025, but it stalled for months because I didn&apos;t have the time to commit to it. I restarted it from zero in December 2025 (reusing many parts of the old code) and finally released the initial version in late January 2026. It took about seven weeks from the &amp;quot;reboot&amp;quot; to the first release.&lt;/p&gt;&#10;&lt;p&gt;Thanks to the enormous effort of the champions and implementers to expand &lt;a href=&quot;https://github.com/tc39/test262&quot;&gt;test262&lt;/a&gt;, Temporal has almost 100% test coverage in test262 now. A fast test runner developed by the champions (&lt;a href=&quot;https://github.com/js-temporal/temporal-test262-runner&quot;&gt;&lt;code&gt;temporal-test262-runner&lt;/code&gt;&lt;/a&gt;) was a lifesaver, significantly reducing test execution time. The Temporal proposal repository also has &amp;quot;thorough tests&amp;quot;, scripts for testing implementation against a vast number of test cases. I found various bugs in my implementation with the aid of these tests.&lt;/p&gt;&#10;&lt;p&gt;I should mention that I was a latecomer. Unlike other polyfill authors, I implemented the polyfill based on the almost finalized spec. I didn&apos;t have to navigate the major normative changes (like the big scope reduction in June 2024) that the pioneers had to deal with. I have immense respect for those who kept their polyfills updated for years as the spec evolved.&lt;/p&gt;&#10;&lt;p&gt;As a side effect of building this, I found and reported several bugs and errors in the spec text and even submitted a pull request to improve it (&lt;a href=&quot;https://github.com/tc39/proposal-temporal/pull/3271&quot;&gt;tc39/proposal-temporal#3271&lt;/a&gt;). I&apos;m very happy to have contributed to the proposal in some small way.&lt;/p&gt;&#10;&lt;p&gt;I know some people think human coding is obsolete. Claude Code or Codex could probably write a Temporal polyfill in days or even hours. But I wrote every line by hand, and I don&apos;t regret it. It was a &amp;quot;desirable difficulty&amp;quot; that expanded my knowledge. Understanding the details of the spec and implementation, such as how to deal with an &lt;a href=&quot;https://github.com/tc39/proposal-temporal/issues/2910&quot;&gt;unusual time zone transition in Canada 100 years ago&lt;/a&gt; or the quirks of floating-point arithmetic in JavaScript, isn&apos;t a &amp;quot;boring task&amp;quot; I want to outsource to an agent; it&apos;s exactly what I find interesting. For me, coding is like DIY and isn&apos;t something I have to &amp;quot;streamline&amp;quot; at the expense of the joy of understanding how things work&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;&#10;&lt;h3&gt;Time zone calculations&lt;/h3&gt;&#10;&lt;p&gt;The only way to access the time zone database in JavaScript engines is by parsing the output of &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; with the &lt;code&gt;timeZone&lt;/code&gt; option. Parsing localized strings is usually a terrible idea, as formats vary between engines and versions, but there&apos;s no other choice. Fortunately, the &lt;code&gt;formatToParts&lt;/code&gt; method returns structured data that is relatively reliable to parse.&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; Intl&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;DateTimeFormat&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;en&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  year&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  month&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  day&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  hour&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  minute&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  second&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  hour12&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;  timeZone&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;Asia/Tokyo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;formatToParts&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// Result:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;[&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;month&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;literal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;day&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;literal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;year&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;1970&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;literal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;hour&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;09&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;literal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;minute&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;00&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;literal&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;second&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;00&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Essentially, we can calculate the UTC offset by comparing the formatted parts to the original timestamp. Most date and time libraries (Luxon, Day.js with &lt;code&gt;tz&lt;/code&gt; plugin, &lt;code&gt;@date-fns/tz&lt;/code&gt;, etc.) and other Temporal polyfills use a similar approach too.&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; getOffsetMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;epochSeconds&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; timeZone&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; parts&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; Intl&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;DateTimeFormat&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;en&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    year&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    month&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    day&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    hour&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    minute&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    second&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    hour12&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    timeZone&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  }&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;formatToParts&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;epochSeconds&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; units&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;year&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;month&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;day&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;hour&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;minute&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;second&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;localYear&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; localMonth&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; localDay&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; localHour&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; localMinute&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; localSecond&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    units&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;unit&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; parseInt&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;parts&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; ===&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; unit&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    Date&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;      localYear&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;      localMonth&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;      localDay&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;      localHour&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;      localMinute&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;      localSecond&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;    ) &lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;-&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;    epochSeconds&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt; 1000&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;  )&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;getOffsetMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;Europe/London&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // 3600000 (UTC+1)&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;getOffsetMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;America/New_York&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // -18000000 (UTC-5)&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;getOffsetMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;Asia/Tokyo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // 32400000 (UTC+9)&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;getOffsetMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;Africa/Monrovia&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // -2670000 (UTC-0:44:30)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Because &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; is slow, the polyfill uses an LRU cache. However, the current mechanism is far from ideal. It caches offsets for every second, even though offsets rarely change. Most countries and regions don&apos;t use DST (daylight saving time), and time zone offsets change at most twice per year in time zones where DST is observed. Time zone offset transitions for political reasons are even less common. I&apos;m currently working on a more efficient caching algorithm (&lt;a href=&quot;https://github.com/fabon-f/temporal-polyfill-lite/issues/26&quot;&gt;issue&lt;/a&gt;).&lt;/p&gt;&#10;&lt;h2&gt;Reducing bundle size&lt;/h2&gt;&#10;&lt;p&gt;One of my main goals was a small bundle size. I wrote a script to measure the size (with and without compression) to ensure every optimization actually worked. You can&apos;t optimize what you don&apos;t measure.&lt;/p&gt;&#10;&lt;p&gt;If you look at minified JavaScript code, you&apos;ll notice many long property names. That&apos;s because mangling properties is unsafe; it can easily break your code. Properties in public APIs or internal properties accessed by the bracket operator can&apos;t be mangled.&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// original:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; fooBarBaz&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; prop&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;fooBarBaz&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;keys&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // [&quot;fooBarBaz&quot;]&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;prop&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // 0&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// after mangling properties:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B48EAD&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; prop&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;fooBarBaz&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;keys&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // [&quot;a&quot;]&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;prop&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#616E88&quot;&gt; // undefined&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Initially, I tried to write the whole polyfill using tuples instead of objects, but that was almost impossible to maintain. No one wants to remember that &lt;code&gt;isoDateTime[0][1]&lt;/code&gt; actually means &lt;code&gt;isoDateTime.date.month&lt;/code&gt;. So, I decided to introduce property mangling when I &amp;quot;rebooted&amp;quot; the project.&lt;/p&gt;&#10;&lt;p&gt;Instead of making a long list of properties we want to preserve, I introduced a simple naming convention: every internal property that should be mangled starts with a &lt;code&gt;$&lt;/code&gt; (e.g., &lt;code&gt;$isoDate&lt;/code&gt;) or &lt;code&gt;_&lt;/code&gt;. This allows the minifier to safely mangle internal properties while leaving the public API intact. I picked up this idea from &lt;a href=&quot;https://zenn.dev/mizchi/articles/mangle-best-practice&quot;&gt;this article&lt;/a&gt; (&lt;a href=&quot;https://zenn.dev/mizchi/articles/mangle-best-practice?locale=en&quot;&gt;English version&lt;/a&gt; available too) on JavaScript minification.&lt;/p&gt;&#10;&lt;p&gt;I also prioritized expressions over statements. Multiple function calls can be merged using the comma operator, and &lt;code&gt;if&lt;/code&gt; statements can be converted into conditional or logical operators if the block doesn&apos;t contain any statements.&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;  bar&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;  baz&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// after minification:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;bar&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; baz&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;It might seem weird to replace &lt;code&gt;throw&lt;/code&gt; statements with function calls that throw errors, but it actually reduced the bundle size significantly because it allowed the minifier to optimize the code further. I also removed intermediate variables wherever possible to keep the code as a series of expressions.&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// before:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; aaaaa&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; RangeError&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; bar&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; baz&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; qux&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;bar&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// code above is minified like below:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; aaaaa&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; RangeError&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; baz&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; qux&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// after:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; throwRangeError&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  throw&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; RangeError&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; aaaaa&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;    throwRangeError&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; qux&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;baz&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;// code above is minified like below:&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; aaaaa&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#616E88&quot;&gt;  // Note that `throwRangeError` will be also mangled in the production build.&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; throwRangeError&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt; qux&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#88C0D0&quot;&gt;baz&lt;/span&gt;&lt;span style=&quot;color:#D8DEE9FF&quot;&gt;()))&lt;/span&gt;&lt;span style=&quot;color:#81A1C1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Compared to the initial release, the bundle size has dropped by 15% (from 60 kB to 52 kB) minified, and 10% (from 19.7 kB to 18 kB) gzipped. What a huge win!&lt;/p&gt;&#10;&lt;h2&gt;Support for non-Gregorian calendars&lt;/h2&gt;&#10;&lt;p&gt;After spending a few weeks to reduce the bundle size, I became confident that the whole codebase was optimized enough. As a next step, I looked into adding non-Gregorian calendars without increasing the bundle size for the majority of users (&lt;a href=&quot;https://github.com/fabon-f/temporal-polyfill-lite/issues/6&quot;&gt;issue&lt;/a&gt;). It had been in my backlog for months, but I hadn&apos;t figured out yet how to implement it.&lt;/p&gt;&#10;&lt;p&gt;I wanted something like &lt;a href=&quot;https://doc.rust-lang.org/cargo/reference/features.html&quot;&gt;Rust&apos;s feature flags&lt;/a&gt;, but that doesn&apos;t really exist in the JavaScript ecosystem. After human deep research and ultrathinking, I decided to use custom conditions for conditional exports and imports. Fortunately, all toolchains I use in this project (Node.js, TypeScript compiler, and Rolldown) support this.&lt;/p&gt;&#10;&lt;p&gt;The &lt;code&gt;package.json&lt;/code&gt; looks like this:&lt;/p&gt;&#10;&lt;pre class=&quot;shiki nord&quot; style=&quot;background-color:#2e3440ff;color:#d8dee9ff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;./dist/index.js&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt;./calendars-full&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;./dist/calendars/index.js&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt;imports&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt;#calendricalCalculations&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt;nonIsoCalendars&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;./src/internal/calendars/all.ts&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#8FBCBB&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#A3BE8C&quot;&gt;./src/internal/calendars/basic.ts&lt;/span&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&#10;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ECEFF4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;The polyfill has two entrypoints. The standard one is built without the &lt;code&gt;nonIsoCalendars&lt;/code&gt; condition, while &lt;code&gt;calendars-full&lt;/code&gt; includes it. Both &lt;code&gt;all.ts&lt;/code&gt; and &lt;code&gt;basic.ts&lt;/code&gt; export identical functions with different sets of supported calendars (see &lt;a href=&quot;https://github.com/fabon-f/temporal-polyfill-lite/pull/7&quot;&gt;fabon-f/temporal-polyfill-lite#7&lt;/a&gt; for details).&lt;/p&gt;&#10;&lt;h3&gt;Calendrical calculations&lt;/h3&gt;&#10;&lt;p&gt;While JavaScript engines can calculate non-Gregorian dates internally, there&apos;s no direct API to access those results (this is exactly what Temporal does). Unlike time zone calculations, parsing the output of &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; for non-Gregorian calendars is theoretically possible but unreliable, because formats produced by &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; for those calendars are far more inconsistent than for Gregorian across JavaScript engines or even operating systems (cf. &lt;a href=&quot;https://github.com/js-temporal/temporal-polyfill/issues/284&quot;&gt;js-temporal/temporal-polyfill#284&lt;/a&gt;).&lt;/p&gt;&#10;&lt;p&gt;Instead, I implemented the calendrical calculations myself for rule-based calendars. In particular, the &lt;code&gt;hebrew&lt;/code&gt; calendar is purely arithmetic but incredibly complex, so I tested my implementation against &lt;a href=&quot;https://github.com/unicode-org/icu4x&quot;&gt;ICU4X&lt;/a&gt; to ensure accuracy. For calendars that require astronomical simulation or historical calendar data (i.e., &lt;code&gt;islamic-umalqura&lt;/code&gt;, &lt;code&gt;persian&lt;/code&gt;, &lt;code&gt;chinese&lt;/code&gt;, and &lt;code&gt;dangi&lt;/code&gt;), the polyfill defers to the native &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2&gt;The result&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt; is currently the only Temporal polyfill that follows the final spec and is compatible with the &lt;a href=&quot;https://devblogs.microsoft.com/typescript/announcing-typescript-6-0/#new-types-for-temporal&quot;&gt;official TypeScript type definitions in v6.0&lt;/a&gt;. In my opinion, it&apos;s also the most reliable one for now. These points are important for developers who want to use Temporal right now, but will be irrelevant in the near future since other polyfills will eventually be updated too. I&apos;m not sure when, but I hope so.&lt;/p&gt;&#10;&lt;p&gt;Instead, the real advantage of &lt;code&gt;temporal-polyfill-lite&lt;/code&gt; is the bundle size. The table below shows the comparison as of April 2026. Note that the result can change in the future, in particular when &lt;code&gt;temporal-polyfill&lt;/code&gt; and &lt;code&gt;@js-temporal/polyfill&lt;/code&gt; reflect the final spec (see &lt;a href=&quot;https://github.com/fabon-f/temporal-polyfill-comparison&quot;&gt;comparison repository&lt;/a&gt; for the latest result). While I&apos;m happy with the results, I still think the &lt;code&gt;calendars-full&lt;/code&gt; version could be a bit smaller.&lt;/p&gt;&#10;&lt;table&gt;&#10;&lt;thead&gt;&#10;&lt;tr&gt;&#10;&lt;th&gt;&lt;/th&gt;&#10;&lt;th&gt;minified&lt;/th&gt;&#10;&lt;th&gt;gzip&lt;/th&gt;&#10;&lt;th&gt;brotli&lt;/th&gt;&#10;&lt;th&gt;zstd&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;native&lt;/td&gt;&#10;&lt;td&gt;0 kB&lt;/td&gt;&#10;&lt;td&gt;0 kB&lt;/td&gt;&#10;&lt;td&gt;0 kB&lt;/td&gt;&#10;&lt;td&gt;0 kB&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;&lt;code&gt;temporal-polyfill-lite&lt;/code&gt;&lt;/td&gt;&#10;&lt;td&gt;52.1 kB&lt;/td&gt;&#10;&lt;td&gt;17.9 kB&lt;/td&gt;&#10;&lt;td&gt;15.9 kB&lt;/td&gt;&#10;&lt;td&gt;18.6 kB&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;&lt;code&gt;temporal-polyfill-lite/calendars-full&lt;/code&gt;&lt;/td&gt;&#10;&lt;td&gt;63.6 kB&lt;/td&gt;&#10;&lt;td&gt;22.2 kB&lt;/td&gt;&#10;&lt;td&gt;19.6 kB&lt;/td&gt;&#10;&lt;td&gt;23.2 kB&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;&lt;code&gt;temporal-polyfill&lt;/code&gt;&lt;/td&gt;&#10;&lt;td&gt;57.0 kB&lt;/td&gt;&#10;&lt;td&gt;20.3 kB&lt;/td&gt;&#10;&lt;td&gt;18.2 kB&lt;/td&gt;&#10;&lt;td&gt;21.2 kB&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;&lt;code&gt;@js-temporal/polyfill&lt;/code&gt;&lt;/td&gt;&#10;&lt;td&gt;159.7 kB&lt;/td&gt;&#10;&lt;td&gt;45.3 kB&lt;/td&gt;&#10;&lt;td&gt;39.3 kB&lt;/td&gt;&#10;&lt;td&gt;47.2 kB&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;I haven&apos;t checked the runtime performance, so perhaps there is room for optimization. Of course I want to speed up the polyfill while not bloating the bundle size.&lt;/p&gt;&#10;&lt;h2&gt;Which polyfill should we use?&lt;/h2&gt;&#10;&lt;p&gt;I&apos;ll try to be as objective and honest as I can.&lt;/p&gt;&#10;&lt;h3&gt;Backend projects&lt;/h3&gt;&#10;&lt;p&gt;Introducing Temporal to backend projects sounds very reasonable and promising, because Temporal enables us to handle dates and times in a reliable manner.&lt;/p&gt;&#10;&lt;p&gt;You don&apos;t have to mind bundle size too much for backend. Rather, the primary requirement for these projects is robustness. I believe &lt;code&gt;temporal-polyfill-lite&lt;/code&gt; is the best polyfill for now, but &lt;code&gt;@js-temporal/polyfill&lt;/code&gt; would also be a good option after it is updated (I hope the update will be done in a few weeks). Both polyfills have very few bugs.&lt;/p&gt;&#10;&lt;p&gt;Anyway, Node.js v26 with support for Temporal will move to LTS this October, so we can remove a Temporal polyfill from backend projects soon.&lt;/p&gt;&#10;&lt;h3&gt;Frontend projects&lt;/h3&gt;&#10;&lt;p&gt;Honestly, it would be too early to use Temporal for most frontend projects since it isn&apos;t even &amp;quot;Baseline Newly available&amp;quot; yet and a Temporal polyfill isn&apos;t tiny. However, Temporal is no longer unstable or experimental, so you can try it. In particular, projects using SSG frameworks such as Astro can benefit from Temporal without increasing JavaScript size.&lt;/p&gt;&#10;&lt;p&gt;In my opinion, &lt;code&gt;temporal-polyfill-lite&lt;/code&gt; is the least painful polyfill for frontend projects, because it is up-to-date, least buggy, and the smallest for most developers, at least for now. &lt;code&gt;temporal-polyfill&lt;/code&gt; can be another option after it is fixed and updated.&lt;/p&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;&lt;p&gt;I&apos;ve been following the Temporal proposal for the last two years, always wondering when it would be ready for production. Now I can answer that question with confidence: you can use it today if you really want. If you want to start using Temporal right now, &lt;code&gt;temporal-polyfill-lite&lt;/code&gt; is exactly what you need for the foreseeable future (for a few years at most, I believe).&lt;/p&gt;&#10;&lt;p&gt;If you find any bugs, please feel free to report them on &lt;a href=&quot;https://github.com/fabon-f/temporal-polyfill-lite/issues&quot;&gt;GitHub&lt;/a&gt;. I&apos;ll fix them as soon as possible.&lt;/p&gt;&#10;&lt;p&gt;In closing, it&apos;s a great honor to contribute to Temporal, the unparalleled project in the history of ECMAScript. Long live web standards! Long live ECMAScript!&lt;/p&gt;&#10;&lt;hr class=&quot;footnotes-sep&quot;&gt;&#10;&lt;section class=&quot;footnotes&quot;&gt;&#10;&lt;ol class=&quot;footnotes-list&quot;&gt;&#10;&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The release is originally planned in 22nd April, but it has been postponed until 4th May due to build issues, mainly caused by Temporal implementation. V8 introduced Rust dependencies (ICU4X and &lt;code&gt;temporal_rs&lt;/code&gt;) for the first time to implement Temporal (cf. &lt;a href=&quot;https://github.com/nodejs/node/issues/58730&quot;&gt;nodejs/node#58730&lt;/a&gt;), therefore Node.js have to add Rust toolchains to build pipeline. The work is basically done, but Node.js developers are still struggling with build errors. &lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I agree about the part that it&apos;s a matter of time, but I can&apos;t say irresponsibly that Safari will ship Temporal soon. Honestly, I think it can&apos;t happen in this year. There is still great uncertainty, especially problems of calendrical calculations in ICU4C. I even suspect communication between Igalia and Apple doesn&apos;t work well, or implementation of Temporal has low priority, but I hope I&apos;m wrong. &lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Actually, I&apos;m not even a STEM student. I&apos;m currently studying modern Russian history at the University of Tokyo. &lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;That being said, I&apos;m still exploring how to integrate coding agents into my workflow without losing the parts of coding I find fun. &lt;a href=&quot;https://dnevnik.fabon.info/posts/2026/04/30/temporal-polyfill-lite/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/section&gt;&#10;</content><updated>2026-04-29T17:45:00Z</updated></entry></feed>