Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/builtins/core/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,15 @@ impl PlainDate {
resolved.smallest_unit == Unit::Day && resolved.increment.get() == 1;
// 12. If roundingGranularityIsNoop is false, then
if !rounding_granularity_is_noop {
let iso_date_time = IsoDateTime::new_unchecked(self.iso, IsoTime::default());
let origin_epoch_ns = iso_date_time.as_nanoseconds();
// a. Let destEpochNs be GetUTCEpochNanoseconds(other.[[ISOYear]], other.[[ISOMonth]], other.[[ISODay]], 0, 0, 0, 0, 0, 0).
let dest_epoch_ns = other.iso.as_nanoseconds();
// b. Let dateTime be ISO Date-Time Record { [[Year]]: temporalDate.[[ISOYear]], [[Month]]: temporalDate.[[ISOMonth]], [[Day]]: temporalDate.[[ISODay]], [[Hour]]: 0, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0 }.
let dt = PlainDateTime::new_unchecked(
IsoDateTime::new_unchecked(self.iso, IsoTime::default()),
self.calendar.clone(),
);
let dt = PlainDateTime::new_unchecked(iso_date_time, self.calendar.clone());
// c. Set duration to ? RoundRelativeDuration(duration, destEpochNs, dateTime, calendarRec, unset, settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
duration = duration.round_relative_duration(
origin_epoch_ns,
dest_epoch_ns.0,
&dt,
Option::<(&TimeZone, &NeverProvider)>::None,
Expand Down
3 changes: 3 additions & 0 deletions src/builtins/core/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ impl PlainDateTime {
let dest_epoch_ns = other.iso.as_nanoseconds();
// 6. Return ? RoundRelativeDuration(diff, destEpochNs, isoDateTime1, unset, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode).
diff.round_relative_duration(
self.iso.as_nanoseconds(),
dest_epoch_ns.0,
self,
Option::<(&TimeZone, &NeverProvider)>::None,
Expand All @@ -336,10 +337,12 @@ impl PlainDateTime {
if unit == Unit::Nanosecond {
return FiniteF64::try_from(diff.normalized_time_duration().0);
}
let origin_epoch_ns = self.iso.as_nanoseconds();
// 5. Let destEpochNs be GetUTCEpochNanoseconds(isoDateTime2).
let dest_epoch_ns = other.iso.as_nanoseconds();
// 6. Return ? TotalRelativeDuration(diff, destEpochNs, isoDateTime1, unset, calendar, unit).
diff.total_relative_duration(
origin_epoch_ns,
dest_epoch_ns.0,
self,
Option::<(&TimeZone, &NeverProvider)>::None,
Expand Down
50 changes: 36 additions & 14 deletions src/builtins/core/duration/normalized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use core::{cmp, num::NonZeroU128, ops::Add};

use num_traits::AsPrimitive;
use timezone_provider::epoch_nanoseconds::EpochNanoseconds;

use crate::{
builtins::core::{timezone::TimeZone, PlainDate, PlainDateTime},
Expand Down Expand Up @@ -370,6 +371,7 @@ impl InternalDurationRecord {
fn nudge_calendar_unit(
&self,
sign: Sign,
origin_epoch_ns: EpochNanoseconds,
dest_epoch_ns: i128,
dt: &PlainDateTime,
tz: Option<(&TimeZone, &impl TimeZoneProvider)>, // ???
Expand Down Expand Up @@ -562,33 +564,43 @@ impl InternalDurationRecord {
_ => unreachable!(), // TODO: potentially reject with range error?
};

// 7. Let start be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], startDuration, constrain).
let start =
dt.calendar()
.date_add(&dt.iso.date, &start_duration, ArithmeticOverflow::Constrain)?;
let start_epoch_ns = if r1 == 0 {
origin_epoch_ns
} else {
// 7. Let start be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], startDuration, constrain).
let start = dt.calendar().date_add(
&dt.iso.date,
&start_duration,
ArithmeticOverflow::Constrain,
)?;
// 9. Let startDateTime be CombineISODateAndTimeRecord(start, isoDateTime.[[Time]]).
let start_date_time = IsoDateTime::new_unchecked(start.iso, dt.iso.time);
if let Some((tz, provider)) = tz {
tz.get_epoch_nanoseconds_for(start_date_time, Disambiguation::Compatible, provider)?
.ns
} else {
start_date_time.as_nanoseconds()
}
};

// 8. Let end be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], endDuration, constrain).
let end =
dt.calendar()
.date_add(&dt.iso.date, &end_duration, ArithmeticOverflow::Constrain)?;
// 9. Let startDateTime be CombineISODateAndTimeRecord(start, isoDateTime.[[Time]]).
let start = IsoDateTime::new_unchecked(start.iso, dt.iso.time);
// 10. Let endDateTime be CombineISODateAndTimeRecord(end, isoDateTime.[[Time]]).
let end = IsoDateTime::new_unchecked(end.iso, dt.iso.time);

// 12. Else,
let (start_epoch_ns, end_epoch_ns) = if let Some((tz, provider)) = tz {
let end_epoch_ns = if let Some((tz, provider)) = tz {
// a. Let startEpochNs be ? GetEpochNanosecondsFor(timeZone, startDateTime, compatible).
// b. Let endEpochNs be ? GetEpochNanosecondsFor(timeZone, endDateTime, compatible).
let start_epoch_ns =
tz.get_epoch_nanoseconds_for(start, Disambiguation::Compatible, provider)?;
let end_epoch_ns =
tz.get_epoch_nanoseconds_for(end, Disambiguation::Compatible, provider)?;
(start_epoch_ns.ns, end_epoch_ns.ns)
tz.get_epoch_nanoseconds_for(end, Disambiguation::Compatible, provider)?
.ns
// 11. If timeZoneRec is unset, then
} else {
// a. Let startEpochNs be GetUTCEpochNanoseconds(start.[[Year]], start.[[Month]], start.[[Day]], start.[[Hour]], start.[[Minute]], start.[[Second]], start.[[Millisecond]], start.[[Microsecond]], start.[[Nanosecond]]).
// b. Let endEpochNs be GetUTCEpochNanoseconds(end.[[Year]], end.[[Month]], end.[[Day]], end.[[Hour]], end.[[Minute]], end.[[Second]], end.[[Millisecond]], end.[[Microsecond]], end.[[Nanosecond]]).
(start.as_nanoseconds(), end.as_nanoseconds())
end.as_nanoseconds()
};

// TODO: look into handling asserts
Expand Down Expand Up @@ -947,6 +959,7 @@ impl InternalDurationRecord {
#[inline]
pub(crate) fn round_relative_duration(
&self,
origin_epoch_ns: EpochNanoseconds,
dest_epoch_ns: i128,
dt: &PlainDateTime,
time_zone: Option<(&TimeZone, &impl TimeZoneProvider)>,
Expand All @@ -967,7 +980,14 @@ impl InternalDurationRecord {
let nudge_result = if irregular_length_unit {
// a. Let record be ? NudgeToCalendarUnit(sign, duration, destEpochNs, isoDateTime, timeZone, calendar, increment, smallestUnit, roundingMode).
// b. Let nudgeResult be record.[[NudgeResult]].
duration.nudge_calendar_unit(sign, dest_epoch_ns, dt, time_zone, options)?
duration.nudge_calendar_unit(
sign,
origin_epoch_ns,
dest_epoch_ns,
dt,
time_zone,
options,
)?
} else if let Some((time_zone, time_zone_provider)) = time_zone {
// 6. Else if timeZone is not unset, then
// a. Let nudgeResult be ? NudgeToZonedTime(sign, duration, isoDateTime, timeZone, calendar, increment, smallestUnit, roundingMode).
Expand Down Expand Up @@ -1005,6 +1025,7 @@ impl InternalDurationRecord {
// 7.5.38 TotalRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone, calendar, unit )
pub(crate) fn total_relative_duration(
&self,
origin_epoch_ns: EpochNanoseconds,
dest_epoch_ns: i128,
dt: &PlainDateTime,
tz: Option<(&TimeZone, &impl TimeZoneProvider)>,
Expand All @@ -1017,6 +1038,7 @@ impl InternalDurationRecord {
// b. Let record be ? NudgeToCalendarUnit(sign, duration, destEpochNs, isoDateTime, timeZone, calendar, 1, unit, trunc).
let record = self.nudge_calendar_unit(
sign,
origin_epoch_ns,
dest_epoch_ns,
dt,
tz,
Expand Down
1 change: 1 addition & 0 deletions src/builtins/core/year_month.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ impl PlainYearMonth {
let dest_epoch_ns = target_iso_date_time.as_nanoseconds();
// d. Set duration to ? RoundRelativeDuration(duration, destEpochNs, isoDateTime, unset, calendar, resolved.[[LargestUnit]], resolved.[[RoundingIncrement]], resolved.[[SmallestUnit]], resolved.[[RoundingMode]]).
duration = duration.round_relative_duration(
iso_date_time.as_nanoseconds(),
dest_epoch_ns.as_i128(),
&PlainDateTime::new_unchecked(iso_date_time, self.calendar.clone()),
Option::<(&TimeZone, &NeverProvider)>::None,
Expand Down
2 changes: 2 additions & 0 deletions src/builtins/core/zoneddatetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ impl ZonedDateTime {
let iso = self.get_iso_datetime();
// 5. Return ? RoundRelativeDuration(difference, ns2, dateTime, timeZone, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode).
diff.round_relative_duration(
*self.epoch_nanoseconds(),
other.epoch_nanoseconds().as_i128(),
&PlainDateTime::new_unchecked(iso, self.calendar().clone()),
Some((self.timezone(), provider)),
Expand Down Expand Up @@ -430,6 +431,7 @@ impl ZonedDateTime {
let iso = self.get_iso_datetime();
// 4. Return ? TotalRelativeDuration(difference, ns2, dateTime, timeZone, calendar, unit).
diff.total_relative_duration(
*self.epoch_nanoseconds(),
other.epoch_nanoseconds().as_i128(),
&PlainDateTime::new_unchecked(iso, self.calendar().clone()),
Some((self.timezone(), provider)),
Expand Down
Loading