Skip to content

Add to-x methods and with-x methods to ZonedDateTime #129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 14, 2024
Merged

Conversation

nekevss
Copy link
Member

@nekevss nekevss commented Dec 9, 2024

This PR adds support to ZonedDateTime for the following methods.

  • ZonedDateTime.prototype.toInstant
  • ZonedDateTime.prototype.toPlainDate
  • ZonedDateTime.prototype.toPlainTime
  • ZonedDateTime.prototype.toPlainDateTime
  • ZonedDateTime.prototype.withTimezone
  • ZonedDateTime.prototype.withCalendar
  • ZonedDateTime.prototype.withTimezone
  • ZonedDateTime.prototype.StartOfDay

@@ -400,6 +420,15 @@ impl ZonedDateTime {

#[cfg(feature = "experimental")]
impl ZonedDateTime {
/// Creates a new `ZonedDateTime` from the current `ZonedDateTime`
/// combined with the provided `TimeZone`.
pub fn with_plain_time(&self, time: Option<PlainTime>) -> TemporalResult<Self> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, does it make sense to take Option here? I would assume if someone's calling with_plain_time, they would have a specific time to set the datetime to

Copy link
Member Author

@nekevss nekevss Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's a good note.

The proposal is fairly clear that the argument for with_plain_time is optional and can be undefined. So from a proposal perspective, this is technically correct. But to what degree does it makes sense as an API ...

Hmmmm, sort of thinking out loud. with_plain_time is on some level with_epoch_nanoseconds where the IsoDate of the ZonedDateTime is a base.

We could have a with_epoch_nanosecond and then reconstruct the functionality in Boa using that method.

From Boa's side, it would probably end up looking like:

fn with_plain_time(this: &JsValue, args: [JsValue], context: &mut Context) -> JsResult<JsValue> {
    let zdt = this.
        .as_object()
        .and_then(JsObject::downcast_ref::<Self>)
        .ok_or_else( // -- throw error -- //)?;

    let time = args.first().map(|v| to_temporal_time(v)).transpose()?;
    
    let epoch_nanos = if let Some(pt) = time {
        // `as_epoch_nanoseconds` would need to be added to `PlainDateTime`.
        zdt.inner.to_plain_datetime().with_time(pt)?.as_epoch_nanoseconds()
    } else {
       zdt.inner.start_of_day(context.tz_provider())?
    };
    
    // Below could be:
    // ZonedDateTimeInner::with_instant(epoch_nanos.into())
    ZonedDateTimeInner::with_epoch_nanoseconds(epoch_nanos)
}

I don't necessarily dislike it ... but it also brings up the question to a point of if it's worthwhile having a with_epoch_nanoseconds and with_instant.

Thoughts?

Copy link
Member Author

@nekevss nekevss Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or alternatively, we could just support the path where PlainTime is available.

fn with_plain_time(this: &JsValue, args: [JsValue], context: &mut Context) -> JsResult<JsValue> {
    let zdt = this.
        .as_object()
        .and_then(JsObject::downcast_ref::<Self>)
        .ok_or_else( // -- throw error -- //)?;

    let time = args.first().map(|v| to_temporal_time(v)).transpose()?;
    
    if let Some(pt) = time {
        zdt.inner.with_time(pt, context.tz_provider())
    } else {
       zdt.inner.with_instant(zdt.start_of_day(context.tz_provider())?.into())
    }
}

EDIT: I did go ahead with this second one. I sort of convinced myself 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the second one looks a bit cleaner

/// combined with the provided `TimeZone`.
pub fn with_plain_time_and_provider(
&self,
time: Option<PlainTime>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same suggestion as my previous comment

@nekevss nekevss added the C-enhancement New feature or request label Dec 9, 2024
Copy link
Member

@jedel1043 jedel1043 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

@nekevss nekevss merged commit 92fd59c into main Dec 14, 2024
5 checks passed
@nekevss nekevss deleted the zdt-to-x-methods branch December 16, 2024 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants