From 12bb6cbba52caedf18d1d84efb838ef3bd4c62eb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Mar 2026 12:33:23 -0700 Subject: [PATCH] Add epoch_ns_for_utc --- src/builtins/core/plain_date.rs | 13 +++++++++++++ src/builtins/core/plain_date_time.rs | 10 ++++++++++ src/builtins/core/plain_month_day.rs | 12 ++++++++++++ src/builtins/core/plain_time.rs | 15 +++++++++++++++ src/builtins/core/plain_year_month.rs | 16 +++++++++++++--- src/iso.rs | 2 ++ temporal_capi/bindings/c/PlainDate.h | 3 +++ temporal_capi/bindings/c/PlainDateTime.h | 3 +++ temporal_capi/bindings/c/PlainMonthDay.h | 3 +++ temporal_capi/bindings/c/PlainTime.h | 3 +++ temporal_capi/bindings/c/PlainYearMonth.h | 3 +++ .../bindings/cpp/temporal_rs/PlainDate.d.hpp | 2 ++ .../bindings/cpp/temporal_rs/PlainDate.hpp | 8 ++++++++ .../bindings/cpp/temporal_rs/PlainDateTime.d.hpp | 2 ++ .../bindings/cpp/temporal_rs/PlainDateTime.hpp | 8 ++++++++ .../bindings/cpp/temporal_rs/PlainMonthDay.d.hpp | 2 ++ .../bindings/cpp/temporal_rs/PlainMonthDay.hpp | 8 ++++++++ .../bindings/cpp/temporal_rs/PlainTime.d.hpp | 2 ++ .../bindings/cpp/temporal_rs/PlainTime.hpp | 8 ++++++++ .../cpp/temporal_rs/PlainYearMonth.d.hpp | 2 ++ .../bindings/cpp/temporal_rs/PlainYearMonth.hpp | 8 ++++++++ temporal_capi/src/plain_date.rs | 13 +++++++++++++ temporal_capi/src/plain_date_time.rs | 12 ++++++++++++ temporal_capi/src/plain_month_day.rs | 12 ++++++++++++ temporal_capi/src/plain_time.rs | 12 ++++++++++++ temporal_capi/src/plain_year_month.rs | 12 ++++++++++++ 26 files changed, 191 insertions(+), 3 deletions(-) diff --git a/src/builtins/core/plain_date.rs b/src/builtins/core/plain_date.rs index 9647b1a0d..7f9153f21 100644 --- a/src/builtins/core/plain_date.rs +++ b/src/builtins/core/plain_date.rs @@ -17,6 +17,7 @@ use crate::{ }, parsers::IxdtfStringBuilder, provider::{NeverProvider, TimeZoneProvider}, + unix_time::EpochNanoseconds, MonthCode, TemporalError, TemporalResult, TimeZone, }; use alloc::string::String; @@ -685,6 +686,18 @@ impl PlainDate { epoch_ns.offset, ) } + + /// Gets the EpochNanoseconds represented by this PlainDate + /// (using noon time, and UTC timezone) + /// + // Useful for implementing HandleDateTimeTemporalYearMonth + pub fn epoch_ns_for_utc(&self) -> EpochNanoseconds { + // 2. Let isoDateTime be CombineISODateAndTimeRecord(temporalYearMonth.[[ISODate]], NoonTimeRecord()). + let iso = IsoDateTime::new(self.iso, IsoTime::noon()); + debug_assert!(iso.is_ok()); + // 3. Let epochNs be ? GetUTCEpochNanoseconds(isoDateTime). + iso.unwrap_or_default().as_nanoseconds() + } } // ==== Trait impls ==== diff --git a/src/builtins/core/plain_date_time.rs b/src/builtins/core/plain_date_time.rs index 502ebd1cf..102d54c36 100644 --- a/src/builtins/core/plain_date_time.rs +++ b/src/builtins/core/plain_date_time.rs @@ -19,6 +19,7 @@ use crate::{ parsers::IxdtfStringBuilder, primitive::FiniteF64, provider::{NeverProvider, TimeZoneProvider}, + unix_time::EpochNanoseconds, MonthCode, TemporalError, TemporalResult, TimeZone, }; use alloc::string::String; @@ -907,6 +908,15 @@ impl PlainDateTime { )) } + /// Gets the EpochNanoseconds represented by this PlainDateTime + /// (using and UTC timezone) + /// + // Useful for implementing HandleDateTimeTemporalDateTime + pub fn epoch_ns_for_utc(&self) -> EpochNanoseconds { + // 3. Let epochNs be ? GetUTCEpochNanoseconds(isoDateTime). + self.iso.as_nanoseconds() + } + /// Create a [`PlainDate`] from the current `PlainDateTime`. #[inline] pub fn to_plain_date(&self) -> PlainDate { diff --git a/src/builtins/core/plain_month_day.rs b/src/builtins/core/plain_month_day.rs index 48728939d..4084e3761 100644 --- a/src/builtins/core/plain_month_day.rs +++ b/src/builtins/core/plain_month_day.rs @@ -364,6 +364,18 @@ impl PlainMonthDay { .ns) } + /// Gets the EpochNanoseconds represented by this MonthDay + /// (using the reference year, noon time, and UTC timezone) + /// + // Useful for implementing HandleDateTimeTemporalYearMonth + pub fn epoch_ns_for_utc(&self) -> EpochNanoseconds { + // 2. Let isoDateTime be CombineISODateAndTimeRecord(temporalMonthDay.[[ISODate]], NoonTimeRecord()). + let iso = IsoDateTime::new(self.iso, IsoTime::noon()); + debug_assert!(iso.is_ok()); + // 3. Let epochNs be ? GetUTCEpochNanoseconds(isoDateTime). + iso.unwrap_or_default().as_nanoseconds() + } + /// Creates a RFC9557 IXDTF string from the current `PlainMonthDay`. pub fn to_ixdtf_string(&self, display_calendar: DisplayCalendar) -> String { self.to_ixdtf_writeable(display_calendar) diff --git a/src/builtins/core/plain_time.rs b/src/builtins/core/plain_time.rs index 68c27c8d6..34f1030d9 100644 --- a/src/builtins/core/plain_time.rs +++ b/src/builtins/core/plain_time.rs @@ -7,11 +7,13 @@ use crate::{ }, error::ErrorMessage, iso::IsoTime, + iso::{IsoDate, IsoDateTime}, options::{ DifferenceOperation, DifferenceSettings, Overflow, ResolvedRoundingOptions, RoundingOptions, ToStringRoundingOptions, Unit, UnitGroup, }, parsers::{parse_time, IxdtfStringBuilder}, + unix_time::EpochNanoseconds, TemporalError, TemporalResult, }; use alloc::string::String; @@ -541,6 +543,19 @@ impl PlainTime { let builder = IxdtfStringBuilder::default().with_time(result, resolved.precision); Ok(builder) } + + /// Gets the EpochNanoseconds represented by this PlainTime + /// (using the Unix epoch, and UTC timezone) + /// + // Useful for implementing HandleDateTimeTemporalTime + pub fn epoch_ns_for_utc(&self) -> EpochNanoseconds { + // 1. Let isoDate be CreateISODateRecord(1970, 1, 1). + // 2. Let isoDateTime be CombineISODateAndTimeRecord(isoDate, temporalTime.[[Time]]). + let iso = IsoDateTime::new(IsoDate::UNIX_EPOCH, self.iso); + debug_assert!(iso.is_ok()); + // 3. Let epochNs be ? GetUTCEpochNanoseconds(isoDateTime). + iso.unwrap_or_default().as_nanoseconds() + } } impl From for PlainTime { diff --git a/src/builtins/core/plain_year_month.rs b/src/builtins/core/plain_year_month.rs index d1ae5b344..89c0f1c6c 100644 --- a/src/builtins/core/plain_year_month.rs +++ b/src/builtins/core/plain_year_month.rs @@ -598,9 +598,7 @@ impl PlainYearMonth { } /// Gets the epochMilliseconds represented by this YearMonth in the given timezone - /// (using the reference year, and noon time) - /// - // Useful for implementing HandleDateTimeTemporalYearMonth + /// (using the reference day, and noon time) pub fn epoch_ns_for_with_provider( &self, time_zone: TimeZone, @@ -614,6 +612,18 @@ impl PlainYearMonth { .ns) } + /// Gets the EpochNanoseconds represented by this YearMonth + /// (using the reference day, noon time, and UTC timezone) + /// + // Useful for implementing HandleDateTimeTemporalYearMonth + pub fn epoch_ns_for_utc(&self) -> EpochNanoseconds { + // 2. Let isoDateTime be CombineISODateAndTimeRecord(temporalYearMonth.[[ISODate]], NoonTimeRecord()). + let iso = IsoDateTime::new(self.iso, IsoTime::noon()); + debug_assert!(iso.is_ok()); + // 3. Let epochNs be ? GetUTCEpochNanoseconds(isoDateTime). + iso.unwrap_or_default().as_nanoseconds() + } + /// Returns a RFC9557 IXDTF string for the current `PlainYearMonth` #[inline] pub fn to_ixdtf_string(&self, display_calendar: DisplayCalendar) -> String { diff --git a/src/iso.rs b/src/iso.rs index 2abf72098..f8b383e39 100644 --- a/src/iso.rs +++ b/src/iso.rs @@ -264,6 +264,8 @@ pub struct IsoDate { } impl IsoDate { + pub(crate) const UNIX_EPOCH: Self = Self::new_unchecked(1970, 1, 1); + /// Creates a new `IsoDate` without determining the validity. pub(crate) const fn new_unchecked(year: i32, month: u8, day: u8) -> Self { Self { year, month, day } diff --git a/temporal_capi/bindings/c/PlainDate.h b/temporal_capi/bindings/c/PlainDate.h index d196dc30a..a7a3ccc89 100644 --- a/temporal_capi/bindings/c/PlainDate.h +++ b/temporal_capi/bindings/c/PlainDate.h @@ -138,6 +138,9 @@ temporal_rs_PlainDate_to_zoned_date_time_result temporal_rs_PlainDate_to_zoned_d typedef struct temporal_rs_PlainDate_to_zoned_date_time_with_provider_result {union {ZonedDateTime* ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainDate_to_zoned_date_time_with_provider_result; temporal_rs_PlainDate_to_zoned_date_time_with_provider_result temporal_rs_PlainDate_to_zoned_date_time_with_provider(const PlainDate* self, TimeZone time_zone, const PlainTime* time, const Provider* p); +typedef struct temporal_rs_PlainDate_epoch_ms_for_utc_result {union {int64_t ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainDate_epoch_ms_for_utc_result; +temporal_rs_PlainDate_epoch_ms_for_utc_result temporal_rs_PlainDate_epoch_ms_for_utc(const PlainDate* self); + void temporal_rs_PlainDate_to_ixdtf_string(const PlainDate* self, DisplayCalendar display_calendar, DiplomatWrite* write); PlainDate* temporal_rs_PlainDate_clone(const PlainDate* self); diff --git a/temporal_capi/bindings/c/PlainDateTime.h b/temporal_capi/bindings/c/PlainDateTime.h index 32b5e35b8..87e63d0a4 100644 --- a/temporal_capi/bindings/c/PlainDateTime.h +++ b/temporal_capi/bindings/c/PlainDateTime.h @@ -147,6 +147,9 @@ temporal_rs_PlainDateTime_to_zoned_date_time_result temporal_rs_PlainDateTime_to typedef struct temporal_rs_PlainDateTime_to_zoned_date_time_with_provider_result {union {ZonedDateTime* ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_to_zoned_date_time_with_provider_result; temporal_rs_PlainDateTime_to_zoned_date_time_with_provider_result temporal_rs_PlainDateTime_to_zoned_date_time_with_provider(const PlainDateTime* self, TimeZone time_zone, Disambiguation disambiguation, const Provider* p); +typedef struct temporal_rs_PlainDateTime_epoch_ms_for_utc_result {union {int64_t ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_epoch_ms_for_utc_result; +temporal_rs_PlainDateTime_epoch_ms_for_utc_result temporal_rs_PlainDateTime_epoch_ms_for_utc(const PlainDateTime* self); + typedef struct temporal_rs_PlainDateTime_to_ixdtf_string_result {union { TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_to_ixdtf_string_result; temporal_rs_PlainDateTime_to_ixdtf_string_result temporal_rs_PlainDateTime_to_ixdtf_string(const PlainDateTime* self, ToStringRoundingOptions options, DisplayCalendar display_calendar, DiplomatWrite* write); diff --git a/temporal_capi/bindings/c/PlainMonthDay.h b/temporal_capi/bindings/c/PlainMonthDay.h index 96f001b14..6a5343afb 100644 --- a/temporal_capi/bindings/c/PlainMonthDay.h +++ b/temporal_capi/bindings/c/PlainMonthDay.h @@ -58,6 +58,9 @@ int32_t temporal_rs_PlainMonthDay_reference_year(const PlainMonthDay* self); typedef struct temporal_rs_PlainMonthDay_to_plain_date_result {union {PlainDate* ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainMonthDay_to_plain_date_result; temporal_rs_PlainMonthDay_to_plain_date_result temporal_rs_PlainMonthDay_to_plain_date(const PlainMonthDay* self, PartialDate_option year); +typedef struct temporal_rs_PlainMonthDay_epoch_ms_for_utc_result {union {int64_t ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainMonthDay_epoch_ms_for_utc_result; +temporal_rs_PlainMonthDay_epoch_ms_for_utc_result temporal_rs_PlainMonthDay_epoch_ms_for_utc(const PlainMonthDay* self); + typedef struct temporal_rs_PlainMonthDay_epoch_ms_for_result {union {int64_t ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainMonthDay_epoch_ms_for_result; temporal_rs_PlainMonthDay_epoch_ms_for_result temporal_rs_PlainMonthDay_epoch_ms_for(const PlainMonthDay* self, TimeZone time_zone); diff --git a/temporal_capi/bindings/c/PlainTime.h b/temporal_capi/bindings/c/PlainTime.h index 0d897da90..059d2e37c 100644 --- a/temporal_capi/bindings/c/PlainTime.h +++ b/temporal_capi/bindings/c/PlainTime.h @@ -46,6 +46,9 @@ temporal_rs_PlainTime_from_epoch_nanoseconds_result temporal_rs_PlainTime_from_e typedef struct temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider_result {union {PlainTime* ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider_result; temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider_result temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider(I128Nanoseconds ns, TimeZone tz, const Provider* p); +typedef struct temporal_rs_PlainTime_epoch_ms_for_utc_result {union {int64_t ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainTime_epoch_ms_for_utc_result; +temporal_rs_PlainTime_epoch_ms_for_utc_result temporal_rs_PlainTime_epoch_ms_for_utc(const PlainTime* self); + typedef struct temporal_rs_PlainTime_with_result {union {PlainTime* ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainTime_with_result; temporal_rs_PlainTime_with_result temporal_rs_PlainTime_with(const PlainTime* self, PartialTime partial, ArithmeticOverflow_option overflow); diff --git a/temporal_capi/bindings/c/PlainYearMonth.h b/temporal_capi/bindings/c/PlainYearMonth.h index 2f633b803..899529549 100644 --- a/temporal_capi/bindings/c/PlainYearMonth.h +++ b/temporal_capi/bindings/c/PlainYearMonth.h @@ -87,6 +87,9 @@ int8_t temporal_rs_PlainYearMonth_compare(const PlainYearMonth* one, const Plain typedef struct temporal_rs_PlainYearMonth_to_plain_date_result {union {PlainDate* ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainYearMonth_to_plain_date_result; temporal_rs_PlainYearMonth_to_plain_date_result temporal_rs_PlainYearMonth_to_plain_date(const PlainYearMonth* self, PartialDate_option day); +typedef struct temporal_rs_PlainYearMonth_epoch_ms_for_utc_result {union {int64_t ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainYearMonth_epoch_ms_for_utc_result; +temporal_rs_PlainYearMonth_epoch_ms_for_utc_result temporal_rs_PlainYearMonth_epoch_ms_for_utc(const PlainYearMonth* self); + typedef struct temporal_rs_PlainYearMonth_epoch_ms_for_result {union {int64_t ok; TemporalError err;}; bool is_ok;} temporal_rs_PlainYearMonth_epoch_ms_for_result; temporal_rs_PlainYearMonth_epoch_ms_for_result temporal_rs_PlainYearMonth_epoch_ms_for(const PlainYearMonth* self, TimeZone time_zone); diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainDate.d.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainDate.d.hpp index e586d7ceb..62abc7e6c 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainDate.d.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainDate.d.hpp @@ -139,6 +139,8 @@ class PlainDate { inline temporal_rs::diplomat::result, temporal_rs::TemporalError> to_zoned_date_time_with_provider(temporal_rs::TimeZone time_zone, const temporal_rs::PlainTime* time, const temporal_rs::Provider& p) const; + inline temporal_rs::diplomat::result epoch_ms_for_utc() const; + inline std::string to_ixdtf_string(temporal_rs::DisplayCalendar display_calendar) const; template inline void to_ixdtf_string_write(temporal_rs::DisplayCalendar display_calendar, W& writeable_output) const; diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainDate.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainDate.hpp index 10673ade8..4f643693d 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainDate.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainDate.hpp @@ -141,6 +141,9 @@ namespace capi { typedef struct temporal_rs_PlainDate_to_zoned_date_time_with_provider_result {union {temporal_rs::capi::ZonedDateTime* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDate_to_zoned_date_time_with_provider_result; temporal_rs_PlainDate_to_zoned_date_time_with_provider_result temporal_rs_PlainDate_to_zoned_date_time_with_provider(const temporal_rs::capi::PlainDate* self, temporal_rs::capi::TimeZone time_zone, const temporal_rs::capi::PlainTime* time, const temporal_rs::capi::Provider* p); + typedef struct temporal_rs_PlainDate_epoch_ms_for_utc_result {union {int64_t ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDate_epoch_ms_for_utc_result; + temporal_rs_PlainDate_epoch_ms_for_utc_result temporal_rs_PlainDate_epoch_ms_for_utc(const temporal_rs::capi::PlainDate* self); + void temporal_rs_PlainDate_to_ixdtf_string(const temporal_rs::capi::PlainDate* self, temporal_rs::capi::DisplayCalendar display_calendar, temporal_rs::diplomat::capi::DiplomatWrite* write); temporal_rs::capi::PlainDate* temporal_rs_PlainDate_clone(const temporal_rs::capi::PlainDate* self); @@ -410,6 +413,11 @@ inline temporal_rs::diplomat::result return result.is_ok ? temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Ok>(std::unique_ptr(temporal_rs::ZonedDateTime::FromFFI(result.ok)))) : temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); } +inline temporal_rs::diplomat::result temporal_rs::PlainDate::epoch_ms_for_utc() const { + auto result = temporal_rs::capi::temporal_rs_PlainDate_epoch_ms_for_utc(this->AsFFI()); + return result.is_ok ? temporal_rs::diplomat::result(temporal_rs::diplomat::Ok(result.ok)) : temporal_rs::diplomat::result(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); +} + inline std::string temporal_rs::PlainDate::to_ixdtf_string(temporal_rs::DisplayCalendar display_calendar) const { std::string output; temporal_rs::diplomat::capi::DiplomatWrite write = temporal_rs::diplomat::WriteFromString(output); diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp index f5052625f..c77f5303f 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp @@ -148,6 +148,8 @@ class PlainDateTime { inline temporal_rs::diplomat::result, temporal_rs::TemporalError> to_zoned_date_time_with_provider(temporal_rs::TimeZone time_zone, temporal_rs::Disambiguation disambiguation, const temporal_rs::Provider& p) const; + inline temporal_rs::diplomat::result epoch_ms_for_utc() const; + inline temporal_rs::diplomat::result to_ixdtf_string(temporal_rs::ToStringRoundingOptions options, temporal_rs::DisplayCalendar display_calendar) const; template inline temporal_rs::diplomat::result to_ixdtf_string_write(temporal_rs::ToStringRoundingOptions options, temporal_rs::DisplayCalendar display_calendar, W& writeable_output) const; diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp index 2513e06d7..ecf67eaed 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp @@ -150,6 +150,9 @@ namespace capi { typedef struct temporal_rs_PlainDateTime_to_zoned_date_time_with_provider_result {union {temporal_rs::capi::ZonedDateTime* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_to_zoned_date_time_with_provider_result; temporal_rs_PlainDateTime_to_zoned_date_time_with_provider_result temporal_rs_PlainDateTime_to_zoned_date_time_with_provider(const temporal_rs::capi::PlainDateTime* self, temporal_rs::capi::TimeZone time_zone, temporal_rs::capi::Disambiguation disambiguation, const temporal_rs::capi::Provider* p); + typedef struct temporal_rs_PlainDateTime_epoch_ms_for_utc_result {union {int64_t ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_epoch_ms_for_utc_result; + temporal_rs_PlainDateTime_epoch_ms_for_utc_result temporal_rs_PlainDateTime_epoch_ms_for_utc(const temporal_rs::capi::PlainDateTime* self); + typedef struct temporal_rs_PlainDateTime_to_ixdtf_string_result {union { temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainDateTime_to_ixdtf_string_result; temporal_rs_PlainDateTime_to_ixdtf_string_result temporal_rs_PlainDateTime_to_ixdtf_string(const temporal_rs::capi::PlainDateTime* self, temporal_rs::capi::ToStringRoundingOptions options, temporal_rs::capi::DisplayCalendar display_calendar, temporal_rs::diplomat::capi::DiplomatWrite* write); @@ -454,6 +457,11 @@ inline temporal_rs::diplomat::result return result.is_ok ? temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Ok>(std::unique_ptr(temporal_rs::ZonedDateTime::FromFFI(result.ok)))) : temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); } +inline temporal_rs::diplomat::result temporal_rs::PlainDateTime::epoch_ms_for_utc() const { + auto result = temporal_rs::capi::temporal_rs_PlainDateTime_epoch_ms_for_utc(this->AsFFI()); + return result.is_ok ? temporal_rs::diplomat::result(temporal_rs::diplomat::Ok(result.ok)) : temporal_rs::diplomat::result(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); +} + inline temporal_rs::diplomat::result temporal_rs::PlainDateTime::to_ixdtf_string(temporal_rs::ToStringRoundingOptions options, temporal_rs::DisplayCalendar display_calendar) const { std::string output; temporal_rs::diplomat::capi::DiplomatWrite write = temporal_rs::diplomat::WriteFromString(output); diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.d.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.d.hpp index fd505d5a6..ac892b813 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.d.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.d.hpp @@ -69,6 +69,8 @@ class PlainMonthDay { inline temporal_rs::diplomat::result, temporal_rs::TemporalError> to_plain_date(std::optional year) const; + inline temporal_rs::diplomat::result epoch_ms_for_utc() const; + inline temporal_rs::diplomat::result epoch_ms_for(temporal_rs::TimeZone time_zone) const; inline temporal_rs::diplomat::result epoch_ms_for_with_provider(temporal_rs::TimeZone time_zone, const temporal_rs::Provider& p) const; diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.hpp index 3628a8f49..f3adda767 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.hpp @@ -61,6 +61,9 @@ namespace capi { typedef struct temporal_rs_PlainMonthDay_to_plain_date_result {union {temporal_rs::capi::PlainDate* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainMonthDay_to_plain_date_result; temporal_rs_PlainMonthDay_to_plain_date_result temporal_rs_PlainMonthDay_to_plain_date(const temporal_rs::capi::PlainMonthDay* self, temporal_rs::capi::PartialDate_option year); + typedef struct temporal_rs_PlainMonthDay_epoch_ms_for_utc_result {union {int64_t ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainMonthDay_epoch_ms_for_utc_result; + temporal_rs_PlainMonthDay_epoch_ms_for_utc_result temporal_rs_PlainMonthDay_epoch_ms_for_utc(const temporal_rs::capi::PlainMonthDay* self); + typedef struct temporal_rs_PlainMonthDay_epoch_ms_for_result {union {int64_t ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainMonthDay_epoch_ms_for_result; temporal_rs_PlainMonthDay_epoch_ms_for_result temporal_rs_PlainMonthDay_epoch_ms_for(const temporal_rs::capi::PlainMonthDay* self, temporal_rs::capi::TimeZone time_zone); @@ -160,6 +163,11 @@ inline temporal_rs::diplomat::result, te return result.is_ok ? temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Ok>(std::unique_ptr(temporal_rs::PlainDate::FromFFI(result.ok)))) : temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); } +inline temporal_rs::diplomat::result temporal_rs::PlainMonthDay::epoch_ms_for_utc() const { + auto result = temporal_rs::capi::temporal_rs_PlainMonthDay_epoch_ms_for_utc(this->AsFFI()); + return result.is_ok ? temporal_rs::diplomat::result(temporal_rs::diplomat::Ok(result.ok)) : temporal_rs::diplomat::result(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); +} + inline temporal_rs::diplomat::result temporal_rs::PlainMonthDay::epoch_ms_for(temporal_rs::TimeZone time_zone) const { auto result = temporal_rs::capi::temporal_rs_PlainMonthDay_epoch_ms_for(this->AsFFI(), time_zone.AsFFI()); diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainTime.d.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainTime.d.hpp index b4f01054e..d4d8eb306 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainTime.d.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainTime.d.hpp @@ -53,6 +53,8 @@ class PlainTime { inline static temporal_rs::diplomat::result, temporal_rs::TemporalError> from_epoch_nanoseconds_with_provider(temporal_rs::I128Nanoseconds ns, temporal_rs::TimeZone tz, const temporal_rs::Provider& p); + inline temporal_rs::diplomat::result epoch_ms_for_utc() const; + inline temporal_rs::diplomat::result, temporal_rs::TemporalError> with(temporal_rs::PartialTime partial, std::optional overflow) const; inline static temporal_rs::diplomat::result, temporal_rs::TemporalError> from_utf8(std::string_view s); diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainTime.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainTime.hpp index b15878bcb..6f765e3fd 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainTime.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainTime.hpp @@ -49,6 +49,9 @@ namespace capi { typedef struct temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider_result {union {temporal_rs::capi::PlainTime* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider_result; temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider_result temporal_rs_PlainTime_from_epoch_nanoseconds_with_provider(temporal_rs::capi::I128Nanoseconds ns, temporal_rs::capi::TimeZone tz, const temporal_rs::capi::Provider* p); + typedef struct temporal_rs_PlainTime_epoch_ms_for_utc_result {union {int64_t ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainTime_epoch_ms_for_utc_result; + temporal_rs_PlainTime_epoch_ms_for_utc_result temporal_rs_PlainTime_epoch_ms_for_utc(const temporal_rs::capi::PlainTime* self); + typedef struct temporal_rs_PlainTime_with_result {union {temporal_rs::capi::PlainTime* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainTime_with_result; temporal_rs_PlainTime_with_result temporal_rs_PlainTime_with(const temporal_rs::capi::PlainTime* self, temporal_rs::capi::PartialTime partial, temporal_rs::capi::ArithmeticOverflow_option overflow); @@ -152,6 +155,11 @@ inline temporal_rs::diplomat::result, te return result.is_ok ? temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Ok>(std::unique_ptr(temporal_rs::PlainTime::FromFFI(result.ok)))) : temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); } +inline temporal_rs::diplomat::result temporal_rs::PlainTime::epoch_ms_for_utc() const { + auto result = temporal_rs::capi::temporal_rs_PlainTime_epoch_ms_for_utc(this->AsFFI()); + return result.is_ok ? temporal_rs::diplomat::result(temporal_rs::diplomat::Ok(result.ok)) : temporal_rs::diplomat::result(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); +} + inline temporal_rs::diplomat::result, temporal_rs::TemporalError> temporal_rs::PlainTime::with(temporal_rs::PartialTime partial, std::optional overflow) const { auto result = temporal_rs::capi::temporal_rs_PlainTime_with(this->AsFFI(), partial.AsFFI(), diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.d.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.d.hpp index 585dea504..c550409d1 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.d.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.d.hpp @@ -96,6 +96,8 @@ class PlainYearMonth { inline temporal_rs::diplomat::result, temporal_rs::TemporalError> to_plain_date(std::optional day) const; + inline temporal_rs::diplomat::result epoch_ms_for_utc() const; + inline temporal_rs::diplomat::result epoch_ms_for(temporal_rs::TimeZone time_zone) const; inline temporal_rs::diplomat::result epoch_ms_for_with_provider(temporal_rs::TimeZone time_zone, const temporal_rs::Provider& p) const; diff --git a/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.hpp b/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.hpp index 2d499756b..aeefe108f 100644 --- a/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.hpp +++ b/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.hpp @@ -90,6 +90,9 @@ namespace capi { typedef struct temporal_rs_PlainYearMonth_to_plain_date_result {union {temporal_rs::capi::PlainDate* ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainYearMonth_to_plain_date_result; temporal_rs_PlainYearMonth_to_plain_date_result temporal_rs_PlainYearMonth_to_plain_date(const temporal_rs::capi::PlainYearMonth* self, temporal_rs::capi::PartialDate_option day); + typedef struct temporal_rs_PlainYearMonth_epoch_ms_for_utc_result {union {int64_t ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainYearMonth_epoch_ms_for_utc_result; + temporal_rs_PlainYearMonth_epoch_ms_for_utc_result temporal_rs_PlainYearMonth_epoch_ms_for_utc(const temporal_rs::capi::PlainYearMonth* self); + typedef struct temporal_rs_PlainYearMonth_epoch_ms_for_result {union {int64_t ok; temporal_rs::capi::TemporalError err;}; bool is_ok;} temporal_rs_PlainYearMonth_epoch_ms_for_result; temporal_rs_PlainYearMonth_epoch_ms_for_result temporal_rs_PlainYearMonth_epoch_ms_for(const temporal_rs::capi::PlainYearMonth* self, temporal_rs::capi::TimeZone time_zone); @@ -262,6 +265,11 @@ inline temporal_rs::diplomat::result, te return result.is_ok ? temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Ok>(std::unique_ptr(temporal_rs::PlainDate::FromFFI(result.ok)))) : temporal_rs::diplomat::result, temporal_rs::TemporalError>(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); } +inline temporal_rs::diplomat::result temporal_rs::PlainYearMonth::epoch_ms_for_utc() const { + auto result = temporal_rs::capi::temporal_rs_PlainYearMonth_epoch_ms_for_utc(this->AsFFI()); + return result.is_ok ? temporal_rs::diplomat::result(temporal_rs::diplomat::Ok(result.ok)) : temporal_rs::diplomat::result(temporal_rs::diplomat::Err(temporal_rs::TemporalError::FromFFI(result.err))); +} + inline temporal_rs::diplomat::result temporal_rs::PlainYearMonth::epoch_ms_for(temporal_rs::TimeZone time_zone) const { auto result = temporal_rs::capi::temporal_rs_PlainYearMonth_epoch_ms_for(this->AsFFI(), time_zone.AsFFI()); diff --git a/temporal_capi/src/plain_date.rs b/temporal_capi/src/plain_date.rs index 7752e3bd6..6c5420ce9 100644 --- a/temporal_capi/src/plain_date.rs +++ b/temporal_capi/src/plain_date.rs @@ -367,6 +367,19 @@ pub mod ffi { .map(|x| Box::new(ZonedDateTime(x))) .map_err(Into::into) } + + pub fn epoch_ms_for_utc(&self) -> Result { + let ns = self.0.epoch_ns_for_utc(); + + let ns_i128 = ns.as_i128(); + let ms = ns_i128 / 1_000_000; + if let Ok(ms) = i64::try_from(ms) { + Ok(ms) + } else { + Err(TemporalError::assert("Found an out-of-range Date")) + } + } + pub fn to_ixdtf_string( &self, display_calendar: DisplayCalendar, diff --git a/temporal_capi/src/plain_date_time.rs b/temporal_capi/src/plain_date_time.rs index b0800afdc..be33a7f2e 100644 --- a/temporal_capi/src/plain_date_time.rs +++ b/temporal_capi/src/plain_date_time.rs @@ -355,6 +355,18 @@ pub mod ffi { .map_err(Into::into) } + pub fn epoch_ms_for_utc(&self) -> Result { + let ns = self.0.epoch_ns_for_utc(); + + let ns_i128 = ns.as_i128(); + let ms = ns_i128 / 1_000_000; + if let Ok(ms) = i64::try_from(ms) { + Ok(ms) + } else { + Err(TemporalError::assert("Found an out-of-range DateTime")) + } + } + pub fn to_ixdtf_string( &self, options: ToStringRoundingOptions, diff --git a/temporal_capi/src/plain_month_day.rs b/temporal_capi/src/plain_month_day.rs index 6e54d0253..2180cc9cb 100644 --- a/temporal_capi/src/plain_month_day.rs +++ b/temporal_capi/src/plain_month_day.rs @@ -116,6 +116,18 @@ pub mod ffi { .map_err(Into::into) } + pub fn epoch_ms_for_utc(&self) -> Result { + let ns = self.0.epoch_ns_for_utc(); + + let ns_i128 = ns.as_i128(); + let ms = ns_i128 / 1_000_000; + if let Ok(ms) = i64::try_from(ms) { + Ok(ms) + } else { + Err(TemporalError::assert("Found an out-of-range MonthDay")) + } + } + #[cfg(feature = "compiled_data")] pub fn epoch_ms_for(&self, time_zone: TimeZone) -> Result { self.epoch_ms_for_with_provider(time_zone, &Provider::compiled()) diff --git a/temporal_capi/src/plain_time.rs b/temporal_capi/src/plain_time.rs index 3320d4513..83c1eed42 100644 --- a/temporal_capi/src/plain_time.rs +++ b/temporal_capi/src/plain_time.rs @@ -100,6 +100,18 @@ pub mod ffi { Ok(Box::new(Self(zdt.to_plain_time()))) } + pub fn epoch_ms_for_utc(&self) -> Result { + let ns = self.0.epoch_ns_for_utc(); + + let ns_i128 = ns.as_i128(); + let ms = ns_i128 / 1_000_000; + if let Ok(ms) = i64::try_from(ms) { + Ok(ms) + } else { + Err(TemporalError::assert("Found an out-of-range Time")) + } + } + pub fn with( &self, partial: PartialTime, diff --git a/temporal_capi/src/plain_year_month.rs b/temporal_capi/src/plain_year_month.rs index 2507bf3ab..733c89f4b 100644 --- a/temporal_capi/src/plain_year_month.rs +++ b/temporal_capi/src/plain_year_month.rs @@ -183,6 +183,18 @@ pub mod ffi { .map_err(Into::into) } + pub fn epoch_ms_for_utc(&self) -> Result { + let ns = self.0.epoch_ns_for_utc(); + + let ns_i128 = ns.as_i128(); + let ms = ns_i128 / 1_000_000; + if let Ok(ms) = i64::try_from(ms) { + Ok(ms) + } else { + Err(TemporalError::assert("Found an out-of-range YearMonth")) + } + } + #[cfg(feature = "compiled_data")] pub fn epoch_ms_for(&self, time_zone: TimeZone) -> Result { self.epoch_ms_for_with_provider(time_zone, &Provider::compiled())