Skip to content

Commit aa1db99

Browse files
authored
Add Eq and Ord for PlainYearMonth + Eq for PlainMonthDay (#175)
This PR adds `Eq` and `Ord` trait implementations for `PlainYearMonth` and an `Eq` trait impl for `PlainMonthDay` to enable implementing `Temporal.PlainYearMonth.compare`, `Temporal.PlainYearMonth.prototype.equals` and `Temporal.PlainMonthDay.prototype.equals`.
1 parent 1501955 commit aa1db99

File tree

6 files changed

+97
-67
lines changed

6 files changed

+97
-67
lines changed

src/builtins/core/date.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
TemporalError, TemporalResult, TemporalUnwrap, TimeZone,
1616
};
1717
use alloc::{format, string::String};
18-
use core::str::FromStr;
18+
use core::{cmp::Ordering, str::FromStr};
1919

2020
use super::{
2121
calendar::{ascii_four_to_integer, month_to_month_code},
@@ -139,18 +139,6 @@ impl core::fmt::Display for PlainDate {
139139
}
140140
}
141141

142-
impl Ord for PlainDate {
143-
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
144-
self.iso.cmp(&other.iso)
145-
}
146-
}
147-
148-
impl PartialOrd for PlainDate {
149-
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
150-
Some(self.cmp(other))
151-
}
152-
}
153-
154142
// ==== Private API ====
155143

156144
impl PlainDate {
@@ -437,6 +425,7 @@ impl PlainDate {
437425
self.iso.is_valid()
438426
}
439427

428+
// TODO: make private
440429
/// `DaysUntil`
441430
///
442431
/// Calculates the epoch days between two `Date`s
@@ -446,6 +435,20 @@ impl PlainDate {
446435
other.iso.to_epoch_days() - self.iso.to_epoch_days()
447436
}
448437

438+
/// Compares one `PlainDate` to another `PlainDate` using their
439+
/// `IsoDate` representation.
440+
///
441+
/// # Note on Ordering.
442+
///
443+
/// `temporal_rs` does not implement `PartialOrd`/`Ord` as `PlainDate` does
444+
/// not fulfill all the conditions required to implement the traits. However,
445+
/// it is possible to compare `PlainDate`'s as their `IsoDate` representation.
446+
#[inline]
447+
#[must_use]
448+
pub fn compare_iso(&self, other: &Self) -> Ordering {
449+
self.iso.cmp(&other.iso)
450+
}
451+
449452
#[inline]
450453
/// Adds a `Duration` to the current `Date`
451454
pub fn add(
@@ -639,30 +642,30 @@ mod tests {
639642
assert!(err.is_err());
640643
let err = PlainDate::try_new(275_760, 9, 14, Calendar::default());
641644
assert!(err.is_err());
642-
let ok = PlainDate::try_new(-271_821, 4, 19, Calendar::default()).unwrap();
645+
let ok = PlainDate::try_new(-271_821, 4, 19, Calendar::default());
643646
assert_eq!(
644647
ok,
645-
PlainDate {
648+
Ok(PlainDate {
646649
iso: IsoDate {
647650
year: -271_821,
648651
month: 4,
649652
day: 19,
650653
},
651654
calendar: Calendar::default(),
652-
}
655+
})
653656
);
654657

655-
let ok = PlainDate::try_new(275_760, 9, 13, Calendar::default()).unwrap();
658+
let ok = PlainDate::try_new(275_760, 9, 13, Calendar::default());
656659
assert_eq!(
657660
ok,
658-
PlainDate {
661+
Ok(PlainDate {
659662
iso: IsoDate {
660663
year: 275760,
661664
month: 9,
662665
day: 13,
663666
},
664667
calendar: Calendar::default(),
665-
}
668+
})
666669
);
667670
}
668671

src/builtins/core/datetime.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,6 @@ impl core::fmt::Display for PlainDateTime {
4545
}
4646
}
4747

48-
impl Ord for PlainDateTime {
49-
fn cmp(&self, other: &Self) -> Ordering {
50-
self.iso.cmp(&other.iso)
51-
}
52-
}
53-
54-
impl PartialOrd for PlainDateTime {
55-
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
56-
Some(self.cmp(other))
57-
}
58-
}
59-
6048
// ==== Private PlainDateTime API ====
6149

