Skip to content
Merged
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
67 changes: 37 additions & 30 deletions src/builtins/core/duration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,27 +181,26 @@ impl Duration {
duration_record.normalized_time_duration(),
largest_unit,
)?;
Self::new(
duration_record.date().years.into(),
duration_record.date().months.into(),
duration_record.date().weeks.into(),
let sign = duration_record.sign()?;
let mut duration = Self::new(
i64::from(duration_record.date().years),
i64::from(duration_record.date().months),
i64::from(duration_record.date().weeks),
i64::try_from(duration_record.date().days)
.or(Err(TemporalError::range()))?
.checked_add(overflow_day)
.ok_or(TemporalError::range())?,
time.hours.try_into().or(Err(TemporalError::range()))?,
time.minutes.try_into().or(Err(TemporalError::range()))?,
time.seconds.try_into().or(Err(TemporalError::range()))?,
time.milliseconds
.try_into()
.or(Err(TemporalError::range()))?,
time.microseconds
.try_into()
.or(Err(TemporalError::range()))?,
time.nanoseconds
.try_into()
.or(Err(TemporalError::range()))?,
)
i64::try_from(time.hours).or(Err(TemporalError::range()))?,
i64::try_from(time.minutes).or(Err(TemporalError::range()))?,
i64::try_from(time.seconds).or(Err(TemporalError::range()))?,
i64::try_from(time.milliseconds).or(Err(TemporalError::range()))?,
i128::try_from(time.microseconds).or(Err(TemporalError::range()))?,
i128::try_from(time.nanoseconds).or(Err(TemporalError::range()))?,
)?;
if sign == Sign::Negative {
duration = duration.negated();
}
Ok(duration)
}

/// Returns this `Duration` as a `NormalizedTimeDuration`.
Expand Down Expand Up @@ -1519,19 +1518,27 @@ impl FromStr for Duration {
(0, 0, 0, 0)
};

let sign = parse_record.sign as i64;
let sign = if parse_record.sign == ixdtf::parsers::records::Sign::Negative {
Sign::Negative
} else {
Sign::Positive
};

Self::new(
years as i64 * sign,
months as i64 * sign,
weeks as i64 * sign,
days as i64 * sign,
hours as i64 * sign,
minutes as i64 * sign,
seconds as i64 * sign,
millis as i64 * sign,
micros as i128 * sign as i128,
nanos as i128 * sign as i128,
)
let mut duration = Self::new(
years as i64,
months as i64,
weeks as i64,
days as i64,
hours as i64,
minutes as i64,
seconds as i64,
millis as i64,
micros as i128,
nanos as i128,
)?;
if sign == Sign::Negative {
duration = duration.negated();
}
Ok(duration)
}
}
20 changes: 14 additions & 6 deletions src/iso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,14 @@ impl IsoDateTime {
let date = PlainDate::new_unchecked(self.date, calendar);

// 5. Let dateDuration be ? CreateTemporalDuration(years, months, weeks, days + timeResult.[[Days]], 0, 0, 0, 0, 0, 0).
let sign = date_duration.sign.as_sign_multiplier();
let date_duration = DateDuration::new(
date_duration.years.into(),
date_duration.months.into(),
date_duration.weeks.into(),
i64::from(date_duration.years) * i64::from(sign),
i64::from(date_duration.months) * i64::from(sign),
i64::from(date_duration.weeks) * i64::from(sign),
i64::try_from(date_duration.days)
.or(Err(TemporalError::range()))?
* i64::from(sign)
.checked_add(t_result.0)
.ok_or(TemporalError::range())?,
)?;
Expand Down Expand Up @@ -399,9 +401,13 @@ impl IsoDate {
// 1. Assert: year, month, day, years, months, weeks, and days are integers.
// 2. Assert: overflow is either "constrain" or "reject".
// 3. Let intermediate be ! BalanceISOYearMonth(year + years, month + months).
let year_offset = i64::from(duration.years)
* i64::from(duration.sign.as_sign_multiplier());
let month_offset = i64::from(duration.months)
* i64::from(duration.sign.as_sign_multiplier());
let intermediate = balance_iso_year_month_with_clamp(
i64::from(self.year) + i64::from(duration.years),
i64::from(self.month) + i64::from(duration.months),
i64::from(self.year) + year_offset,
i64::from(self.month) + month_offset,
);

// 4. Let intermediate be ? RegulateISODate(intermediate.[[Year]], intermediate.[[Month]], day, overflow).
Expand All @@ -410,7 +416,9 @@ impl IsoDate {

// 5. Set days to days + 7 × weeks.
let additional_days = i64::try_from(duration.days).or(Err(TemporalError::range()))?
+ (7 * i64::from(duration.weeks)); // Verify
* i64::from(duration.sign.as_sign_multiplier())
+ (7 * i64::from(duration.weeks)
* i64::from(duration.sign.as_sign_multiplier()));

// 6. Let d be intermediate.[[Day]] + days.
let intermediate_days = i64::from(intermediate.day) + additional_days;
Expand Down
7 changes: 4 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,11 @@ impl From<i64> for Sign {
impl Sign {
/// Coerces the current `Sign` to be either negative or positive.
pub(crate) fn as_sign_multiplier(&self) -> i8 {
if matches!(self, Self::Zero) {
return 1;
match self {
Self::Positive => 1,
Self::Negative => -1,
Self::Zero => 0,
}
*self as i8
}

pub(crate) fn negate(&self) -> Sign {
Expand Down