From e72ed83f4e4db7b3806253cb787d9658eac18de3 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 27 Apr 2025 20:04:43 -0500 Subject: [PATCH 01/57] Add first blog post for temporal_rs and general Boa Temporal work --- blog/temporal-introduction.md | 408 ++++++++++++++++++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 blog/temporal-introduction.md diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md new file mode 100644 index 00000000..1d449aeb --- /dev/null +++ b/blog/temporal-introduction.md @@ -0,0 +1,408 @@ +--- +authors: boa-dev +--- + +# Implementing Temporal, the new date/time API for JavaScript (and Rust!) + +This will be a series of posts primarily about implementing a new +JavaScript feature in Rust, specifically the new date/time builtin: +Temporal. We'll go over general lessons and to discuss the library we've +been working on. + +Why should you care? Well we are not only implementing it for +JavaScript, but Rust as well ... more on that in a bit. + +First, an aside! + +## What even is Temporal? + +Temporal is a modern API for handling date/time in a calendar and time +zone aware manner that includes nine objects with over 200+ methods. + +In JavaScript, Temporal is a global builtin namespace object that +includes each of these nine builtins: + +- Temporal.Now +- Temporal.PlainDate +- Temporal.PlainTime +- Temporal.PlainDateTime +- Temporal.ZonedDateTime +- Temporal.Duration +- Temporal.Instant +- Temporal.PlainYearMonth +- Temporal.PlainMonthDay + +But to be honest, this post isn't meant to give an overview of Temporal +and its general API. If Temporal is news to you and you are interested +in learning more, feel free to check out the phenomenal [MDN +documentation][mdn-temporal]. + +## Back on track + +Being a JavaScript engine / interpreter, implementing the ECMAScript +specification is our raison d'être. One of our primary goals is to +implement the specification to high degree of conformance. This is even +more so important because Temporal represents roughly 7-8% of the +current conformance test suite (~4000 of the ~50,000 tests). + +When the PR of the first prototype of Temporal for Boa was submitted a +few things became evident. + +1. Date/Time is a complicated beast (duh) +2. There's room for optimization and improvement +3. This would be handy to have in Rust + +So after the prototype was merged, the prototype was pulled out of Boa's +internal builtins and externalized into its own crate, +[temporal_rs][temporal-rs-repo], which then first landed behind an +experimental flag in Boa v0.18. + +After over a year and a half of development, Boa now sits at about 90% +overall conformance for Temporal and growing with the entire +implementation backed by `temporal_rs`. + +For its part, `temporal_rs` is shaping out to be a proper Rust date/time +library that can be used to implement temporal in a JavaScript engine or +for general usage purposes. + +So let's take a look at Temporal: it's JavaScript API, it's Rust API in +temporal_rs, and how temporal_rs supports implementing the +specification. + +## Important core differences + +Let's briefly talk about JavaScript values (`JsValue`). This is +functionally the core `any` value type of JavaScript. A `JsValue` could +be a number represented as a 64 bit floating point, a string, a boolean, +or an object. Not only is it an any, but `JsValue` is ultimately engine +defined with various implementations existing across engines. + +While this is handy for a dynamically typed language like JavaScript, it +is not ideal for implementing deep language specifications where an +object or string may need to be cloned. Furthermore, it's just not great +for an API in a typed language like Rust. + +To work around this, we use liberally `FromStr` and a `FiniteF64` custom +primitive to handle casting and constraining, respectively, to adapt +values for use with a typed API. + +For instance, in Boa, we heavily lean into using the below patterns: + +```rust +// (Note: this is abridged for readability) + +// FiniteF64 usage +let number: f64 = js_value.to_number(context)?; +let finite_f64: FiniteF64 = FiniteF64::try_from(number)?; +let year: i32 = finite_f64.as_integer_with_truncation::(); + +// FromStr usage with `get_option` +let options_obj: &JsObject = get_options_object(&js_value)?; +let overflow: Option = get_option::( + &options_obj, + js_string!("overflow"), + context +)?; +``` + +This is the core glue between Boa and the temporal_rs API that we will +be going over below. + +## Implementing constructors + +There are a variety of ways to construct a core component like +`PlainDate`, and that stems from the core constructor for each of the +core components `new_with_overflow`: + +```rust +impl PlainDate { + pub fn new_with_overflow(year: i32, month: u8, day: u8, calendar: Calendar, overflow: ArithmeticOverflow) -> Result { + // Create PlainDate + } +} +``` + +This function supports the baseline construction of Temporal builtins, +which takes the usual year, month, day, alongside a calendar and also an +overflow option to constrain or reject based on whether the provided +values are in an expected range. + +However, we can better express this in Rust with common `try_` prefix +notation. + +```rust +impl PlainDate { + pub fn new(year: i32, month: u8, day: u8, calendar: Calendar) -> Result { + Self::new_with_overflow(year, month, day, calendar, ArithmeticOverflow::Constrain) + } + + pub fn try_new(year: i32, month: u8, day: u8, calendar: Calendar) -> Result { + Self::new_with_overflow(year, month, day, calendar, ArithmeticOverflow::Reject) + } +} +``` + +These methods are flexible enough and allow full coverage of the +Temporal specification. + +For instance, take the below constructor: + +```js +const plainDate = Temporal.PlainDate(2025, 6, 9); +``` + +Can easily be conveyed in Rust as: + +```rust +let plain_date = PlainDate::try_new(2025, 6, 9, Calendar::default())?; +``` + +We actually learn some interesting things immediately about the +JavaScript API from looking at the temporal_rs API: + +1. Temporal.PlainDate constructor can throw. +2. When the calendar is omitted, the default calendar is used (this will + default to the `iso8601` calendar) + +Of course, if you somewhat prefer the brevity of the JavaScript API and +don't want to list the default Calendar, temporal_rs provides the +additional constructors `new_iso` and `try_new_iso`. + +## Let's discuss Now + +> Colonel Sandurz: Now. You're looking at now, sir. Everything that +> happens now, is happening now.

Dark Helmet: What happened to +> then?

Colonel Sandurz: We passed then.

Dark Helmet: +> When?

Colonel Sandurz: Just now. We're at now now.

+> Dark Helmet: Go back to then.

Colonel Sandurz: When?

+> Dark Helmet: Now.

Colonel Sandurz: Now?

Dark Helmet: +> Now.

Colonel Sandurz: I can't.

Dark Helmet: +> Why?

Colonel Sandurz: We missed it.

Dark Helmet: +> When?

Colonel Sandurz: Just now.

Dark Helmet: When +> will then be now?