6250
impl PlainDateTime {
@@ -575,6 +563,20 @@ impl PlainDateTime {
575563
}
576564

577565
impl PlainDateTime {
566+
/// Compares one `PlainDateTime` to another `PlainDateTime` using their
567+
/// `IsoDate` representation.
568+
///
569+
/// # Note on Ordering.
570+
///
571+
/// `temporal_rs` does not implement `PartialOrd`/`Ord` as `PlainDateTime` does
572+
/// not fulfill all the conditions required to implement the traits. However,
573+
/// it is possible to compare `PlainDate`'s as their `IsoDate` representation.
574+
#[inline]
575+
#[must_use]
576+
pub fn compare_iso(&self, other: &Self) -> Ordering {
577+
self.iso.cmp(&other.iso)
578+
}
579+
578580
#[inline]
579581
/// Adds a `Duration` to the current `DateTime`.
580582
pub fn add(

src/builtins/core/month_day.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414

1515
/// The native Rust implementation of `Temporal.PlainMonthDay`
1616
#[non_exhaustive]
17-
#[derive(Debug, Default, Clone)]
17+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
1818
pub struct PlainMonthDay {
1919
pub iso: IsoDate,
2020
calendar: Calendar,

src/builtins/core/year_month.rs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module implements `YearMonth` and any directly related algorithms.
22
33
use alloc::string::String;
4-
use core::str::FromStr;
4+
use core::{cmp::Ordering, str::FromStr};
55

66
use tinystr::TinyAsciiStr;
77

@@ -17,7 +17,7 @@ use super::{Duration, PartialDate};
1717

1818
/// The native Rust implementation of `Temporal.YearMonth`.
1919
#[non_exhaustive]
20-
#[derive(Debug, Default, Clone)]
20+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
2121
pub struct PlainYearMonth {
2222
pub(crate) iso: IsoDate,
2323
calendar: Calendar,
@@ -72,44 +72,53 @@ impl PlainYearMonth {
7272
self.iso.month
7373
}
7474

75+
/// Returns the calendar era of the current `PlainYearMonth`
76+
pub fn era(&self) -> TemporalResult<Option<TinyAsciiStr<16>>> {
77+
self.calendar().era(&self.iso)
78+
}
79+
80+
/// Returns the calendar era year of the current `PlainYearMonth`
81+
pub fn era_year(&self) -> TemporalResult<Option<i32>> {
82+
self.calendar().era_year(&self.iso)
83+
}
84+
85+
/// Returns the calendar year of the current `PlainYearMonth`
7586
pub fn year(&self) -> TemporalResult<i32> {
7687
self.calendar().year(&self.iso)
7788
}
7889

90+
/// Returns the calendar month of the current `PlainYearMonth`
7991
pub fn month(&self) -> TemporalResult<u8> {
8092
self.calendar().month(&self.iso)
8193
}
8294

95+
/// Returns the calendar month code of the current `PlainYearMonth`
8396
pub fn month_code(&self) -> TemporalResult<TinyAsciiStr<4>> {
8497
self.calendar().month_code(&self.iso)
8598
}
8699

87-
#[inline]
88-
#[must_use]
89-
pub fn in_leap_year(&self) -> bool {
90-
self.calendar()
91-
.in_leap_year(&self.iso)
92-
.is_ok_and(|is_leap_year| is_leap_year)
93-
}
94-
95-
pub fn get_days_in_year(&self) -> TemporalResult<u16> {
100+
/// Returns the days in the calendar year of the current `PlainYearMonth`.
101+
pub fn days_in_year(&self) -> TemporalResult<u16> {
96102
self.calendar().days_in_year(&self.iso)
97103
}
98104

99-
pub fn get_days_in_month(&self) -> TemporalResult<u16> {
105+
/// Returns the days in the calendar month of the current `PlainYearMonth`.
106+
pub fn days_in_month(&self) -> TemporalResult<u16> {
100107
self.calendar().days_in_month(&self.iso)
101108
}
102109

103-
pub fn get_months_in_year(&self) -> TemporalResult<u16> {
110+
/// Returns the months in the calendar year of the current `PlainYearMonth`.
111+
pub fn months_in_year(&self) -> TemporalResult<u16> {
104112
self.calendar().months_in_year(&self.iso)
105113
}
106114

107-
pub fn era(&self) -> TemporalResult<Option<TinyAsciiStr<16>>> {
108-
self.calendar().era(&self.iso)
109-
}
110-
111-
pub fn era_year(&self) -> TemporalResult<Option<i32>> {
112-
self.calendar().era_year(&self.iso)
115+
#[inline]
116+
#[must_use]
117+
/// Returns a boolean representing whether the current `PlainYearMonth` is in a leap year.
118+
pub fn in_leap_year(&self) -> bool {
119+
self.calendar()
120+
.in_leap_year(&self.iso)
121+
.is_ok_and(|is_leap_year| is_leap_year)
113122
}
114123
}
115124

@@ -128,6 +137,20 @@ impl PlainYearMonth {
128137
self.calendar.identifier()
129138
}
130139

140+
/// Compares one `PlainYearMonth` to another `PlainYearMonth` using their
141+
/// `IsoDate` representation.
142+
///
143+
/// # Note on Ordering.
144+
///
145+
/// `temporal_rs` does not implement `PartialOrd`/`Ord` as `PlainYearMonth` does
146+
/// not fulfill all the conditions required to implement the traits. However,
147+
/// it is possible to compare `PlainDate`'s as their `IsoDate` representation.
148+
#[inline]
149+
#[must_use]
150+
pub fn compare_iso(&self, other: &Self) -> Ordering {
151+
self.iso.cmp(&other.iso)
152+
}
153+
131154
pub fn add_duration(
132155
&self,
133156
duration: &Duration,

src/builtins/core/zoneddatetime.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module implements `ZonedDateTime` and any directly related algorithms.
22
33
use alloc::string::String;
4-
use core::num::NonZeroU128;
4+
use core::{cmp::Ordering, num::NonZeroU128};
55
use ixdtf::parsers::records::{TimeZoneRecord, UtcOffsetRecordOrZ};
66
use tinystr::TinyAsciiStr;
77

@@ -50,18 +50,6 @@ pub struct ZonedDateTime {
5050
tz: TimeZone,
5151
}
5252

53-
impl Ord for ZonedDateTime {
54-
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
55-
self.instant.cmp(&other.instant)
56-
}
57-
}
58-
59-
impl PartialOrd for ZonedDateTime {
60-
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
61-
Some(self.cmp(other))
62-
}
63-
}
64-
6553
// ==== Private API ====
6654

6755
impl ZonedDateTime {
@@ -432,6 +420,20 @@ impl ZonedDateTime {
432420
pub fn with_calendar(&self, calendar: Calendar) -> TemporalResult<Self> {
433421
Self::try_new(self.epoch_nanoseconds(), calendar, self.tz.clone())
434422
}
423+
424+
/// Compares one `ZonedDateTime` to another `ZonedDateTime` using their
425+
/// `Instant` representation.
426+
///
427+
/// # Note on Ordering.
428+
///
429+
/// `temporal_rs` does not implement `PartialOrd`/`Ord` as `ZonedDateTime` does
430+
/// not fulfill all the conditions required to implement the traits. However,
431+
/// it is possible to compare `PlainDate`'s as their `IsoDate` representation.
432+
#[inline]
433+
#[must_use]
434+
pub fn compare_instant(&self, other: &Self) -> Ordering {
435+
self.instant.cmp(&other.instant)
436+
}
435437
}
436438

437439
// ==== HoursInDay accessor method implementation ====

temporal_capi/src/plain_year_month.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ pub mod ffi {
6464
self.0.in_leap_year()
6565
}
6666
pub fn days_in_month(&self) -> Result<u16, TemporalError> {
67-
self.0.get_days_in_month().map_err(Into::into)
67+
self.0.days_in_month().map_err(Into::into)
6868
}
6969
pub fn days_in_year(&self) -> Result<u16, TemporalError> {
70-
self.0.get_days_in_year().map_err(Into::into)
70+
self.0.days_in_year().map_err(Into::into)
7171
}
7272
pub fn months_in_year(&self) -> Result<u16, TemporalError> {
73-
self.0.get_months_in_year().map_err(Into::into)
73+
self.0.months_in_year().map_err(Into::into)
7474
}
7575
// Writes an empty string for no era
7676
pub fn era(&self, write: &mut DiplomatWrite) -> Result<(), TemporalError> {

0 commit comments

Comments
 (0)