@@ -8,6 +8,7 @@ use tinystr::TinyAsciiStr;
8
8
use crate :: {
9
9
components:: {
10
10
calendar:: CalendarDateLike ,
11
+ duration:: normalized:: NormalizedTimeDuration ,
11
12
tz:: { parse_offset, TzProvider } ,
12
13
EpochNanoseconds ,
13
14
} ,
@@ -240,7 +241,7 @@ impl ZonedDateTime {
240
241
}
241
242
}
242
243
243
- // ===== TzProvider APIs for ZonedDateTime =====
244
+ // ===== Experimental TZ_PROVIDER accessor implementations =====
244
245
245
246
#[ cfg( feature = "experimental" ) ]
246
247
impl ZonedDateTime {
@@ -314,7 +315,103 @@ impl ZonedDateTime {
314
315
315
316
self . millisecond_with_provider ( provider. deref ( ) )
316
317
}
318
+ }
319
+
320
+ // ==== Experimental TZ_PROVIDER calendar method implementations ====
321
+
322
+ #[ cfg( feature = "experimental" ) ]
323
+ impl ZonedDateTime {
324
+ pub fn era ( & self ) -> TemporalResult < Option < TinyAsciiStr < 16 > > > {
325
+ let provider = TZ_PROVIDER
326
+ . lock ( )
327
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
328
+ self . era_with_provider ( provider. deref ( ) )
329
+ }
330
+
331
+ pub fn era_year ( & self ) -> TemporalResult < Option < i32 > > {
332
+ let provider = TZ_PROVIDER
333
+ . lock ( )
334
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
335
+ self . era_year_with_provider ( provider. deref ( ) )
336
+ }
337
+
338
+ /// Returns the calendar day of week value.
339
+ pub fn day_of_week ( & self ) -> TemporalResult < u16 > {
340
+ let provider = TZ_PROVIDER
341
+ . lock ( )
342
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
343
+ self . day_of_week_with_provider ( provider. deref ( ) )
344
+ }
345
+
346
+ /// Returns the calendar day of year value.
347
+ pub fn day_of_year ( & self ) -> TemporalResult < u16 > {
348
+ let provider = TZ_PROVIDER
349
+ . lock ( )
350
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
351
+ self . day_of_year_with_provider ( provider. deref ( ) )
352
+ }
353
+
354
+ /// Returns the calendar week of year value.
355
+ pub fn week_of_year ( & self ) -> TemporalResult < Option < u16 > > {
356
+ let provider = TZ_PROVIDER
357
+ . lock ( )
358
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
359
+ self . week_of_year_with_provider ( provider. deref ( ) )
360
+ }
361
+
362
+ /// Returns the calendar year of week value.
363
+ pub fn year_of_week ( & self ) -> TemporalResult < Option < i32 > > {
364
+ let provider = TZ_PROVIDER
365
+ . lock ( )
366
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
367
+ self . year_of_week_with_provider ( provider. deref ( ) )
368
+ }
369
+
370
+ /// Returns the calendar days in week value.
371
+ pub fn days_in_week ( & self ) -> TemporalResult < u16 > {
372
+ let provider = TZ_PROVIDER
373
+ . lock ( )
374
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
375
+ self . days_in_week_with_provider ( provider. deref ( ) )
376
+ }
377
+
378
+ /// Returns the calendar days in month value.
379
+ pub fn days_in_month ( & self ) -> TemporalResult < u16 > {
380
+ let provider = TZ_PROVIDER
381
+ . lock ( )
382
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
383
+ self . days_in_month_with_provider ( provider. deref ( ) )
384
+ }
385
+
386
+ /// Returns the calendar days in year value.
387
+ pub fn days_in_year ( & self ) -> TemporalResult < u16 > {
388
+ let provider = TZ_PROVIDER
389
+ . lock ( )
390
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
391
+ self . days_in_year_with_provider ( provider. deref ( ) )
392
+ }
393
+
394
+ /// Returns the calendar months in year value.
395
+ pub fn months_in_year ( & self ) -> TemporalResult < u16 > {
396
+ let provider = TZ_PROVIDER
397
+ . lock ( )
398
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
399
+ self . months_in_year_with_provider ( provider. deref ( ) )
400
+ }
401
+
402
+ /// Returns returns whether the date in a leap year for the given calendar.
403
+ pub fn in_leap_year ( & self ) -> TemporalResult < bool > {
404
+ let provider = TZ_PROVIDER
405
+ . lock ( )
406
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
407
+ self . in_leap_year_with_provider ( provider. deref ( ) )
408
+ }
409
+ }
410
+
411
+ // ==== Experimental TZ_PROVIDER method implementations ====
317
412
413
+ #[ cfg( feature = "experimental" ) ]
414
+ impl ZonedDateTime {
318
415
pub fn add (
319
416
& self ,
320
417
duration : & Duration ,
@@ -358,6 +455,40 @@ impl ZonedDateTime {
358
455
}
359
456
}
360
457
458
+ // ==== HoursInDay accessor method implementation ====
459
+
460
+ impl ZonedDateTime {
461
+ #[ cfg( feature = "experimental" ) ]
462
+ pub fn hours_in_day ( & self ) -> TemporalResult < u8 > {
463
+ let provider = TZ_PROVIDER
464
+ . lock ( )
465
+ . map_err ( |_| TemporalError :: general ( "Unable to acquire lock" ) ) ?;
466
+ self . hours_in_day_with_provider ( provider. deref ( ) )
467
+ }
468
+
469
+ pub fn hours_in_day_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < u8 > {
470
+ // 1-3. Is engine specific steps
471
+ // 4. Let isoDateTime be GetISODateTimeFor(timeZone, zonedDateTime.[[EpochNanoseconds]]).
472
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
473
+ // 5. Let today be isoDateTime.[[ISODate]].
474
+ let today = iso. date ;
475
+ // 6. Let tomorrow be BalanceISODate(today.[[Year]], today.[[Month]], today.[[Day]] + 1).
476
+ let tomorrow = IsoDate :: balance ( today. year , today. month . into ( ) , i32:: from ( today. day + 1 ) ) ;
477
+ // 7. Let todayNs be ? GetStartOfDay(timeZone, today).
478
+ let today_ns = self . tz . get_start_of_day ( & today, provider) ?;
479
+ // 8. Let tomorrowNs be ? GetStartOfDay(timeZone, tomorrow).
480
+ let tomorrow_ns = self . tz . get_start_of_day ( & tomorrow, provider) ?;
481
+ // 9. Let diff be TimeDurationFromEpochNanosecondsDifference(tomorrowNs, todayNs).
482
+ let diff = NormalizedTimeDuration :: from_nanosecond_difference ( tomorrow_ns. 0 , today_ns. 0 ) ?;
483
+ // NOTE: The below should be safe as today_ns and tomorrow_ns should be at most 25 hours.
484
+ // TODO: Tests for the below cast.
485
+ // 10. Return 𝔽(TotalTimeDuration(diff, hour)).
486
+ Ok ( diff. divide ( 60_000_000_000 ) as u8 )
487
+ }
488
+ }
489
+
490
+ // ==== Core accessor methods ====
491
+
361
492
impl ZonedDateTime {
362
493
/// Returns the `year` value for this `ZonedDateTime`.
363
494
#[ inline]
@@ -426,7 +557,109 @@ impl ZonedDateTime {
426
557
let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
427
558
Ok ( iso. time . nanosecond )
428
559
}
560
+ }
561
+
562
+ // ==== Core calendar method implementations ====
429
563
564
+ impl ZonedDateTime {
565
+ pub fn era_with_provider (
566
+ & self ,
567
+ provider : & impl TzProvider ,
568
+ ) -> TemporalResult < Option < TinyAsciiStr < 16 > > > {
569
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
570
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
571
+ self . calendar . era ( & CalendarDateLike :: DateTime ( & pdt) )
572
+ }
573
+
574
+ pub fn era_year_with_provider (
575
+ & self ,
576
+ provider : & impl TzProvider ,
577
+ ) -> TemporalResult < Option < i32 > > {
578
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
579
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
580
+ self . calendar . era_year ( & CalendarDateLike :: DateTime ( & pdt) )
581
+ }
582
+
583
+ /// Returns the calendar day of week value.
584
+ pub fn day_of_week_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < u16 > {
585
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
586
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
587
+ self . calendar . day_of_week ( & CalendarDateLike :: DateTime ( & pdt) )
588
+ }
589
+
590
+ /// Returns the calendar day of year value.
591
+ pub fn day_of_year_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < u16 > {
592
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
593
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
594
+ self . calendar . day_of_year ( & CalendarDateLike :: DateTime ( & pdt) )
595
+ }
596
+
597
+ /// Returns the calendar week of year value.
598
+ pub fn week_of_year_with_provider (
599
+ & self ,
600
+ provider : & impl TzProvider ,
601
+ ) -> TemporalResult < Option < u16 > > {
602
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
603
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
604
+ self . calendar
605
+ . week_of_year ( & CalendarDateLike :: DateTime ( & pdt) )
606
+ }
607
+
608
+ /// Returns the calendar year of week value.
609
+ pub fn year_of_week_with_provider (
610
+ & self ,
611
+ provider : & impl TzProvider ,
612
+ ) -> TemporalResult < Option < i32 > > {
613
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
614
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
615
+ self . calendar
616
+ . year_of_week ( & CalendarDateLike :: DateTime ( & pdt) )
617
+ }
618
+
619
+ /// Returns the calendar days in week value.
620
+ pub fn days_in_week_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < u16 > {
621
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
622
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
623
+ self . calendar
624
+ . days_in_week ( & CalendarDateLike :: DateTime ( & pdt) )
625
+ }
626
+
627
+ /// Returns the calendar days in month value.
628
+ pub fn days_in_month_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < u16 > {
629
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
630
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
631
+ self . calendar
632
+ . days_in_month ( & CalendarDateLike :: DateTime ( & pdt) )
633
+ }
634
+
635
+ /// Returns the calendar days in year value.
636
+ pub fn days_in_year_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < u16 > {
637
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
638
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
639
+ self . calendar
640
+ . days_in_year ( & CalendarDateLike :: DateTime ( & pdt) )
641
+ }
642
+
643
+ /// Returns the calendar months in year value.
644
+ pub fn months_in_year_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < u16 > {
645
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
646
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
647
+ self . calendar
648
+ . months_in_year ( & CalendarDateLike :: DateTime ( & pdt) )
649
+ }
650
+
651
+ /// Returns returns whether the date in a leap year for the given calendar.
652
+ pub fn in_leap_year_with_provider ( & self , provider : & impl TzProvider ) -> TemporalResult < bool > {
653
+ let iso = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
654
+ let pdt = PlainDateTime :: new_unchecked ( iso, self . calendar . clone ( ) ) ;
655
+ self . calendar
656
+ . in_leap_year ( & CalendarDateLike :: DateTime ( & pdt) )
657
+ }
658
+ }
659
+
660
+ // ==== Core method implementations ====
661
+
662
+ impl ZonedDateTime {
430
663
pub fn add_with_provider (
431
664
& self ,
432
665
duration : & Duration ,
0 commit comments