Skip to content

Commit 3eee9a8

Browse files
authored
Add documentation and doctests for builtins (#360)
Added documentation and doctests for builtin types, including MDN references and examples on how to use them with popular use cases. #107
1 parent f2c5efe commit 3eee9a8

File tree

8 files changed

+912
-29
lines changed

8 files changed

+912
-29
lines changed

src/builtins/core/date.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,74 @@ impl PartialDate {
154154
}
155155

156156
/// The native Rust implementation of `Temporal.PlainDate`.
157+
///
158+
/// Represents a calendar date without any time or timezone
159+
/// information. Useful for dates where the specific time of day doesn't matter,
160+
/// such as deadlines, birth dates, or historical events.
161+
///
162+
/// Uses the ISO 8601 calendar (proleptic Gregorian calendar) by default, with
163+
/// support for other calendar systems when needed.
164+
///
165+
/// ## Examples
166+
///
167+
/// ### Creating dates
168+
///
169+
/// ```rust
170+
/// use temporal_rs::{PlainDate, Calendar};
171+
///
172+
/// // Create a date using the ISO calendar
173+
/// let christmas = PlainDate::try_new_iso(2024, 12, 25).unwrap();
174+
/// assert_eq!(christmas.year(), 2024);
175+
/// assert_eq!(christmas.month(), 12);
176+
/// assert_eq!(christmas.day(), 25);
177+
///
178+
/// // Explicit calendar specification
179+
/// let date = PlainDate::try_new(2024, 12, 25, Calendar::default()).unwrap();
180+
/// assert_eq!(date.year(), 2024);
181+
/// assert_eq!(christmas, date); // Both represent the same date
182+
/// ```
183+
///
184+
/// ### Date arithmetic operations
185+
///
186+
/// ```rust
187+
/// use temporal_rs::{PlainDate, Duration};
188+
/// use core::str::FromStr;
189+
///
190+
/// let start = PlainDate::try_new_iso(2024, 1, 15).unwrap();
191+
///
192+
/// // Add one month
193+
/// let later = start.add(&Duration::from_str("P1M").unwrap(), None).unwrap();
194+
/// assert_eq!(later.month(), 2); // Results in 2024-02-15
195+
/// assert_eq!(later.day(), 15);
196+
///
197+
/// // Calculate duration between dates
198+
/// let new_year = PlainDate::try_new_iso(2024, 1, 1).unwrap();
199+
/// let diff = new_year.until(&start, Default::default()).unwrap();
200+
/// assert_eq!(diff.days(), 14);
201+
/// ```
202+
///
203+
/// ### Parsing ISO 8601 date strings
204+
///
205+
/// ```rust
206+
/// use temporal_rs::PlainDate;
207+
/// use core::str::FromStr;
208+
///
209+
/// // Standard ISO date format
210+
/// let date = PlainDate::from_str("2024-03-15").unwrap();
211+
/// assert_eq!(date.year(), 2024);
212+
/// assert_eq!(date.month(), 3);
213+
/// assert_eq!(date.day(), 15);
214+
///
215+
/// // With explicit calendar annotation
216+
/// let date2 = PlainDate::from_str("2024-03-15[u-ca=iso8601]").unwrap();
217+
/// assert_eq!(date, date2);
218+
/// ```
219+
///
220+
/// ## Reference
221+
///
222+
/// For more information, see the [MDN documentation][mdn-plaindate].
223+
///
224+
/// [mdn-plaindate]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate
157225
#[non_exhaustive]
158226
#[derive(Debug, Default, Clone, PartialEq, Eq)]
159227
pub struct PlainDate {

src/builtins/core/datetime.rs

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,109 @@ impl PartialDateTime {
5454
}
5555
}
5656

57-
// TODO: Example doctest
5857
/// The native Rust implementation of a Temporal `PlainDateTime`.
5958
///
60-
/// The `PlainDateTime` represents a date and time without a
61-
/// time zone. The fundemental represenation of a `PlainDateTime`
62-
/// is it's internal ISO date and time fields and a calendar.
59+
/// Combines a date and time into a single value representing a specific moment
60+
/// in calendar time, such as "2024-03-15T14:30:45". Unlike `Instant`,
61+
/// a `PlainDateTime` does not include timezone information.
62+
///
63+
/// Use `PlainDateTime` when you need to represent a specific date and time but
64+
/// timezone handling is not required, or when working with local times that
65+
/// don't need to be converted across timezones.
66+
///
67+
/// ## Examples
68+
///
69+
/// ### Creating date and time values
70+
///
71+
/// ```rust
72+
/// use temporal_rs::PlainDateTime;
73+
/// use core::str::FromStr;
74+
///
75+
/// // Create a specific date and time from IXDTF string
76+
/// let meeting = PlainDateTime::from_str("2024-03-15T14:30:45.123456789").unwrap();
77+
/// assert_eq!(meeting.year(), 2024);
78+
/// assert_eq!(meeting.hour(), 14);
79+
/// assert_eq!(meeting.minute(), 30);
80+
/// ```
81+
///
82+
/// ### Parsing ISO 8601 datetime strings
83+
///
84+
/// ```rust
85+
/// use temporal_rs::PlainDateTime;
86+
/// use core::str::FromStr;
87+
///
88+
/// let dt = PlainDateTime::from_str("2024-03-15T14:30:45.123456789").unwrap();
89+
/// assert_eq!(dt.year(), 2024);
90+
/// assert_eq!(dt.month(), 3);
91+
/// assert_eq!(dt.day(), 15);
92+
/// assert_eq!(dt.hour(), 14);
93+
/// assert_eq!(dt.minute(), 30);
94+
/// assert_eq!(dt.second(), 45);
95+
/// assert_eq!(dt.millisecond(), 123);
96+
/// assert_eq!(dt.microsecond(), 456);
97+
/// assert_eq!(dt.nanosecond(), 789);
98+
/// ```
99+
///
100+
/// ### DateTime arithmetic
101+
///
102+
/// ```rust
103+
/// use temporal_rs::{PlainDateTime, Duration};
104+
/// use core::str::FromStr;
105+
///
106+
/// let dt = PlainDateTime::from_str("2024-01-15T12:00:00").unwrap();
107+
///
108+
/// // Add duration
109+
/// let later = dt.add(&Duration::from_str("P1M2DT3H4M").unwrap(), None).unwrap();
110+
/// assert_eq!(later.month(), 2);
111+
/// assert_eq!(later.day(), 17);
112+
/// assert_eq!(later.hour(), 15);
113+
/// assert_eq!(later.minute(), 4);
114+
///
115+
/// // Calculate difference
116+
/// let earlier = PlainDateTime::from_str("2024-01-10T10:30:00").unwrap();
117+
/// let duration = earlier.until(&dt, Default::default()).unwrap();
118+
/// assert_eq!(duration.days(), 5);
119+
/// assert_eq!(duration.hours(), 1);
120+
/// assert_eq!(duration.minutes(), 30);
121+
/// ```
122+
///
123+
/// ### Working with partial fields
124+
///
125+
/// ```rust
126+
/// use temporal_rs::{PlainDateTime, partial::{PartialDateTime, PartialDate, PartialTime}};
127+
/// use core::str::FromStr;
128+
///
129+
/// let dt = PlainDateTime::from_str("2024-01-15T12:30:45").unwrap();
130+
///
131+
/// // Change only the hour
132+
/// let partial = PartialDateTime::new()
133+
/// .with_partial_time(PartialTime::new().with_hour(Some(18)));
134+
/// let modified = dt.with(partial, None).unwrap();
135+
/// assert_eq!(modified.hour(), 18);
136+
/// assert_eq!(modified.minute(), 30); // unchanged
137+
/// assert_eq!(modified.second(), 45); // unchanged
138+
/// ```
139+
///
140+
/// ### Converting to other types
141+
///
142+
/// ```rust
143+
/// use temporal_rs::{PlainDateTime, PlainTime};
144+
/// use core::str::FromStr;
145+
///
146+
/// let dt = PlainDateTime::from_str("2024-03-15T14:30:45").unwrap();
147+
///
148+
/// // Extract date component
149+
/// let date = dt.to_plain_date().unwrap();
150+
/// assert_eq!(date.year(), 2024);
151+
/// assert_eq!(date.month(), 3);
152+
/// assert_eq!(date.day(), 15);
153+
///
154+
/// // Extract time component
155+
/// let time = dt.to_plain_time().unwrap();
156+
/// assert_eq!(time.hour(), 14);
157+
/// assert_eq!(time.minute(), 30);
158+
/// assert_eq!(time.second(), 45);
159+
/// ```
63160
///
64161
/// ## Reference
65162
///

src/builtins/core/duration.rs

Lines changed: 146 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,152 @@ impl PartialDuration {
6868

6969
/// The native Rust implementation of `Temporal.Duration`.
7070
///
71-
/// `Duration` is made up of a `DateDuration` and `TimeDuration` as primarily
72-
/// defined by Abtract Operation 7.5.1-5.
71+
/// Represents a span of time such as "2 hours and 30 minutes" or "3 years, 2 months".
72+
/// Unlike `Instant` which represents a specific moment in time, Duration represents
73+
/// the amount of time between two moments.
74+
///
75+
/// A Duration consists of two categories of components:
76+
/// - Date components: years, months, weeks, and days
77+
/// - Time components: hours, minutes, seconds, and subsecond units (nanosecond precision)
78+
///
79+
/// Note that date arithmetic can be complex. For example, adding "1 month" to January 31st
80+
/// could result in February 28th (non-leap year), February 29th (leap year), or March 3rd
81+
/// (if you overflow February), depending on the calendar system and overflow handling.
82+
///
83+
/// ## Examples
84+
///
85+
/// ### Creating durations
86+
///
87+
/// ```rust
88+
/// use temporal_rs::Duration;
89+
///
90+
/// // Create a duration with specific components
91+
/// let vacation_duration = Duration::new(
92+
/// 0, 0, 2, 3, // 2 weeks and 3 days
93+
/// 0, 0, 0, // no time components
94+
/// 0, 0, 0 // no subsecond components
95+
/// ).unwrap();
96+
///
97+
/// assert_eq!(vacation_duration.weeks(), 2);
98+
/// assert_eq!(vacation_duration.days(), 3);
99+
/// ```
100+
///
101+
/// ### Parsing ISO 8601 duration strings
102+
///
103+
/// ```rust
104+
/// use temporal_rs::Duration;
105+
/// use core::str::FromStr;
106+
///
107+
/// // Complex duration with multiple components
108+
/// let complex = Duration::from_str("P1Y2M3DT4H5M6.789S").unwrap();
109+
/// assert_eq!(complex.years(), 1);
110+
/// assert_eq!(complex.months(), 2);
111+
/// assert_eq!(complex.days(), 3);
112+
/// assert_eq!(complex.hours(), 4);
113+
/// assert_eq!(complex.minutes(), 5);
114+
/// assert_eq!(complex.seconds(), 6);
115+
///
116+
/// // Time-only duration
117+
/// let movie_length = Duration::from_str("PT2H30M").unwrap();
118+
/// assert_eq!(movie_length.hours(), 2);
119+
/// assert_eq!(movie_length.minutes(), 30);
120+
///
121+
/// // Negative durations
122+
/// let negative = Duration::from_str("-P1D").unwrap();
123+
/// assert_eq!(negative.days(), -1);
124+
/// ```
125+
///
126+
/// ### Duration arithmetic
127+
///
128+
/// ```rust
129+
/// use temporal_rs::Duration;
130+
/// use core::str::FromStr;
131+
///
132+
/// let commute_time = Duration::from_str("PT45M").unwrap();
133+
/// let lunch_break = Duration::from_str("PT1H").unwrap();
134+
///
135+
/// // Add durations together
136+
/// let total_time = commute_time.add(&lunch_break).unwrap();
137+
/// assert_eq!(total_time.hours(), 1); // Results in 1 hour 45 minutes
138+
/// assert_eq!(total_time.minutes(), 45);
139+
///
140+
/// // Subtract duration components
141+
/// let shortened = lunch_break.subtract(&Duration::from_str("PT15M").unwrap()).unwrap();
142+
/// assert_eq!(shortened.minutes(), 45);
143+
/// ```
144+
///
145+
/// ### Date arithmetic with durations
146+
///
147+
/// ```rust
148+
/// use temporal_rs::{PlainDate, Duration, options::ArithmeticOverflow};
149+
/// use core::str::FromStr;
150+
///
151+
/// // January 31st in different years
152+
/// let jan_31_2023 = PlainDate::try_new_iso(2023, 1, 31).unwrap();
153+
/// let jan_31_2024 = PlainDate::try_new_iso(2024, 1, 31).unwrap(); // leap year
154+
///
155+
/// let one_month = Duration::from_str("P1M").unwrap();
156+
///
157+
/// // Adding 1 month to Jan 31st gives different results:
158+
/// let feb_2023 = jan_31_2023.add(&one_month, Some(ArithmeticOverflow::Constrain)).unwrap();
159+
/// let feb_2024 = jan_31_2024.add(&one_month, Some(ArithmeticOverflow::Constrain)).unwrap();
160+
///
161+
/// // 2023: Jan 31 + 1 month = Feb 28 (no Feb 31st exists)
162+
/// assert_eq!(feb_2023.day(), 28);
163+
/// // 2024: Jan 31 + 1 month = Feb 29 (leap year)
164+
/// assert_eq!(feb_2024.day(), 29);
165+
/// ```
166+
///
167+
/// ### Working with partial durations
168+
///
169+
/// ```rust
170+
/// use temporal_rs::{Duration, partial::PartialDuration};
171+
///
172+
/// let partial = PartialDuration {
173+
/// hours: Some(3),
174+
/// minutes: Some(45),
175+
/// ..Default::default()
176+
/// };
177+
///
178+
/// let duration = Duration::from_partial_duration(partial).unwrap();
179+
/// assert_eq!(duration.hours(), 3);
180+
/// assert_eq!(duration.minutes(), 45);
181+
/// assert_eq!(duration.days(), 0); // other fields default to 0
182+
/// ```
183+
///
184+
/// ### Duration properties
185+
///
186+
/// ```rust
187+
/// use temporal_rs::Duration;
188+
/// use core::str::FromStr;
189+
///
190+
/// let duration = Duration::from_str("P1Y2M3D").unwrap();
191+
///
192+
/// // Check if duration is zero
193+
/// assert!(!duration.is_zero());
194+
///
195+
/// // Get the sign of the duration
196+
/// let sign = duration.sign();
197+
/// // Note: This particular duration has mixed signs which affects the overall sign
198+
///
199+
/// // Get absolute value
200+
/// let abs_duration = duration.abs();
201+
/// assert_eq!(abs_duration.years(), 1);
202+
/// assert_eq!(abs_duration.months(), 2);
203+
/// assert_eq!(abs_duration.days(), 3);
204+
///
205+
/// // Negate duration
206+
/// let negated = duration.negated();
207+
/// assert_eq!(negated.years(), -1);
208+
/// assert_eq!(negated.months(), -2);
209+
/// assert_eq!(negated.days(), -3);
210+
/// ```
211+
///
212+
/// ## Reference
213+
///
214+
/// For more information, see the [MDN documentation][mdn-duration].
215+
///
216+
/// [mdn-duration]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration
73217
#[non_exhaustive]
74218
#[derive(Debug, Clone, Copy, Default)]
75219
pub struct Duration {

0 commit comments

Comments
 (0)