Skip to content

Commit

Permalink
Fix limit.js test and add datetime limit test
Browse files Browse the repository at this point in the history
  • Loading branch information
nekevss committed Jan 30, 2024
1 parent 8951d92 commit 1de809d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 13 deletions.
43 changes: 43 additions & 0 deletions core/temporal/src/components/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,3 +375,46 @@ impl<C: CalendarProtocol> FromStr for DateTime<C> {
))
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;

use crate::components::calendar::CalendarSlot;

use super::DateTime;

#[test]
#[allow(clippy::float_cmp)]
fn plain_date_time_limits() {
// This test is primarily to assert that the `expect` in the epoch methods is
// valid, i.e., a valid instant is within the range of an f64.
let negative_limit = DateTime::<()>::new(
-271821,
4,
19,
0,
0,
0,
0,
0,
0,
CalendarSlot::from_str("iso8601").unwrap(),
);
let positive_limit = DateTime::<()>::new(
275760,
9,
14,
0,
0,
0,
0,
0,
0,
CalendarSlot::from_str("iso8601").unwrap(),
);

assert!(negative_limit.is_err());
assert!(positive_limit.is_err());
}
}
20 changes: 11 additions & 9 deletions core/temporal/src/iso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,10 +562,10 @@ impl IsoTime {
///
/// Functionally the same as Date's `MakeTime`
pub(crate) fn to_epoch_ms(self) -> f64 {
f64::from(self.hour).mul_add(
utils::MS_PER_HOUR,
f64::from(self.minute) * utils::MS_PER_MINUTE,
) + f64::from(self.second).mul_add(1000f64, f64::from(self.millisecond))
((f64::from(self.hour) * utils::MS_PER_HOUR
+ f64::from(self.minute) * utils::MS_PER_MINUTE)
+ f64::from(self.second) * 1000f64)
+ f64::from(self.millisecond)
}
}

Expand All @@ -574,6 +574,9 @@ impl IsoTime {
#[inline]
/// Utility function to determine if a `DateTime`'s components create a `DateTime` within valid limits
fn iso_dt_within_valid_limits(date: IsoDate, time: &IsoTime) -> bool {
if iso_date_to_epoch_days(date.year, (date.month).into(), date.day.into()).abs() > 100_000_001 {
return false;
}
let Some(ns) = utc_epoch_nanos(date, time, 0.0) else {
return false;
};
Expand All @@ -587,9 +590,8 @@ fn iso_dt_within_valid_limits(date: IsoDate, time: &IsoTime) -> bool {
#[inline]
/// Utility function to convert a `IsoDate` and `IsoTime` values into epoch nanoseconds
fn utc_epoch_nanos(date: IsoDate, time: &IsoTime, offset: f64) -> Option<BigInt> {
let day = date.to_epoch_days();
let time_in_ms = time.to_epoch_ms();
let epoch_ms = utils::epoch_days_to_epoch_ms(day, time_in_ms);
let ms = time.to_epoch_ms();
let epoch_ms = utils::epoch_days_to_epoch_ms(date.to_epoch_days(), ms);

let epoch_nanos = epoch_ms.mul_add(
1_000_000f64,
Expand All @@ -607,14 +609,14 @@ fn iso_date_to_epoch_days(year: i32, month: i32, day: i32) -> i32 {
// 1. Let resolvedYear be year + floor(month / 12).
let resolved_year = year + (f64::from(month) / 12_f64).floor() as i32;
// 2. Let resolvedMonth be month modulo 12.
let resolved_month = month % 12;
let resolved_month = month.rem_euclid(12);

// 3. Find a time t such that EpochTimeToEpochYear(t) is resolvedYear, EpochTimeToMonthInYear(t) is resolvedMonth, and EpochTimeToDate(t) is 1.
let year_t = utils::epoch_time_for_year(resolved_year);
let month_t = utils::epoch_time_for_month_given_year(resolved_month, resolved_year);

// 4. Return EpochTimeToDayNumber(t) + date - 1.
utils::epoch_time_to_day_number(year_t + month_t) + day - 1
utils::epoch_time_to_day_number((year_t.abs() + month_t).copysign(year_t)) + day
}

#[inline]
Expand Down
2 changes: 1 addition & 1 deletion core/temporal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub type TemporalResult<T> = Result<T, TemporalError>;

// Relevant numeric constants
/// Nanoseconds per day constant: 8.64e+13
pub const NS_PER_DAY: i64 = 86_400_000_000_000;
pub const NS_PER_DAY: i64 = MS_PER_DAY as i64 * 1_000_000;
/// Milliseconds per day constant: 8.64e+7
pub const MS_PER_DAY: i32 = 24 * 60 * 60 * 1000;
/// Max Instant nanosecond constant
Expand Down
4 changes: 1 addition & 3 deletions core/temporal/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use crate::{
TemporalError, TemporalResult, MS_PER_DAY,
};

use std::ops::Mul;

// NOTE: Review the below for optimizations and add ALOT of tests.

/// Converts and validates an `Option<f64>` rounding increment value into a valid increment result.
Expand Down Expand Up @@ -264,7 +262,7 @@ pub(crate) fn epoch_time_for_month_given_year(m: i32, y: i32) -> f64 {
_ => unreachable!(),
};

f64::from(MS_PER_DAY).mul(f64::from(days))
f64::from(MS_PER_DAY) * f64::from(days)
}

pub(crate) fn epoch_time_to_date(t: f64) -> u8 {
Expand Down

0 comments on commit 1de809d

Please sign in to comment.