-- Spaceballs, 1987 + +`Temporal.Now` is an incredibly strange type, yet nevertheless +important. It is the object from which the current instant can be +measured and mapped into any of the Temporal components. + +In JavaScript, this type has no [[Construct]] or [[Call]] internal +method, which is a fancy way to say that Now has no constructor and +cannot be called directly. + +Instead, Now is used primarily as a namespace for it's methods. + +And this was reflected in early adaptions of Now, which looked more or +less like the below: + +```rust +struct Now; + +impl Now { + pub fn instant() -> Instant; + + pub fn zoned_date_time_iso() -> ZonedDateTime; +} +``` + +Interestingly enough, the above implementation is incorrect, or at the +very least not ideal. + +Hidden in the specification steps for Now are some very tricky steps +invoking the abstract operations: `SystemTimeZoneIdentifier` and +`SystemUtcEpochNanoseconds`. That's great, let's just use the usual +suspects `SystemTime` and `iana-time-zone`, merge it, and call it a day +on the implementation, right? + +Except the core purpose of temporal_rs is that it can be used in any +engine implementation, accessing a system clock and system time zone are +not in scope and must be left up to the engine or runtime to provide +that functionality. + +So how did we end up implementing Now if we have no access to the system +clock or time zone? Well, a builder pattern of course! + +```rust +#[derive(Default)] +pub struct NowBuilder { + clock: Option, + zone: Option, +} + +impl NowBuilder { + pub fn with_system_nanoseconds(mut self, nanoseconds: EpochNanoseconds) -> Self { + self.clock = Some(nanoseconds); + self + } + + pub fn with_system_zone(mut self, zone: TimeZone) -> Self { + self.zone = Some(zone); + self + } + + pub fn build(self) -> Now { + Now { + clock: self.clock, + zone: self.zone.unwrap_or_default(), + } + } +} + +pub struct Now { + clock: Option, + zone: TimeZone, +} +``` + +Once we've constructed `Now`, then we are off to the races! + +The nice part about this approach is that it also allows a `std` +implementation that can be feature gated for general users that are not +concerned with `no_std`. + +```rust + // Available with the `sys` feature flag + use temporal_rs::Temporal; + let now = Temporal::now().instant(); +``` + +## Partial API + +There's an interesting method on each of the Temporal built-ins that I'd +assume most people who have used Rust would be familiar with `from`. But +this isn't Rust's friendly `From` trait. No, this `from` is a behemoth +method that takes a `JsValue` and automagically gives you back the +built-in that you'd like or throws. That's right! Give it a string, give +it a property bag, give it another built-in; `from` will figure it out +for you! + +Simple, right? + +Well we're pleased to announce that temporal_rs won't be supporting +that! ... At least in one method. + +Again, the goal of `temporal_rs` is to implement the specification to +the highest degree possible and where it can't implement the +specification like in the case of a `from`, it provides methods +to support the implementation of Temporal in engines. + +Let's take a look at some valid uses of `from` in JavaScript to +construct a `PlainDate`. + +```js +// Create a `PlainDateTime` +const pdt = new Temporal.PlainDateTime(2025, 1, 1); +// We can use the `PlainDateTime` (`ZonedDateTime` / `PlainDate` are also options). +const pd_from_pdt = Temporal.PlainDate.from(pdt); +// We can use a string. +const pd_from_string = Temporal.PlainDate.from("2025-01-01"); +// We can use a property bag. +const pd_from_property_bag = Temporal.PlainDate.from({ + year: 2025, + month: 1, + day: 1, +}); +``` + +It turns out that the above operations is all that needs to be +implemented by `temporal_rs` in order to support a Temporal +implementation, we just need to implement `From`, +`From`, `FromStr`, and `From` ... oh. Did I +mention `JsObject`, like `JsValue`, is implementation defined as well? + +This is where `temporal_rs`'s Partial API comes in. + +It turns out that while property bags in JavaScript can have various +fields set, there is still a general shape for the fields that can be +provided and validated in Temporal. + +So in order to support this in `temporal_rs`, a "partial" component +exists for each of the components that can then be provided to that +components `from_partial` method. + +With this, we have fully implemented support for the `from` method in +`temporal_rs` + +```rust +let pdt = PlainDateTime::try_new_iso(2025, 1, 1)?; +// We can use the `PlainDateTime` (`ZonedDateTime` / `PlainDate` are also options). +let pd_from_pdt = PlainDate::from(pdt); +// We can use a `str`. +let pd_from_string = PlainDate::from_str("2025-01-01")?; +// We can use a `PartialDate`. +let pd_from_partial = PlainDate::from_partial(PartialDate { + year: Some(2025), + month: Some(1), + day: Some(1), + ..Default::default() +}); +``` + +**NOTE:** there may be updates to `PartialDate` in the future (see +[boa-dev/temporal #349](https://github.com/boa-dev/temporal/issues/349) +for more information). + +## Elephant in the room: time zones + +So far we have not dicussed time zones, and -- suprise! -- we aren't +going to ... yet. It's not because they aren't super cool and +interesting and everyone totally 100% loves them. No, time zones aren't +in this post, because they are still being polished and deserve an +entire post of their own. + +## Conclusion + +In conclusion, we're implementing Temporal in Rust to support engine +implementors as well as to have the API available in native Rust in +general. + +Boa currently sit at a [90% conformance rate][boa-test262] for Temporal +completely backed by temporal_rs v0.0.8, and we're aiming to be 100% +conformant before the end of the year. + +If you're interested in trying Temporal using Boa, you can use it in +Boa's CLI or enable it in `boa_engine` with the `experimental` flag. + +If you're interested in trying out `temporal_rs`, feel free to add to +your project with cargo: + +```bash +cargo add temporal_rs +``` + +or by adding the below to your `Cargo.toml` + +```toml +temporal_rs = "0.0.9" +``` + +A FFI version of temporal is also available for C and C++ via +temporal_capi. + +## General note on API stability + +While the majority of the APIs discussed above are expected to be mostly +stable. Temporal is still a stage 3 proposal that is not fully accepted +into the ECMAScript specification. Any normative change that may be made +upstream in the ECMAScript or ECMA402 specification will also be +reflected in `temporal_rs`. + +There are also a few outstanding issues with changes that may reflect in +the API. + +1. Duration's inner repr and related ctors +2. TemporalError's inner repr +3. Partial objects may need some adjustments to handle differences + between `from_partial` and `with` +4. Time zone provider's and the `TimeZoneProvider` trait are still + largely unstable (although the APIs that use them are expected to be + stable) +5. Era and month code are still be discussed in the intl-era-month-code + proposal, so some calendars and calendar methods may have varying + levels of support. + +The above issues are considered blocking for a 0.1.0 release. + +[mdn-temporal]: + https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal +[temporal-rs-repo]: https://github.com/boa-dev/temporal +[boa-test262]: https://test262.fyi/#|boa From cb09862c2f4d5af4f2dc41e84e4764b24c0f1312 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sat, 14 Jun 2025 17:43:36 -0500 Subject: [PATCH 02/57] Some small adjustments and cleanup --- blog/temporal-introduction.md | 46 ++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 1d449aeb..ee3297b5 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -6,8 +6,8 @@ authors: boa-dev This will be a series of posts primarily about implementing a new JavaScript feature in Rust, specifically the new date/time builtin: -Temporal. We'll go over general lessons and to discuss the library we've -been working on. +Temporal. We'll be going over the general implementation of Temporal in +Boa as well as the crates supporting that implementation. Why should you care? Well we are not only implementing it for JavaScript, but Rust as well ... more on that in a bit. @@ -54,19 +54,19 @@ few things became evident. So after the prototype was merged, the prototype was pulled out of Boa's internal builtins and externalized into its own crate, -[temporal_rs][temporal-rs-repo], which then first landed behind an +[`temporal_rs`][temporal-rs-repo], which then first landed behind an experimental flag in Boa v0.18. After over a year and a half of development, Boa now sits at about 90% overall conformance for Temporal and growing with the entire implementation backed by `temporal_rs`. -For its part, `temporal_rs` is shaping out to be a proper Rust date/time +For its part, `temporal_rs` is shaping up to be a proper Rust date/time library that can be used to implement temporal in a JavaScript engine or for general usage purposes. So let's take a look at Temporal: it's JavaScript API, it's Rust API in -temporal_rs, and how temporal_rs supports implementing the +`temporal_rs`, and how `temporal_rs` supports implementing the specification. ## Important core differences @@ -82,7 +82,7 @@ is not ideal for implementing deep language specifications where an object or string may need to be cloned. Furthermore, it's just not great for an API in a typed language like Rust. -To work around this, we use liberally `FromStr` and a `FiniteF64` custom +To work around this, we routinely use `FromStr` and a `FiniteF64` custom primitive to handle casting and constraining, respectively, to adapt values for use with a typed API. @@ -105,7 +105,7 @@ let overflow: Option = get_option::( )?; ``` -This is the core glue between Boa and the temporal_rs API that we will +This is the core glue between Boa and the `temporal_rs` API that we will be going over below. ## Implementing constructors @@ -158,14 +158,14 @@ let plain_date = PlainDate::try_new(2025, 6, 9, Calendar::default())?; ``` We actually learn some interesting things immediately about the -JavaScript API from looking at the temporal_rs API: +JavaScript API from looking at the `temporal_rs` API: 1. Temporal.PlainDate constructor can throw. 2. When the calendar is omitted, the default calendar is used (this will default to the `iso8601` calendar) Of course, if you somewhat prefer the brevity of the JavaScript API and -don't want to list the default Calendar, temporal_rs provides the +don't want to list the default Calendar, `temporal_rs` provides the additional constructors `new_iso` and `try_new_iso`. ## Let's discuss Now @@ -213,7 +213,7 @@ invoking the abstract operations: `SystemTimeZoneIdentifier` and suspects `SystemTime` and `iana-time-zone`, merge it, and call it a day on the implementation, right? -Except the core purpose of temporal_rs is that it can be used in any +Except the core purpose of `temporal_rs` is that it can be used in any engine implementation, accessing a system clock and system time zone are not in scope and must be left up to the engine or runtime to provide that functionality. @@ -277,7 +277,7 @@ for you! Simple, right? -Well we're pleased to announce that temporal_rs won't be supporting +Well we're pleased to announce that `temporal_rs` won't be supporting that! ... At least in one method. Again, the goal of `temporal_rs` is to implement the specification to @@ -320,9 +320,11 @@ exists for each of the components that can then be provided to that components `from_partial` method. With this, we have fully implemented support for the `from` method in -`temporal_rs` +`temporal_rs`: ```rust +use core::str::FromStr; +use temporal_rs::{PlainDate, PlainDateTime, partial::PartialDate}; let pdt = PlainDateTime::try_new_iso(2025, 1, 1)?; // We can use the `PlainDateTime` (`ZonedDateTime` / `PlainDate` are also options). let pd_from_pdt = PlainDate::from(pdt); @@ -349,21 +351,31 @@ interesting and everyone totally 100% loves them. No, time zones aren't in this post, because they are still being polished and deserve an entire post of their own. +So stay tuned for our next post on implementing Temporal! The one where +we'll hopefully go over everyone's favorite subject, time zones; and +answer the question that some of you may have if you happen to take a +glance at `temporal_rs`'s docs or try out our `no_std` support: what in +the world is a provider API? + ## Conclusion In conclusion, we're implementing Temporal in Rust to support engine implementors as well as to have the API available in native Rust in general. -Boa currently sit at a [90% conformance rate][boa-test262] for Temporal -completely backed by temporal_rs v0.0.8, and we're aiming to be 100% +Boa currently sits at a [90% conformance rate][boa-test262] for Temporal +completely backed by `temporal_rs` v0.0.8, and we're aiming to be 100% conformant before the end of the year. If you're interested in trying Temporal using Boa, you can use it in Boa's CLI or enable it in `boa_engine` with the `experimental` flag. +Outside of Boa's implementation, `temporal_rs` has implemented or +supports the implementation for a large portion of the Temporal's API in +native Rust. + If you're interested in trying out `temporal_rs`, feel free to add to -your project with cargo: +your project with Cargo: ```bash cargo add temporal_rs @@ -394,8 +406,8 @@ the API. 3. Partial objects may need some adjustments to handle differences between `from_partial` and `with` 4. Time zone provider's and the `TimeZoneProvider` trait are still - largely unstable (although the APIs that use them are expected to be - stable) + largely unstable. Although, the provider APIs that use them are + expected to be stable (spoilers!) 5. Era and month code are still be discussed in the intl-era-month-code proposal, so some calendars and calendar methods may have varying levels of support. From 94d1daf82b7164040f3c12e2c19a397292b57a6a Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:31:53 -0500 Subject: [PATCH 03/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index ee3297b5..4a906bf4 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -22,15 +22,15 @@ zone aware manner that includes nine objects with over 200+ methods. In JavaScript, Temporal is a global builtin namespace object that includes each of these nine builtins: -- Temporal.Now -- Temporal.PlainDate -- Temporal.PlainTime -- Temporal.PlainDateTime -- Temporal.ZonedDateTime -- Temporal.Duration -- Temporal.Instant -- Temporal.PlainYearMonth -- Temporal.PlainMonthDay +- `Temporal.Now` +- `Temporal.PlainDate` +- `Temporal.PlainTime` +- `Temporal.PlainDateTime` +- `Temporal.ZonedDateTime` +- `Temporal.Duration` +- `Temporal.Instant` +- `Temporal.PlainYearMonth` +- `Temporal.PlainMonthDay` But to be honest, this post isn't meant to give an overview of Temporal and its general API. If Temporal is news to you and you are interested From a63381b56e632015d1c4de3cda272456ffdf3332 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:32:03 -0500 Subject: [PATCH 04/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 4a906bf4..0bee56c1 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -160,7 +160,7 @@ let plain_date = PlainDate::try_new(2025, 6, 9, Calendar::default())?; We actually learn some interesting things immediately about the JavaScript API from looking at the `temporal_rs` API: -1. Temporal.PlainDate constructor can throw. +1. `Temporal.PlainDate` constructor can throw. 2. When the calendar is omitted, the default calendar is used (this will default to the `iso8601` calendar) From 19b04b3006e26e38d0b7e5e322e63e495e7c16a0 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:32:10 -0500 Subject: [PATCH 05/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 0bee56c1..0c3544cd 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -165,7 +165,7 @@ JavaScript API from looking at the `temporal_rs` API: default to the `iso8601` calendar) Of course, if you somewhat prefer the brevity of the JavaScript API and -don't want to list the default Calendar, `temporal_rs` provides the +don't want to list the default `Calendar`, `temporal_rs` provides the additional constructors `new_iso` and `try_new_iso`. ## Let's discuss Now From cb061ad6a77140ef0143f7fd1584424b05c913f3 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:32:18 -0500 Subject: [PATCH 06/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 0c3544cd..3cbd09a2 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -185,7 +185,7 @@ additional constructors `new_iso` and `try_new_iso`. important. It is the object from which the current instant can be measured and mapped into any of the Temporal components. -In JavaScript, this type has no [[Construct]] or [[Call]] internal +In JavaScript, this type has no `[[Construct]]` or `[[Call]]` internal method, which is a fancy way to say that Now has no constructor and cannot be called directly. From c605f41d1b6de5743ed0abc701de88a7263872be Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:32:28 -0500 Subject: [PATCH 07/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 3cbd09a2..c5beabd1 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -5,7 +5,7 @@ authors: boa-dev # Implementing Temporal, the new date/time API for JavaScript (and Rust!) This will be a series of posts primarily about implementing a new -JavaScript feature in Rust, specifically the new date/time builtin: +JavaScript feature in Rust, specifically the new date/time built-in: Temporal. We'll be going over the general implementation of Temporal in Boa as well as the crates supporting that implementation. From ef7a2837ab9c5337ff14bea3bc0f9bdd57d356ee Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:33:06 -0500 Subject: [PATCH 08/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index c5beabd1..1ef86b7a 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -19,8 +19,8 @@ First, an aside! Temporal is a modern API for handling date/time in a calendar and time zone aware manner that includes nine objects with over 200+ methods. -In JavaScript, Temporal is a global builtin namespace object that -includes each of these nine builtins: +In JavaScript, Temporal is a global built-in namespace object that +includes each of these nine built-ins: - `Temporal.Now` - `Temporal.PlainDate` From f0a80d21ecebd4c8e2cbfdab15bb065d8d4d0cff Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:33:50 -0500 Subject: [PATCH 09/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 1ef86b7a..d8adb039 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -189,7 +189,7 @@ In JavaScript, this type has no `[[Construct]]` or `[[Call]]` internal method, which is a fancy way to say that Now has no constructor and cannot be called directly. -Instead, Now is used primarily as a namespace for it's methods. +Instead, Now is used primarily as a namespace for its methods. And this was reflected in early adaptions of Now, which looked more or less like the below: From e0061f28c58b30f55939c291883f1cdd1089ef28 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:34:00 -0500 Subject: [PATCH 10/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index d8adb039..9f874c37 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -168,7 +168,7 @@ Of course, if you somewhat prefer the brevity of the JavaScript API and don't want to list the default `Calendar`, `temporal_rs` provides the additional constructors `new_iso` and `try_new_iso`. -## Let's discuss Now +## Let's discuss `Now` > Colonel Sandurz: Now. You're looking at now, sir. Everything that > happens now, is happening now.

