Skip to content
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

Implement toZonedDateTime in PlainDate #192

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
16 changes: 16 additions & 0 deletions src/builtins/compiled/date.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::{builtins::TZ_PROVIDER, TemporalError, TemporalResult, PlainDate, PlainTime};

impl PlainDate {

/// Converts a `Date` to a `ZonedDateTime` in the UTC time zone.
pub fn to_zoned_date_time(
&self,
time_zone: TimeZone
plain_time: Option<PlainTime>
) -> TemporalResult<crate::ZonedDateTime> {
let provider = TZ_PROVIDER
.lock()
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
self.to_zoned_date_time_with_provider(time_zone, plain_time, &*provider)
}
}
50 changes: 46 additions & 4 deletions src/builtins/core/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
use crate::{
builtins::core::{
calendar::Calendar, duration::DateDuration, Duration, PlainDateTime, PlainTime,
ZonedDateTime,
},
iso::{IsoDate, IsoDateTime, IsoTime},
options::{
ArithmeticOverflow, DifferenceOperation, DifferenceSettings, DisplayCalendar,
ResolvedRoundingOptions, TemporalUnit, UnitGroup,
ArithmeticOverflow, DifferenceOperation, DifferenceSettings, Disambiguation,
DisplayCalendar, ResolvedRoundingOptions, TemporalUnit, UnitGroup,
},
parsers::{parse_date_time, IxdtfStringBuilder},
primitive::FiniteF64,
provider::NeverProvider,
provider::{NeverProvider, TimeZoneProvider},
MonthCode, TemporalError, TemporalResult, TemporalUnwrap, TimeZone,
};
use alloc::{format, string::String};
Expand Down Expand Up @@ -651,8 +652,49 @@ impl PlainDate {
.with_calendar(self.calendar.identifier(), display_calendar)
.build()
}
}

#[inline]
pub fn to_zoned_date_time_with_provider(
&self,
tz: TimeZone,
plain_time: Option<PlainTime>,
provider: &impl TimeZoneProvider,
) -> TemporalResult<ZonedDateTime> {
// 1. Let temporalDate be the this value.
// 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
// 3. If item is an Object, then
// a. Let timeZoneLike be ? Get(item, "timeZone").
// b. If timeZoneLike is undefined, then
// i. Let timeZone be ? ToTemporalTimeZoneIdentifier(item).
// ii. Let temporalTime be undefined.
// c. Else,
// i. Let timeZone be ? ToTemporalTimeZoneIdentifier(timeZoneLike).
// ii. Let temporalTime be ? Get(item, "plainTime").
// 4. Else,
// a. Let timeZone be ? ToTemporalTimeZoneIdentifier(item).
// b. Let temporalTime be undefined.

// 5. If temporalTime is undefined, then
// a. Let epochNs be ? GetStartOfDay(timeZone, temporalDate.[[ISODate]]).
// 6. Else,
// a. Set temporalTime to ? ToTemporalTime(temporalTime).
// b. Let isoDateTime be CombineISODateAndTimeRecord(temporalDate.[[ISODate]], temporalTime.[[Time]]).
// c. If ISODateTimeWithinLimits(isoDateTime) is false, throw a RangeError exception.
// d. Let epochNs be ? GetEpochNanosecondsFor(timeZone, isoDateTime, compatible).
let epoch_ns = if let Some(time) = plain_time {
let result_iso = IsoDateTime::new(self.iso, time.iso);
tz.get_epoch_nanoseconds_for(
result_iso.unwrap_or_default(),
Disambiguation::Compatible,
provider,
)?
} else {
tz.get_start_of_day(&self.iso, provider)?
};
// 7. Return ! CreateTemporalZonedDateTime(epochNs, timeZone, temporalDate.[[Calendar]]).
ZonedDateTime::try_new(epoch_ns.0, self.calendar.clone(), tz)
}
}
// ==== Trait impls ====

impl From<PlainDateTime> for PlainDate {
Expand Down