diff --git a/src/builtins/compiled/mod.rs b/src/builtins/compiled/mod.rs index 68c34e2bc..113999f88 100644 --- a/src/builtins/compiled/mod.rs +++ b/src/builtins/compiled/mod.rs @@ -3,6 +3,7 @@ mod duration; mod instant; mod now; +mod plain_date_time; mod zoneddatetime; mod options { diff --git a/src/builtins/compiled/plain_date_time.rs b/src/builtins/compiled/plain_date_time.rs new file mode 100644 index 000000000..6956619ec --- /dev/null +++ b/src/builtins/compiled/plain_date_time.rs @@ -0,0 +1,23 @@ +use crate::{ + builtins::core::{PlainDateTime, ZonedDateTime}, + builtins::TZ_PROVIDER, + options::Disambiguation, + TemporalError, TemporalResult, TimeZone, +}; + +impl PlainDateTime { + /// Returns a `ZonedDateTime` with the provided `PlainDateTime`, TimeZone` and + /// `Disambiguation` + /// Enable with the `compiled_data` feature flag. + pub fn to_zoned_date_time( + &self, + time_zone: &TimeZone, + disambiguation: Disambiguation, + ) -> TemporalResult { + let provider = TZ_PROVIDER + .lock() + .map_err(|_| TemporalError::general("Unable to acquire lock"))?; + + self.to_zoned_date_time_with_provider(time_zone, disambiguation, &*provider) + } +} diff --git a/src/builtins/core/datetime.rs b/src/builtins/core/datetime.rs index 5391b21b3..e8cfff55f 100644 --- a/src/builtins/core/datetime.rs +++ b/src/builtins/core/datetime.rs @@ -2,18 +2,19 @@ use super::{ duration::normalized::{NormalizedDurationRecord, NormalizedTimeDuration}, - Duration, PartialDate, PartialTime, PlainDate, PlainTime, + Duration, PartialDate, PartialTime, PlainDate, PlainTime, ZonedDateTime, }; use crate::{ builtins::core::{calendar::Calendar, Instant}, iso::{IsoDate, IsoDateTime, IsoTime}, options::{ - ArithmeticOverflow, DifferenceOperation, DifferenceSettings, DisplayCalendar, - ResolvedRoundingOptions, RoundingOptions, TemporalUnit, ToStringRoundingOptions, UnitGroup, + ArithmeticOverflow, DifferenceOperation, DifferenceSettings, Disambiguation, + DisplayCalendar, ResolvedRoundingOptions, RoundingOptions, TemporalUnit, + ToStringRoundingOptions, UnitGroup, }, parsers::{parse_date_time, IxdtfStringBuilder}, primitive::FiniteF64, - provider::NeverProvider, + provider::{NeverProvider, TimeZoneProvider}, temporal_assert, MonthCode, TemporalError, TemporalResult, TemporalUnwrap, TimeZone, }; use alloc::string::String; @@ -682,8 +683,33 @@ impl PlainDateTime { Ok(Self::new_unchecked(result, self.calendar.clone())) } + pub fn to_zoned_date_time_with_provider( + &self, + time_zone: &TimeZone, + disambiguation: Disambiguation, + provider: &impl TimeZoneProvider, + ) -> TemporalResult { + // 6. Let epochNs be ? GetEpochNanosecondsFor(timeZone, dateTime.[[ISODateTime]], disambiguation). + let epoch_ns = time_zone.get_epoch_nanoseconds_for(self.iso, disambiguation, provider)?; + // 7. Return ! CreateTemporalZonedDateTime(epochNs, timeZone, dateTime.[[Calendar]]). + Ok(ZonedDateTime::new_unchecked( + Instant::from(epoch_ns), + self.calendar.clone(), + time_zone.clone(), + )) + } + + pub fn to_plain_date(&self) -> TemporalResult { + // 3. Return ! CreateTemporalDate(dateTime.[[ISODateTime]].[[ISODate]], dateTime.[[Calendar]]). + Ok(PlainDate::new_unchecked( + self.iso.date, + self.calendar.clone(), + )) + } + pub fn to_plain_time(&self) -> TemporalResult { - Err(TemporalError::general("Not yet implemented.")) + // 3. Return ! CreateTemporalTime(dateTime.[[ISODateTime]].[[Time]]). + Ok(PlainTime::new_unchecked(self.iso.time)) } pub fn to_ixdtf_string( diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp index 7010fb20e..75e1e7735 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp @@ -15,6 +15,8 @@ namespace capi { struct Calendar; } class Calendar; namespace capi { struct Duration; } class Duration; +namespace capi { struct PlainDate; } +class PlainDate; namespace capi { struct PlainDateTime; } class PlainDateTime; namespace capi { struct PlainTime; } @@ -111,6 +113,8 @@ class PlainDateTime { inline diplomat::result, temporal_rs::TemporalError> round(temporal_rs::RoundingOptions options) const; + inline diplomat::result, temporal_rs::TemporalError> to_plain_date() const; + inline diplomat::result, temporal_rs::TemporalError> to_plain_time() const; inline diplomat::result to_ixdtf_string(temporal_rs::ToStringRoundingOptions options, temporal_rs::DisplayCalendar display_calendar) const; diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp index da309fcf1..b1641b2d1 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp @@ -17,6 +17,7 @@ #include "DisplayCalendar.hpp" #include "Duration.hpp" #include "PartialDateTime.hpp" +#include "PlainDate.hpp" #include "PlainTime.hpp" #include "RoundingOptions.hpp" #include "TemporalError.hpp" @@ -114,6 +115,9 @@ namespace capi { typedef struct temporal_rs_PlainDateTime_round_result {union {temporal_rs::capi::PlainDateTime* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_round_result; temporal_rs_PlainDateTime_round_result temporal_rs_PlainDateTime_round(const temporal_rs::capi::PlainDateTime* self, temporal_rs::capi::RoundingOptions options); + typedef struct temporal_rs_PlainDateTime_to_plain_date_result {union {temporal_rs::capi::PlainDate* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_to_plain_date_result; + temporal_rs_PlainDateTime_to_plain_date_result temporal_rs_PlainDateTime_to_plain_date(const temporal_rs::capi::PlainDateTime* self); + typedef struct temporal_rs_PlainDateTime_to_plain_time_result {union {temporal_rs::capi::PlainTime* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_to_plain_time_result; temporal_rs_PlainDateTime_to_plain_time_result temporal_rs_PlainDateTime_to_plain_time(const temporal_rs::capi::PlainDateTime* self); @@ -345,6 +349,11 @@ inline diplomat::result, temporal_rs return result.is_ok ? diplomat::result, temporal_rs::TemporalError>(diplomat::Ok>(std::unique_ptr(temporal_rs::PlainDateTime::FromFFI(result.ok)))) : diplomat::result, temporal_rs::TemporalError>(diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); } +inline diplomat::result, temporal_rs::TemporalError> temporal_rs::PlainDateTime::to_plain_date() const { + auto result = temporal_rs::capi::temporal_rs_PlainDateTime_to_plain_date(this->AsFFI()); + return result.is_ok ? diplomat::result, temporal_rs::TemporalError>(diplomat::Ok>(std::unique_ptr(temporal_rs::PlainDate::FromFFI(result.ok)))) : diplomat::result, temporal_rs::TemporalError>(diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); +} + inline diplomat::result, temporal_rs::TemporalError> temporal_rs::PlainDateTime::to_plain_time() const { auto result = temporal_rs::capi::temporal_rs_PlainDateTime_to_plain_time(this->AsFFI()); return result.is_ok ? diplomat::result, temporal_rs::TemporalError>(diplomat::Ok>(std::unique_ptr(temporal_rs::PlainTime::FromFFI(result.ok)))) : diplomat::result, temporal_rs::TemporalError>(diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); diff --git a/temporal_capi/src/plain_date_time.rs b/temporal_capi/src/plain_date_time.rs index e2acf9c05..9f048e33b 100644 --- a/temporal_capi/src/plain_date_time.rs +++ b/temporal_capi/src/plain_date_time.rs @@ -12,7 +12,7 @@ pub mod ffi { ArithmeticOverflow, DifferenceSettings, DisplayCalendar, RoundingOptions, ToStringRoundingOptions, }; - use crate::plain_date::ffi::PartialDate; + use crate::plain_date::ffi::{PartialDate, PlainDate}; use crate::plain_time::ffi::{PartialTime, PlainTime}; use diplomat_runtime::DiplomatWrite; use std::fmt::Write; @@ -249,6 +249,13 @@ pub mod ffi { .map_err(Into::into) } + pub fn to_plain_date(&self) -> Result, TemporalError> { + self.0 + .to_plain_date() + .map(|x| Box::new(PlainDate(x))) + .map_err(Into::into) + } + pub fn to_plain_time(&self) -> Result, TemporalError> { self.0 .to_plain_time()