Dark Helmet: What happened to From 09fbe650d0282136dee70c3e9c962e6bf08f2303 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:34:34 -0500 Subject: [PATCH 11/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 9f874c37..9906da94 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -345,7 +345,7 @@ for more information). ## Elephant in the room: time zones -So far we have not dicussed time zones, and -- suprise! -- we aren't +So far we have not discussed time zones, and -- surprise! -- we aren't going to ... yet. It's not because they aren't super cool and interesting and everyone totally 100% loves them. No, time zones aren't in this post, because they are still being polished and deserve an From eaf5bdbce3e3065e5e0b0f96c8d16c19f819086e Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:34:41 -0500 Subject: [PATCH 12/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 9906da94..6e9e884c 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -388,7 +388,7 @@ temporal_rs = "0.0.9" ``` A FFI version of temporal is also available for C and C++ via -temporal_capi. +`temporal_capi`. ## General note on API stability From 704e886a43a70f6b50e6b79ce9f3ff50e703b6e5 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:34:49 -0500 Subject: [PATCH 13/57] Update blog/temporal-introduction.md Co-authored-by: Haled Odat <8566042+HalidOdat@users.noreply.github.com> --- blog/temporal-introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/temporal-introduction.md b/blog/temporal-introduction.md index 6e9e884c..bf80808f 100644 --- a/blog/temporal-introduction.md +++ b/blog/temporal-introduction.md @@ -401,7 +401,7 @@ reflected in `temporal_rs`. There are also a few outstanding issues with changes that may reflect in the API. -1. Duration's inner repr and related ctors +1. Duration's inner repr and related constructors. 2. TemporalError's inner repr 3. Partial objects may need some adjustments to handle differences between `from_partial` and `with` From 409f3a4fdb18c2a098f66bce63fd5bea26a7cc48 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:57:08 -0500 Subject: [PATCH 14/57] Housekeeping / add metadata info to blog post --- ...introduction.md => 2025-06-15-temporal-impl-1.md} | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) rename blog/{temporal-introduction.md => 2025-06-15-temporal-impl-1.md} (97%) diff --git a/blog/temporal-introduction.md b/blog/2025-06-15-temporal-impl-1.md similarity index 97% rename from blog/temporal-introduction.md rename to blog/2025-06-15-temporal-impl-1.md index bf80808f..ce8a5183 100644 --- a/blog/temporal-introduction.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -1,9 +1,17 @@ --- +layout: post +tags: [post] +title: + Implementing Temporal, the new date/time API for JavaScript (and + Rust!) +metadata: ["temporal", "temporal_rs", "boa", "date/time"] +description: + A blog post about the temporal_rs Rust crate that implements + JavaScript's Temporal API and how temporal_rs supports implementing + Temporal in JavaScript engines. authors: boa-dev --- -# Implementing Temporal, the new date/time API for JavaScript (and Rust!) - This will be a series of posts primarily about implementing a new JavaScript feature in Rust, specifically the new date/time built-in: Temporal. We'll be going over the general implementation of Temporal in From 3e6bf23780f90491d4d0c74ef8b290517309f004 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 09:29:03 -0500 Subject: [PATCH 15/57] A couple edits to the constructor section --- blog/2025-06-15-temporal-impl-1.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index ce8a5183..1ce3c6cc 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -150,18 +150,19 @@ impl PlainDate { } ``` -These methods are flexible enough and allow full coverage of the -Temporal specification. +These three constructors, `new_with_overflow`, `try_new`, and `new`, are +fairly flexible and provide full coverage of the Temporal specification. For instance, take the below constructor: ```js -const plainDate = Temporal.PlainDate(2025, 6, 9); +const plainDate = new Temporal.PlainDate(2025, 6, 9); ``` Can easily be conveyed in Rust as: ```rust +use temporal_rs::PlainDate; let plain_date = PlainDate::try_new(2025, 6, 9, Calendar::default())?; ``` @@ -176,6 +177,16 @@ Of course, if you somewhat prefer the brevity of the JavaScript API and don't want to list the default `Calendar`, `temporal_rs` provides the additional constructors `new_iso` and `try_new_iso`. +```rust +use temporal_rs::PlainDate; +let plain_date = PlainDate::try_new_iso(2025, 6, 9)?; +``` + +Interestingly enough, the `_iso` constructors are actually extensions of +Temporal specification to provide a similar API in Rust. This is because +the `_iso` constructors are assumed to exist due to resolving an +`undefined` calendar to the default ISO calendar. + ## Let's discuss `Now` > Colonel Sandurz: Now. You're looking at now, sir. Everything that From 6352eb6f3ea6ec8c2149875dade7ef45fae43dff Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:19:15 -0500 Subject: [PATCH 16/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 1ce3c6cc..87dd29cf 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -400,7 +400,7 @@ your project with Cargo: cargo add temporal_rs ``` -or by adding the below to your `Cargo.toml` +or by adding the below in the `[dependencies]` section of your `Cargo.toml`: ```toml temporal_rs = "0.0.9" From 9f1e029e3e3ece929da3bedd53aadaf1a1bb523c Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:19:57 -0500 Subject: [PATCH 17/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 87dd29cf..470a956d 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -14,8 +14,8 @@ authors: boa-dev This will be a series of posts primarily about implementing a new JavaScript feature in Rust, specifically the new date/time built-in: -Temporal. We'll be going over the general implementation of Temporal in -Boa as well as the crates supporting that implementation. +Temporal. We'll be going over general lessons and interesting design choices we've +stumbled upon, as well as the crates supporting that implementation. Why should you care? Well we are not only implementing it for JavaScript, but Rust as well ... more on that in a bit. From 15ffd2c07cb0652c346e7fd6dea8e4c812d2f2df Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:25:07 -0500 Subject: [PATCH 18/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 470a956d..2cdcdddd 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -47,10 +47,10 @@ documentation][mdn-temporal]. ## Back on track -Being a JavaScript engine / interpreter, implementing the ECMAScript -specification is our raison d'être. One of our primary goals is to -implement the specification to high degree of conformance. This is even -more so important because Temporal represents roughly 7-8% of the +Being Boa a JavaScript engine / interpreter, developing a correct +implementation of the ECMAScript specification is our raison d'être. +This, in consequence, makes implementing Temporal one of our most +important goals, since it represents roughly 7-8% of the current conformance test suite (~4000 of the ~50,000 tests). When the PR of the first prototype of Temporal for Boa was submitted a From da5786f80b15c2e6f9fffab46eb1f511caefa006 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:26:19 -0500 Subject: [PATCH 19/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 2cdcdddd..a7a9e72a 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -53,8 +53,8 @@ This, in consequence, makes implementing Temporal one of our most important goals, since it represents roughly 7-8% of the current conformance test suite (~4000 of the ~50,000 tests). -When the PR of the first prototype of Temporal for Boa was submitted a -few things became evident. +When the PR of the first prototype of Temporal for Boa was submitted, a +few things became evident: 1. Date/Time is a complicated beast (duh) 2. There's room for optimization and improvement From b4b15d8033821e89d7855980b53018a5a3f443b6 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:26:55 -0500 Subject: [PATCH 20/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index a7a9e72a..7496a268 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -65,9 +65,9 @@ internal builtins and externalized into its own crate, [`temporal_rs`][temporal-rs-repo], which then first landed behind an experimental flag in Boa v0.18. -After over a year and a half of development, Boa now sits at about 90% -overall conformance for Temporal and growing with the entire -implementation backed by `temporal_rs`. +After over a year and a half of development, Boa now sits at a conformance +of about 90% for Temporal (and growing), with the entire implementation +being backed by `temporal_rs`. For its part, `temporal_rs` is shaping up to be a proper Rust date/time library that can be used to implement temporal in a JavaScript engine or From 4e70741f9f81585c9d73dbed8d3e416499b45f86 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:27:26 -0500 Subject: [PATCH 21/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 7496a268..c29f53d9 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -60,7 +60,7 @@ few things became evident: 2. There's room for optimization and improvement 3. This would be handy to have in Rust -So after the prototype was merged, the prototype was pulled out of Boa's +So after the prototype was merged, we pulled it out of Boa's internal builtins and externalized into its own crate, [`temporal_rs`][temporal-rs-repo], which then first landed behind an experimental flag in Boa v0.18. From 511dbe3c735db7c70fc4c3a830faae17ecc6027e Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:30:48 -0500 Subject: [PATCH 22/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index c29f53d9..4159dcee 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -393,8 +393,8 @@ Outside of Boa's implementation, `temporal_rs` has implemented or supports the implementation for a large portion of the Temporal's API in native Rust. -If you're interested in trying out `temporal_rs`, feel free to add to -your project with Cargo: +If you're interested in trying out `temporal_rs`, feel free to add it to +your dependencies with the command: ```bash cargo add temporal_rs From b111fb14f3563de3eeadb6bddeef4cd0a025d52e Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:33:09 -0500 Subject: [PATCH 23/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 4159dcee..cedb2655 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -73,7 +73,7 @@ For its part, `temporal_rs` is shaping up to be a proper Rust date/time library that can be used to implement temporal in a JavaScript engine or for general usage purposes. -So let's take a look at Temporal: it's JavaScript API, it's Rust API in +Let's take a look at Temporal: it's JavaScript API, it's Rust API in `temporal_rs`, and how `temporal_rs` supports implementing the specification. From dbee951590f0b115e158bcf6fd01dfdda12f50ba Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:33:38 -0500 Subject: [PATCH 24/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index cedb2655..d16a7edf 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -91,8 +91,8 @@ object or string may need to be cloned. Furthermore, it's just not great for an API in a typed language like Rust. To work around this, we routinely use `FromStr` and a `FiniteF64` custom -primitive to handle casting and constraining, respectively, to adapt -values for use with a typed API. +primitive to handle casting and constraining, respectively, which +glues dynamic types like `JsValue` with a typed API. For instance, in Boa, we heavily lean into using the below patterns: From 2e2dbbd61c4a9ab4949984059558427959d8cdd1 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:34:06 -0500 Subject: [PATCH 25/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index d16a7edf..4fcd9089 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -82,7 +82,7 @@ specification. Let's briefly talk about JavaScript values (`JsValue`). This is functionally the core `any` value type of JavaScript. A `JsValue` could be a number represented as a 64 bit floating point, a string, a boolean, -or an object. Not only is it an any, but `JsValue` is ultimately engine +or an object. Not only is it an `any`, but `JsValue` is ultimately engine defined with various implementations existing across engines. While this is handy for a dynamically typed language like JavaScript, it From bbd66cbdf3a379bfa459a9164b70bbe89df11d76 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:45:42 -0500 Subject: [PATCH 26/57] Update 2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 4fcd9089..9c706db5 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -120,7 +120,7 @@ be going over below. There are a variety of ways to construct a core component like `PlainDate`, and that stems from the core constructor for each of the -core components `new_with_overflow`: +core components: `new_with_overflow`. ```rust impl PlainDate { From 907ae55142dd1e2d59eef54b8093f4f2abb34751 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:46:06 -0500 Subject: [PATCH 27/57] Update 2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 9c706db5..177dafbb 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -159,7 +159,7 @@ For instance, take the below constructor: const plainDate = new Temporal.PlainDate(2025, 6, 9); ``` -Can easily be conveyed in Rust as: +This code can easily be translated to Rust as: ```rust use temporal_rs::PlainDate; From 00081e2ee229a96c6e1fbc0d675eb84d3589f62f Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:46:19 -0500 Subject: [PATCH 28/57] Update 2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 177dafbb..8d48bb2d 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -153,7 +153,7 @@ impl PlainDate { These three constructors, `new_with_overflow`, `try_new`, and `new`, are fairly flexible and provide full coverage of the Temporal specification. -For instance, take the below constructor: +For instance, take the below snippet: ```js const plainDate = new Temporal.PlainDate(2025, 6, 9); From 844d6538db35ca31f83049cb74a0a6e7959ba3d6 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:46:46 -0500 Subject: [PATCH 29/57] Update 2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 8d48bb2d..d876cf19 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -166,7 +166,7 @@ use temporal_rs::PlainDate; let plain_date = PlainDate::try_new(2025, 6, 9, Calendar::default())?; ``` -We actually learn some interesting things immediately about the +Furthermore, we actually learn some interesting things about the JavaScript API from looking at the `temporal_rs` API: 1. `Temporal.PlainDate` constructor can throw. From a0c9cd7192b9914442edcc1934517ad12c87ab2d Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:56:01 -0500 Subject: [PATCH 30/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index d876cf19..db88f64f 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -233,9 +233,9 @@ suspects `SystemTime` and `iana-time-zone`, merge it, and call it a day on the implementation, right? Except the core purpose of `temporal_rs` is that it can be used in any -engine implementation, accessing a system clock and system time zone are -not in scope and must be left up to the engine or runtime to provide -that functionality. +engine implementation, and accessing a system clock and system time zone +is sometimes difficult for engines that support targets like embedded systems. +Thus, this functionality must be delegated to the engine or runtime ... somehow. So how did we end up implementing Now if we have no access to the system clock or time zone? Well, a builder pattern of course! From 4dcc46d02d5d096f605228f67439807dc53fc11e Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:56:41 -0500 Subject: [PATCH 31/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index db88f64f..f50f514d 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -287,7 +287,7 @@ concerned with `no_std`. ## Partial API There's an interesting method on each of the Temporal built-ins that I'd -assume most people who have used Rust would be familiar with `from`. But +assume most people who have used Rust would be familiar with: `from`. But this isn't Rust's friendly `From` trait. No, this `from` is a behemoth method that takes a `JsValue` and automagically gives you back the built-in that you'd like or throws. That's right! Give it a string, give From 4cde4d103339f4c6d8f1cf6d13be69244a532361 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:57:10 -0500 Subject: [PATCH 32/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index f50f514d..5a307165 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -169,7 +169,7 @@ let plain_date = PlainDate::try_new(2025, 6, 9, Calendar::default())?; Furthermore, we actually learn some interesting things about the JavaScript API from looking at the `temporal_rs` API: -1. `Temporal.PlainDate` constructor can throw. +1. The `Temporal.PlainDate` constructor can throw. 2. When the calendar is omitted, the default calendar is used (this will default to the `iso8601` calendar) From 38c5834af9c8b2394b65af98fc80b7764a7f7e31 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:59:52 -0500 Subject: [PATCH 33/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 5a307165..43fe1187 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -237,8 +237,8 @@ engine implementation, and accessing a system clock and system time zone is sometimes difficult for engines that support targets like embedded systems. Thus, this functionality must be delegated to the engine or runtime ... somehow. -So how did we end up implementing Now if we have no access to the system -clock or time zone? Well, a builder pattern of course! +How did we end up implementing `Now` if we have no access to the system +clock or time zone? Well ... a builder pattern of course! ```rust #[derive(Default)] From a0f6f35402c53af65c81bcc5d81f84be99b34cca Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:00:40 -0500 Subject: [PATCH 34/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 43fe1187..6685cc79 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -291,8 +291,8 @@ assume most people who have used Rust would be familiar with: `from`. But this isn't Rust's friendly `From` trait. No, this `from` is a behemoth method that takes a `JsValue` and automagically gives you back the built-in that you'd like or throws. That's right! Give it a string, give -it a property bag, give it another built-in; `from` will figure it out -for you! +it a property bag, give it an instance of another Temporal built-in; +`from` will figure it out for you! Simple, right? From f0b92ebc89382e3cbc74c466e204441f9b905e1a Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:08:07 -0500 Subject: [PATCH 35/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 6685cc79..3f1470cc 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -70,8 +70,7 @@ of about 90% for Temporal (and growing), with the entire implementation being backed by `temporal_rs`. For its part, `temporal_rs` is shaping up to be a proper Rust date/time -library that can be used to implement temporal in a JavaScript engine or -for general usage purposes. +library that can be used to implement Temporal in a JavaScript engine, and even support general date/time use cases. Let's take a look at Temporal: it's JavaScript API, it's Rust API in `temporal_rs`, and how `temporal_rs` supports implementing the From 2f1f1c15342a6acae366bf2595b63de6eeb9a4e1 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:09:34 -0500 Subject: [PATCH 36/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 3f1470cc..d6e0302a 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -366,7 +366,7 @@ for more information). So far we have not discussed time zones, and -- surprise! -- we aren't going to ... yet. It's not because they aren't super cool and interesting and everyone totally 100% loves them. No, time zones aren't -in this post, because they are still being polished and deserve an +in this post because they are still being polished and deserve an entire post of their own. So stay tuned for our next post on implementing Temporal! The one where From 1df7aac7fa45a6f7255bf5be64d93bacb1a7d1b8 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:10:10 -0500 Subject: [PATCH 37/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index d6e0302a..bedf9fba 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -303,7 +303,7 @@ the highest degree possible and where it can't implement the specification like in the case of a `from`, it provides methods to support the implementation of Temporal in engines. -Let's take a look at some valid uses of `from` in JavaScript to +To exemplify this, let's take a look at some valid uses of `from` in JavaScript to construct a `PlainDate`. ```js From e3dd3319c769a26bbe04310514a3fba7e92f6bf8 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:10:28 -0500 Subject: [PATCH 38/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index bedf9fba..81d84f2e 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -295,8 +295,8 @@ it a property bag, give it an instance of another Temporal built-in; Simple, right? -Well we're pleased to announce that `temporal_rs` won't be supporting -that! ... At least in one method. +Folks, we're pleased to announce that `temporal_rs` won't be supporting +that! ... or at least not in that shape. Again, the goal of `temporal_rs` is to implement the specification to the highest degree possible and where it can't implement the From b037258396f1904fdc92edcf92cdf6d9ebee5296 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:12:46 -0500 Subject: [PATCH 39/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 81d84f2e..fb768154 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -335,7 +335,7 @@ provided and validated in Temporal. So in order to support this in `temporal_rs`, a "partial" component exists for each of the components that can then be provided to that -components `from_partial` method. +component's `from_partial` method. With this, we have fully implemented support for the `from` method in `temporal_rs`: From a3cc93d26d976c3e9126335bd67efdc54dac1840 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:13:02 -0500 Subject: [PATCH 40/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index fb768154..bc0b5fb1 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -365,7 +365,7 @@ for more information). So far we have not discussed time zones, and -- surprise! -- we aren't going to ... yet. It's not because they aren't super cool and -interesting and everyone totally 100% loves them. No, time zones aren't +interesting and everyone _totally_ 100% loves them. No, time zones aren't in this post because they are still being polished and deserve an entire post of their own. From 3b43b89362d423f94b919b8c8cb4d8e2ef93fbf3 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:14:03 -0500 Subject: [PATCH 41/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index bc0b5fb1..f59baae6 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -333,7 +333,7 @@ It turns out that while property bags in JavaScript can have various fields set, there is still a general shape for the fields that can be provided and validated in Temporal. -So in order to support this in `temporal_rs`, a "partial" component +To support this in `temporal_rs`, a "partial" component exists for each of the components that can then be provided to that component's `from_partial` method. From 77d6e13965b596d94eaf851498f743a84177ec99 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:14:21 -0500 Subject: [PATCH 42/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index f59baae6..31ac3f3f 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -329,7 +329,7 @@ mention `JsObject`, like `JsValue`, is implementation defined as well? This is where `temporal_rs`'s Partial API comes in. -It turns out that while property bags in JavaScript can have various +It turns out that, while property bags in JavaScript can have various fields set, there is still a general shape for the fields that can be provided and validated in Temporal. From 6dd2b0c1c1ed21178d1ddbd4fd48f79beb2450d3 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:14:39 -0500 Subject: [PATCH 43/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 31ac3f3f..94dc11e1 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -327,7 +327,7 @@ implementation, we just need to implement `From`, `From`, `FromStr`, and `From` ... oh. Did I mention `JsObject`, like `JsValue`, is implementation defined as well? -This is where `temporal_rs`'s Partial API comes in. +Fortunately, this is where `temporal_rs`'s Partial API comes in. It turns out that, while property bags in JavaScript can have various fields set, there is still a general shape for the fields that can be From bfb9483b1f71889de184a52ded32b55ca4b9b072 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:15:12 -0500 Subject: [PATCH 44/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 94dc11e1..be8929b4 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -299,9 +299,10 @@ Folks, we're pleased to announce that `temporal_rs` won't be supporting that! ... or at least not in that shape. Again, the goal of `temporal_rs` is to implement the specification to -the highest degree possible and where it can't implement the -specification like in the case of a `from`, it provides methods -to support the implementation of Temporal in engines. +the highest possible degree of conformance, so when we couldn't provide +a direct translation of the specification's API, we made sure to +provide APIs that (hopefully) made the glue code between engines and +`temporal_rs` much shorter. To exemplify this, let's take a look at some valid uses of `from` in JavaScript to construct a `PlainDate`. From 88c3b9b7be065775b9c94c155d4dadc461ad1609 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:15:30 -0500 Subject: [PATCH 45/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index be8929b4..cb78ca0d 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -322,11 +322,13 @@ const pd_from_property_bag = Temporal.PlainDate.from({ }); ``` -It turns out that the above operations is all that needs to be -implemented by `temporal_rs` in order to support a Temporal -implementation, we just need to implement `From`, -`From`, `FromStr`, and `From` ... oh. Did I -mention `JsObject`, like `JsValue`, is implementation defined as well? +If we look closely to the common usage of the method, it seems like +all that needs to be implemented by `temporal_rs` is: +- `From`: Easy. +- `From`: Simple. +- `FromStr`: Tricky but can be done. +- `From`: ... +... oh. Did I mention `JsObject`, like `JsValue`, is engine defined as well? Fortunately, this is where `temporal_rs`'s Partial API comes in. From 35040270624193852c0e416239ac9c8996ab4fda Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:58:04 -0500 Subject: [PATCH 46/57] Some changes based off the remaining review comments --- blog/2025-06-15-temporal-impl-1.md | 208 +++++++++++++++++------------ 1 file changed, 125 insertions(+), 83 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index cb78ca0d..480ae575 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -12,13 +12,18 @@ description: authors: boa-dev --- -This will be a series of posts primarily about implementing a new -JavaScript feature in Rust, specifically the new date/time built-in: -Temporal. We'll be going over general lessons and interesting design choices we've -stumbled upon, as well as the crates supporting that implementation. +Writing a JavaScript engine in Rust can seem like pretty daunting task +to some. To provide some insight into how we implement JavaScript +features, we will be going over implementing a JavaScript feature in +Rust. -Why should you care? Well we are not only implementing it for -JavaScript, but Rust as well ... more on that in a bit. +More specifically, this will be the first in a series of posts primarily +about implementing the new date/time built-in: Temporal. We'll be going +over general lessons and interesting design choices we've stumbled upon, +as well as the crates supporting that implementation. + +Why should you care? Well we are not only implementing Temporal for +JavaScript, but for Rust as well ... more on that in a bit. First, an aside! @@ -50,8 +55,8 @@ documentation][mdn-temporal]. Being Boa a JavaScript engine / interpreter, developing a correct implementation of the ECMAScript specification is our raison d'être. This, in consequence, makes implementing Temporal one of our most -important goals, since it represents roughly 7-8% of the -current conformance test suite (~4000 of the ~50,000 tests). +important goals, since it represents roughly 7-8% of the current +conformance test suite (~4000 of the ~50,000 tests). When the PR of the first prototype of Temporal for Boa was submitted, a few things became evident: @@ -60,17 +65,18 @@ few things became evident: 2. There's room for optimization and improvement 3. This would be handy to have in Rust -So after the prototype was merged, we pulled it out of Boa's -internal builtins and externalized into its own crate, -[`temporal_rs`][temporal-rs-repo], which then first landed behind an -experimental flag in Boa v0.18. +So after the prototype was merged, we pulled it out of Boa's internal +builtins and externalized into its own crate, +[`temporal_rs`][temporal-rs-repo], which landed behind an experimental +flag in Boa v0.18. -After over a year and a half of development, Boa now sits at a conformance -of about 90% for Temporal (and growing), with the entire implementation -being backed by `temporal_rs`. +After over a year and a half of development, Boa now sits at a +conformance of about 90% for Temporal (and growing), with the entire +implementation being backed by `temporal_rs`. For its part, `temporal_rs` is shaping up to be a proper Rust date/time -library that can be used to implement Temporal in a JavaScript engine, and even support general date/time use cases. +library that can be used to implement Temporal in a JavaScript engine, +and even support general date/time use cases. Let's take a look at Temporal: it's JavaScript API, it's Rust API in `temporal_rs`, and how `temporal_rs` supports implementing the @@ -78,11 +84,12 @@ specification. ## Important core differences -Let's briefly talk about JavaScript values (`JsValue`). This is -functionally the core `any` value type of JavaScript. A `JsValue` could -be a number represented as a 64 bit floating point, a string, a boolean, -or an object. Not only is it an `any`, but `JsValue` is ultimately engine -defined with various implementations existing across engines. +First, we need to talk about JavaScript values (`JsValue`) for a bit. +This is functionally the core `any` value type of JavaScript. A +`JsValue` could be a number represented as a 64 bit floating point, a +string, a boolean, or an object. Not only is it an `any`, but `JsValue` +is ultimately engine defined with various implementations existing +across engines. While this is handy for a dynamically typed language like JavaScript, it is not ideal for implementing deep language specifications where an @@ -90,8 +97,8 @@ object or string may need to be cloned. Furthermore, it's just not great for an API in a typed language like Rust. To work around this, we routinely use `FromStr` and a `FiniteF64` custom -primitive to handle casting and constraining, respectively, which -glues dynamic types like `JsValue` with a typed API. +primitive to handle casting and constraining, respectively, which glues +dynamic types like `JsValue` with a typed API. For instance, in Boa, we heavily lean into using the below patterns: @@ -181,10 +188,10 @@ use temporal_rs::PlainDate; let plain_date = PlainDate::try_new_iso(2025, 6, 9)?; ``` -Interestingly enough, the `_iso` constructors are actually extensions of -Temporal specification to provide a similar API in Rust. This is because -the `_iso` constructors are assumed to exist due to resolving an -`undefined` calendar to the default ISO calendar. +Interestingly enough, the `_iso` constructors are mostly expressing a +part of the JavaScript API, just in native Rust. This is because in +JavaScript the `_iso` constructors are assumed to exist due to resolving +an `undefined` calendar to the default ISO calendar. ## Let's discuss `Now` @@ -203,9 +210,9 @@ the `_iso` constructors are assumed to exist due to resolving an important. It is the object from which the current instant can be measured and mapped into any of the Temporal components. -In JavaScript, this type has no `[[Construct]]` or `[[Call]]` internal -method, which is a fancy way to say that Now has no constructor and -cannot be called directly. +In JavaScript, this type has no [`[[Construct]]`][construct-link] or +[`[[Call]]`][call-link] internal method, which is a fancy way to say +that Now has no constructor and cannot be called directly. Instead, Now is used primarily as a namespace for its methods. @@ -233,8 +240,9 @@ on the implementation, right? Except the core purpose of `temporal_rs` is that it can be used in any engine implementation, and accessing a system clock and system time zone -is sometimes difficult for engines that support targets like embedded systems. -Thus, this functionality must be delegated to the engine or runtime ... somehow. +is sometimes difficult for engines that support targets like embedded +systems. Thus, this functionality must be delegated to the engine or +runtime ... somehow. How did we end up implementing `Now` if we have no access to the system clock or time zone? Well ... a builder pattern of course! @@ -273,6 +281,34 @@ pub struct Now { Once we've constructed `Now`, then we are off to the races! +In Boa, implementing `Now` is as easy the below implementation for +`Temporal.Now.plainDateISO()`: + +```rust +impl Now { + // The `Temporal.Now.plainDateISO` used when building `Temporal.Now`. + fn plain_date_iso(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult { + let time_zone = args + .get_or_undefined(0) + .map(|v| to_temporal_timezone_identifier(v, context)) + .transpose()?; + + let now = build_now(context)?; + + let pd = now.plain_date_iso_with_provider(time_zone, context.tz_provider())?; + create_temporal_date(pd, None, context).map(Into::into) + } +} + +// A helper for building Now +fn build_now(context: &mut Context) -> JsResult { + Ok(NowBuilder::default() + .with_system_zone(system_time_zone()?) + .with_system_nanoseconds(system_nanoseconds(context)?) + .build()) +} +``` + The nice part about this approach is that it also allows a `std` implementation that can be feature gated for general users that are not concerned with `no_std`. @@ -286,12 +322,12 @@ concerned with `no_std`. ## Partial API There's an interesting method on each of the Temporal built-ins that I'd -assume most people who have used Rust would be familiar with: `from`. But -this isn't Rust's friendly `From` trait. No, this `from` is a behemoth -method that takes a `JsValue` and automagically gives you back the -built-in that you'd like or throws. That's right! Give it a string, give -it a property bag, give it an instance of another Temporal built-in; -`from` will figure it out for you! +assume most people who have used Rust would be familiar with: `from`. +But this isn't Rust's friendly `From` trait. No, this `from` is a +behemoth method that takes a `JsValue` and automagically gives you back +the built-in that you'd like or throws. That's right! Give it a string, +give it a property bag, give it an instance of another Temporal +built-in; `from` will figure it out for you! Simple, right? @@ -300,12 +336,12 @@ that! ... or at least not in that shape. Again, the goal of `temporal_rs` is to implement the specification to the highest possible degree of conformance, so when we couldn't provide -a direct translation of the specification's API, we made sure to -provide APIs that (hopefully) made the glue code between engines and +a direct translation of the specification's API, we made sure to provide +APIs that (hopefully) made the glue code between engines and `temporal_rs` much shorter. -To exemplify this, let's take a look at some valid uses of `from` in JavaScript to -construct a `PlainDate`. +To exemplify this, let's take a look at some valid uses of `from` in +JavaScript to construct a `PlainDate`. ```js // Create a `PlainDateTime` @@ -322,13 +358,14 @@ const pd_from_property_bag = Temporal.PlainDate.from({ }); ``` -If we look closely to the common usage of the method, it seems like -all that needs to be implemented by `temporal_rs` is: +If we look closely to the common usage of the method, it seems like all +that needs to be implemented by `temporal_rs` is: + - `From`: Easy. - `From`: Simple. - `FromStr`: Tricky but can be done. -- `From`: ... -... oh. Did I mention `JsObject`, like `JsValue`, is engine defined as well? +- `From`: ... ... oh. Did I mention `JsObject`, like + `JsValue`, is engine defined as well? Fortunately, this is where `temporal_rs`'s Partial API comes in. @@ -336,9 +373,9 @@ It turns out that, while property bags in JavaScript can have various fields set, there is still a general shape for the fields that can be provided and validated in Temporal. -To support this in `temporal_rs`, a "partial" component -exists for each of the components that can then be provided to that -component's `from_partial` method. +To support this in `temporal_rs`, a "partial" component exists for each +of the components that can then be provided to that component's +`from_partial` method. With this, we have fully implemented support for the `from` method in `temporal_rs`: @@ -352,12 +389,12 @@ let pd_from_pdt = PlainDate::from(pdt); // We can use a `str`. let pd_from_string = PlainDate::from_str("2025-01-01")?; // We can use a `PartialDate`. -let pd_from_partial = PlainDate::from_partial(PartialDate { - year: Some(2025), - month: Some(1), - day: Some(1), - ..Default::default() -}); +let pd_from_partial = PlainDate::from_partial( + PartialDate::new() + .with_year(Some(2025)) + .with_month(Some(1)) + .with_day(Some(1)) +); ``` **NOTE:** there may be updates to `PartialDate` in the future (see @@ -368,8 +405,8 @@ for more information). So far we have not discussed time zones, and -- surprise! -- we aren't going to ... yet. It's not because they aren't super cool and -interesting and everyone _totally_ 100% loves them. No, time zones aren't -in this post because they are still being polished and deserve an +interesting and everyone _totally_ 100% loves them. No, time zones +aren't in this post because they are still being polished and deserve an entire post of their own. So stay tuned for our next post on implementing Temporal! The one where @@ -384,16 +421,14 @@ In conclusion, we're implementing Temporal in Rust to support engine implementors as well as to have the API available in native Rust in general. -Boa currently sits at a [90% conformance rate][boa-test262] for Temporal -completely backed by `temporal_rs` v0.0.8, and we're aiming to be 100% -conformant before the end of the year. - If you're interested in trying Temporal using Boa, you can use it in Boa's CLI or enable it in `boa_engine` with the `experimental` flag. Outside of Boa's implementation, `temporal_rs` has implemented or supports the implementation for a large portion of the Temporal's API in -native Rust. +native Rust. Furthermore, an overwhelming amount of the API can be +considered stable[^stability] and is currently available in Boa with +only a few outstanding issues that may be considered breaking changes. If you're interested in trying out `temporal_rs`, feel free to add it to your dependencies with the command: @@ -402,40 +437,47 @@ your dependencies with the command: cargo add temporal_rs ``` -or by adding the below in the `[dependencies]` section of your `Cargo.toml`: +or by adding the below in the `[dependencies]` section of your +`Cargo.toml`: ```toml temporal_rs = "0.0.9" ``` A FFI version of temporal is also available for C and C++ via -`temporal_capi`. +[`temporal_capi`][temporal-capi]. -## General note on API stability +[^stability]: A general note on API stability -While the majority of the APIs discussed above are expected to be mostly -stable. Temporal is still a stage 3 proposal that is not fully accepted -into the ECMAScript specification. Any normative change that may be made -upstream in the ECMAScript or ECMA402 specification will also be -reflected in `temporal_rs`. + While the majority of the APIs discussed above are expected to be + mostly stable. Temporal is still a stage 3 proposal that is not + fully accepted into the ECMAScript specification. Any normative + change that may be made upstream in the ECMAScript or ECMA402 + specification will also be reflected in `temporal_rs`. -There are also a few outstanding issues with changes that may reflect in -the API. + There are also a few outstanding issues with changes that may + reflect in the API. -1. Duration's inner repr and related constructors. -2. TemporalError's inner repr -3. Partial objects may need some adjustments to handle differences - between `from_partial` and `with` -4. Time zone provider's and the `TimeZoneProvider` trait are still - largely unstable. Although, the provider APIs that use them are - expected to be stable (spoilers!) -5. Era and month code are still be discussed in the intl-era-month-code - proposal, so some calendars and calendar methods may have varying - levels of support. + 1. Duration's inner repr and related constructors. + 2. `ZonedDateTime.prototype.getTimeZoneTransition` implementation + 3. TemporalError's inner repr + 4. Partial objects may need some adjustments to handle differences + between `from_partial` and `with` + 5. Time zone provider's and the `TimeZoneProvider` trait are still + largely unstable. Although, the provider APIs that use them are + expected to be stable (spoilers!) + 6. Era and month code are still be discussed in the + intl-era-month-code proposal, so some calendars and calendar + methods may have varying levels of support. -The above issues are considered blocking for a 0.1.0 release. + The above issues are considered blocking for a 0.1.0 release. [mdn-temporal]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal [temporal-rs-repo]: https://github.com/boa-dev/temporal +[construct-link]: + https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-behaviours.html#sec-ecmascript-function-objects-construct-argumentslist-newtarget +[call-link]: + https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-behaviours.html#sec-ecmascript-function-objects-call-thisargument-argumentslist [boa-test262]: https://test262.fyi/#|boa +[temporal-capi]: https://crates.io/crates/temporal_capi From fcf6cc4dd90fb3ee0b560fd09fc078675a89ceb5 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:12:57 -0500 Subject: [PATCH 47/57] Reword first paragraph --- blog/2025-06-15-temporal-impl-1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 480ae575..13d41cf9 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -12,10 +12,10 @@ description: authors: boa-dev --- -Writing a JavaScript engine in Rust can seem like pretty daunting task -to some. To provide some insight into how we implement JavaScript -features, we will be going over implementing a JavaScript feature in -Rust. +Developing a JavaScript engine in Rust can seem like pretty daunting +task to some. In order to demystify working on a feature and to go over +what we've been working on implementing in Boa recently, we thought we'd +write a post about implementing a JavaScript feature in Rust. More specifically, this will be the first in a series of posts primarily about implementing the new date/time built-in: Temporal. We'll be going From c69e8fcd26d9ef133f0eae7059411f9aec19ea11 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:22:26 -0500 Subject: [PATCH 48/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 13d41cf9..d7304a51 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -22,7 +22,7 @@ about implementing the new date/time built-in: Temporal. We'll be going over general lessons and interesting design choices we've stumbled upon, as well as the crates supporting that implementation. -Why should you care? Well we are not only implementing Temporal for +Why should you care? Well, we are not only implementing Temporal for JavaScript, but for Rust as well ... more on that in a bit. First, an aside! From 57721b20ef46130ee5b9ad2b0a1c30ad273da188 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:22:48 -0500 Subject: [PATCH 49/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index d7304a51..1cc68c15 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -66,7 +66,7 @@ few things became evident: 3. This would be handy to have in Rust So after the prototype was merged, we pulled it out of Boa's internal -builtins and externalized into its own crate, +builtins and externalized it into its own crate, [`temporal_rs`][temporal-rs-repo], which landed behind an experimental flag in Boa v0.18. From e59d4de5bc884ba2a7c3e357bed42d6f98a47b30 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:23:06 -0500 Subject: [PATCH 50/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 1cc68c15..622b1b6e 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -88,7 +88,7 @@ First, we need to talk about JavaScript values (`JsValue`) for a bit. This is functionally the core `any` value type of JavaScript. A `JsValue` could be a number represented as a 64 bit floating point, a string, a boolean, or an object. Not only is it an `any`, but `JsValue` -is ultimately engine defined with various implementations existing +is ultimately engine defined, with various implementations existing across engines. While this is handy for a dynamically typed language like JavaScript, it From 5d11e72b590f9aff4e81fb5f8538f934f25d818a Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:23:15 -0500 Subject: [PATCH 51/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 622b1b6e..72200ccf 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -214,7 +214,7 @@ In JavaScript, this type has no [`[[Construct]]`][construct-link] or [`[[Call]]`][call-link] internal method, which is a fancy way to say that Now has no constructor and cannot be called directly. -Instead, Now is used primarily as a namespace for its methods. +Instead, `Now` is used primarily as a namespace for its methods. And this was reflected in early adaptions of Now, which looked more or less like the below: From c61b9622f193d0780fabcc4c276e1b205eb3a258 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:23:43 -0500 Subject: [PATCH 52/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 72200ccf..eab7222e 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -450,7 +450,7 @@ A FFI version of temporal is also available for C and C++ via [^stability]: A general note on API stability While the majority of the APIs discussed above are expected to be - mostly stable. Temporal is still a stage 3 proposal that is not + mostly stable, Temporal is still a stage 3 proposal that is not fully accepted into the ECMAScript specification. Any normative change that may be made upstream in the ECMAScript or ECMA402 specification will also be reflected in `temporal_rs`. From c8531b3d409cba4a5e6d5c028cf2a46c73689df1 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:23:51 -0500 Subject: [PATCH 53/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index eab7222e..f842c91a 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -216,7 +216,7 @@ that Now has no constructor and cannot be called directly. Instead, `Now` is used primarily as a namespace for its methods. -And this was reflected in early adaptions of Now, which looked more or +And this was reflected in early adaptions of `Now`, which looked more or less like the below: ```rust From 6c3dba54fd367507282283e94053170c6829434d Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:24:13 -0500 Subject: [PATCH 54/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index f842c91a..1eb9092a 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -456,7 +456,7 @@ A FFI version of temporal is also available for C and C++ via specification will also be reflected in `temporal_rs`. There are also a few outstanding issues with changes that may - reflect in the API. + be reflected in the API. 1. Duration's inner repr and related constructors. 2. `ZonedDateTime.prototype.getTimeZoneTransition` implementation From 5191a1b992420084a9d8873081242b9a24d843be Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:24:34 -0500 Subject: [PATCH 55/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 1eb9092a..25aa4db5 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -232,7 +232,7 @@ impl Now { Interestingly enough, the above implementation is incorrect, or at the very least not ideal. -Hidden in the specification steps for Now are some very tricky steps +Hidden in the specification steps for `Now` are some very tricky steps invoking the abstract operations: `SystemTimeZoneIdentifier` and `SystemUtcEpochNanoseconds`. That's great, let's just use the usual suspects `SystemTime` and `iana-time-zone`, merge it, and call it a day From 195d5291a013d0af534c9dbf86f99c8433202442 Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:28:43 -0500 Subject: [PATCH 56/57] Reword Boa Now codeblock intro --- blog/2025-06-15-temporal-impl-1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index 25aa4db5..e26dae46 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -281,8 +281,8 @@ pub struct Now { Once we've constructed `Now`, then we are off to the races! -In Boa, implementing `Now` is as easy the below implementation for -`Temporal.Now.plainDateISO()`: +To show the `NowBuilder` in action, in Boa, the implementation for +`Temporal.Now.plainDateISO()` with the builder API is the below: ```rust impl Now { @@ -455,8 +455,8 @@ A FFI version of temporal is also available for C and C++ via change that may be made upstream in the ECMAScript or ECMA402 specification will also be reflected in `temporal_rs`. - There are also a few outstanding issues with changes that may - be reflected in the API. + There are also a few outstanding issues with changes that may be + reflected in the API. 1. Duration's inner repr and related constructors. 2. `ZonedDateTime.prototype.getTimeZoneTransition` implementation From c5b38a2e326fdc2317f8d107cb469c7403239b6a Mon Sep 17 00:00:00 2001 From: Kevin Ness <46825870+nekevss@users.noreply.github.com> Date: Sun, 15 Jun 2025 16:21:29 -0500 Subject: [PATCH 57/57] Update blog/2025-06-15-temporal-impl-1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Julián Espina --- blog/2025-06-15-temporal-impl-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2025-06-15-temporal-impl-1.md b/blog/2025-06-15-temporal-impl-1.md index e26dae46..d6ba33a7 100644 --- a/blog/2025-06-15-temporal-impl-1.md +++ b/blog/2025-06-15-temporal-impl-1.md @@ -282,7 +282,7 @@ pub struct Now { Once we've constructed `Now`, then we are off to the races! To show the `NowBuilder` in action, in Boa, the implementation for -`Temporal.Now.plainDateISO()` with the builder API is the below: +`Temporal.Now.plainDateISO()` with the builder API is shown below: ```rust impl Now {