Skip to content

Commit 9baaaa4

Browse files
committed
Add accessor methods to ZonedDateTime + organization
1 parent 454d1a8 commit 9baaaa4

File tree

2 files changed

+229
-7
lines changed

2 files changed

+229
-7
lines changed

src/components/duration/normalized.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl NormalizedTimeDuration {
7474

7575
// TODO: Potentially, update divisor to u64?
7676
/// `Divide the NormalizedTimeDuraiton` by a divisor.
77-
pub(super) fn divide(&self, divisor: i64) -> i128 {
77+
pub(crate) fn divide(&self, divisor: i64) -> i128 {
7878
// TODO: Validate.
7979
self.0 / i128::from(divisor)
8080
}

src/components/zoneddatetime.rs

Lines changed: 228 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
use tinystr::TinyAsciiStr;
44

55
use crate::{
6-
components::{calendar::Calendar, tz::TimeZone, Instant},
7-
iso::IsoDateTime,
6+
components::{calendar::Calendar, duration::normalized::NormalizedTimeDuration, tz::TimeZone, Instant},
7+
iso::{IsoDate, IsoDateTime},
88
options::{ArithmeticOverflow, Disambiguation},
99
Sign, TemporalError, TemporalResult,
1010
};
@@ -78,7 +78,7 @@ impl ZonedDateTime {
7878
.with_message("Intermediate ISO datetime was not within a valid range."));
7979
}
8080
// 6. Let intermediateNs be ! GetEpochNanosecondsFor(timeZone, intermediateDateTime, compatible).
81-
let intermediate_ns = self.tz().get_epoch_nanoseconds_for(
81+
let intermediate_ns = self.timezone().get_epoch_nanoseconds_for(
8282
intermediate,
8383
Disambiguation::Compatible,
8484
provider,
@@ -113,7 +113,7 @@ impl ZonedDateTime {
113113
.add_as_instant(duration, overflow, provider)?
114114
.epoch_nanos;
115115
// 9. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
116-
Self::try_new(epoch_ns, self.calendar().clone(), self.tz().clone())
116+
Self::try_new(epoch_ns, self.calendar().clone(), self.timezone().clone())
117117
}
118118
}
119119

@@ -137,7 +137,7 @@ impl ZonedDateTime {
137137
/// Returns `ZonedDateTime`'s `TimeZone` slot.
138138
#[inline]
139139
#[must_use]
140-
pub fn tz(&self) -> &TimeZone {
140+
pub fn timezone(&self) -> &TimeZone {
141141
&self.tz
142142
}
143143

@@ -166,7 +166,7 @@ impl ZonedDateTime {
166166
}
167167
}
168168

169-
// ===== TzProvider APIs for ZonedDateTime =====
169+
// ===== Experimental TZ_PROVIDER accessor implementations =====
170170

171171
#[cfg(feature = "experimental")]
172172
impl ZonedDateTime {
@@ -240,7 +240,103 @@ impl ZonedDateTime {
240240

241241
self.millisecond_with_provider(provider.deref())
242242
}
243+
}
244+
245+
// ==== Experimental TZ_PROVIDER calendar method implementations ====
246+
247+
#[cfg(feature = "experimental")]
248+
impl ZonedDateTime {
249+
pub fn era(&self) -> TemporalResult<Option<TinyAsciiStr<16>>> {
250+
let provider = TZ_PROVIDER
251+
.lock()
252+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
253+
self.era_with_provider(provider.deref())
254+
}
255+
256+
pub fn era_year(&self) -> TemporalResult<Option<i32>> {
257+
let provider = TZ_PROVIDER
258+
.lock()
259+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
260+
self.era_year_with_provider(provider.deref())
261+
}
262+
263+
/// Returns the calendar day of week value.
264+
pub fn day_of_week(&self) -> TemporalResult<u16> {
265+
let provider = TZ_PROVIDER
266+
.lock()
267+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
268+
self.day_of_week_with_provider(provider.deref())
269+
}
270+
271+
/// Returns the calendar day of year value.
272+
pub fn day_of_year(&self) -> TemporalResult<u16> {
273+
let provider = TZ_PROVIDER
274+
.lock()
275+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
276+
self.day_of_year_with_provider(provider.deref())
277+
}
278+
279+
/// Returns the calendar week of year value.
280+
pub fn week_of_year(&self) -> TemporalResult<Option<u16>> {
281+
let provider = TZ_PROVIDER
282+
.lock()
283+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
284+
self.week_of_year_with_provider(provider.deref())
285+
}
286+
287+
/// Returns the calendar year of week value.
288+
pub fn year_of_week(&self) -> TemporalResult<Option<i32>> {
289+
let provider = TZ_PROVIDER
290+
.lock()
291+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
292+
self.year_of_week_with_provider(provider.deref())
293+
}
294+
295+
/// Returns the calendar days in week value.
296+
pub fn days_in_week(&self) -> TemporalResult<u16> {
297+
let provider = TZ_PROVIDER
298+
.lock()
299+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
300+
self.days_in_week_with_provider(provider.deref())
301+
}
302+
303+
/// Returns the calendar days in month value.
304+
pub fn days_in_month(&self) -> TemporalResult<u16> {
305+
let provider = TZ_PROVIDER
306+
.lock()
307+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
308+
self.days_in_month_with_provider(provider.deref())
309+
}
310+
311+
/// Returns the calendar days in year value.
312+
pub fn days_in_year(&self) -> TemporalResult<u16> {
313+
let provider = TZ_PROVIDER
314+
.lock()
315+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
316+
self.days_in_year_with_provider(provider.deref())
317+
}
318+
319+
/// Returns the calendar months in year value.
320+
pub fn months_in_year(&self) -> TemporalResult<u16> {
321+
let provider = TZ_PROVIDER
322+
.lock()
323+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
324+
self.months_in_year_with_provider(provider.deref())
325+
}
243326

327+
/// Returns returns whether the date in a leap year for the given calendar.
328+
pub fn in_leap_year(&self) -> TemporalResult<bool> {
329+
let provider = TZ_PROVIDER
330+
.lock()
331+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
332+
self.in_leap_year_with_provider(provider.deref())
333+
}
334+
}
335+
336+
// ==== Experimental TZ_PROVIDER method implementations ====
337+
338+
#[cfg(feature = "experimental")]
339+
impl ZonedDateTime {
244340
pub fn add(
245341
&self,
246342
duration: &Duration,
@@ -270,9 +366,44 @@ impl ZonedDateTime {
270366
overflow.unwrap_or(ArithmeticOverflow::Constrain),
271367
provider.deref(),
272368
)
369+
273370
}
274371
}
275372

373+
// ==== HoursInDay accessor method implementation ====
374+
375+
impl ZonedDateTime {
376+
#[cfg(feature = "experimental")]
377+
pub fn hours_in_day(&self) -> TemporalResult<u8> {
378+
let provider = TZ_PROVIDER
379+
.lock()
380+
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
381+
self.hours_in_day_with_provider(provider.deref())
382+
}
383+
384+
pub fn hours_in_day_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<u8> {
385+
// 1-3. Is engine specific steps
386+
// 4. Let isoDateTime be GetISODateTimeFor(timeZone, zonedDateTime.[[EpochNanoseconds]]).
387+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
388+
// 5. Let today be isoDateTime.[[ISODate]].
389+
let today = iso.date;
390+
// 6. Let tomorrow be BalanceISODate(today.[[Year]], today.[[Month]], today.[[Day]] + 1).
391+
let tomorrow = IsoDate::balance(today.year, today.month.into(), i32::from(today.day + 1));
392+
// 7. Let todayNs be ? GetStartOfDay(timeZone, today).
393+
let today_ns = self.tz.get_start_of_day(&today, provider)?;
394+
// 8. Let tomorrowNs be ? GetStartOfDay(timeZone, tomorrow).
395+
let tomorrow_ns = self.tz.get_start_of_day(&tomorrow, provider)?;
396+
// 9. Let diff be TimeDurationFromEpochNanosecondsDifference(tomorrowNs, todayNs).
397+
let diff = NormalizedTimeDuration::from_nanosecond_difference(tomorrow_ns, today_ns)?;
398+
// NOTE: The below should be safe as today_ns and tomorrow_ns should be at most 25 hours.
399+
// TODO: Tests for the below cast.
400+
// 10. Return 𝔽(TotalTimeDuration(diff, hour)).
401+
Ok(diff.divide(60_000_000_000) as u8)
402+
}
403+
}
404+
405+
// ==== Core accessor methods ====
406+
276407
impl ZonedDateTime {
277408
/// Returns the `year` value for this `ZonedDateTime`.
278409
#[inline]
@@ -341,7 +472,98 @@ impl ZonedDateTime {
341472
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
342473
Ok(iso.time.nanosecond)
343474
}
475+
}
476+
477+
// ==== Core calendar method implementations ====
478+
479+
impl ZonedDateTime {
480+
pub fn era_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<Option<TinyAsciiStr<16>>> {
481+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
482+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
483+
self.calendar.era(&CalendarDateLike::DateTime(&pdt))
484+
}
485+
486+
pub fn era_year_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<Option<i32>> {
487+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
488+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
489+
self.calendar.era_year(&CalendarDateLike::DateTime(&pdt))
344490

491+
}
492+
493+
/// Returns the calendar day of week value.
494+
pub fn day_of_week_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<u16> {
495+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
496+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
497+
self.calendar.day_of_week(&CalendarDateLike::DateTime(&pdt))
498+
499+
}
500+
501+
/// Returns the calendar day of year value.
502+
pub fn day_of_year_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<u16> {
503+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
504+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
505+
self.calendar.day_of_year(&CalendarDateLike::DateTime(&pdt))
506+
}
507+
508+
/// Returns the calendar week of year value.
509+
pub fn week_of_year_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<Option<u16>> {
510+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
511+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
512+
self.calendar.week_of_year(&CalendarDateLike::DateTime(&pdt))
513+
514+
}
515+
516+
/// Returns the calendar year of week value.
517+
pub fn year_of_week_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<Option<i32>> {
518+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
519+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
520+
self.calendar.year_of_week(&CalendarDateLike::DateTime(&pdt))
521+
522+
}
523+
524+
/// Returns the calendar days in week value.
525+
pub fn days_in_week_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<u16> {
526+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
527+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
528+
self.calendar.days_in_week(&CalendarDateLike::DateTime(&pdt))
529+
530+
}
531+
532+
/// Returns the calendar days in month value.
533+
pub fn days_in_month_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<u16> {
534+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
535+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
536+
self.calendar.days_in_month(&CalendarDateLike::DateTime(&pdt))
537+
538+
}
539+
540+
/// Returns the calendar days in year value.
541+
pub fn days_in_year_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<u16> {
542+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
543+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
544+
self.calendar.days_in_year(&CalendarDateLike::DateTime(&pdt))
545+
}
546+
547+
/// Returns the calendar months in year value.
548+
pub fn months_in_year_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<u16> {
549+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
550+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
551+
self.calendar.months_in_year(&CalendarDateLike::DateTime(&pdt))
552+
553+
}
554+
555+
/// Returns returns whether the date in a leap year for the given calendar.
556+
pub fn in_leap_year_with_provider(&self, provider: &impl TzProvider) -> TemporalResult<bool> {
557+
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
558+
let pdt = PlainDateTime::new_unchecked(iso, self.calendar.clone());
559+
self.calendar.in_leap_year(&CalendarDateLike::DateTime(&pdt))
560+
}
561+
562+
}
563+
564+
// ==== Core method implementations ====
565+
566+
impl ZonedDateTime {
345567
pub fn add_with_provider(
346568
&self,
347569
duration: &Duration,

0 commit comments

Comments
 (0)