|
3 | 3 | use crate::{
|
4 | 4 | builtins::core::{
|
5 | 5 | calendar::Calendar, duration::DateDuration, Duration, PlainDateTime, PlainTime,
|
| 6 | + ZonedDateTime, |
6 | 7 | },
|
7 | 8 | iso::{IsoDate, IsoDateTime, IsoTime},
|
8 | 9 | options::{
|
9 |
| - ArithmeticOverflow, DifferenceOperation, DifferenceSettings, DisplayCalendar, |
10 |
| - ResolvedRoundingOptions, TemporalUnit, UnitGroup, |
| 10 | + ArithmeticOverflow, DifferenceOperation, DifferenceSettings, Disambiguation, |
| 11 | + DisplayCalendar, ResolvedRoundingOptions, TemporalUnit, UnitGroup, |
11 | 12 | },
|
12 | 13 | parsers::{parse_date_time, IxdtfStringBuilder},
|
13 | 14 | primitive::FiniteF64,
|
14 |
| - provider::NeverProvider, |
| 15 | + provider::{NeverProvider, TimeZoneProvider}, |
15 | 16 | MonthCode, TemporalError, TemporalResult, TemporalUnwrap, TimeZone,
|
16 | 17 | };
|
17 | 18 | use alloc::{format, string::String};
|
@@ -666,8 +667,50 @@ impl PlainDate {
|
666 | 667 | .with_calendar(self.calendar.identifier(), display_calendar)
|
667 | 668 | .build()
|
668 | 669 | }
|
669 |
| -} |
670 | 670 |
|
| 671 | + #[inline] |
| 672 | + pub fn to_zoned_date_time_with_provider( |
| 673 | + &self, |
| 674 | + tz: TimeZone, |
| 675 | + plain_time: Option<PlainTime>, |
| 676 | + provider: &impl TimeZoneProvider, |
| 677 | + ) -> TemporalResult<ZonedDateTime> { |
| 678 | + // 1. Let temporalDate be the this value. |
| 679 | + // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). |
| 680 | + // 3. If item is an Object, then |
| 681 | + // a. Let timeZoneLike be ? Get(item, "timeZone"). |
| 682 | + // b. If timeZoneLike is undefined, then |
| 683 | + // i. Let timeZone be ? ToTemporalTimeZoneIdentifier(item). |
| 684 | + // ii. Let temporalTime be undefined. |
| 685 | + // c. Else, |
| 686 | + // i. Let timeZone be ? ToTemporalTimeZoneIdentifier(timeZoneLike). |
| 687 | + // ii. Let temporalTime be ? Get(item, "plainTime"). |
| 688 | + // 4. Else, |
| 689 | + // a. Let timeZone be ? ToTemporalTimeZoneIdentifier(item). |
| 690 | + // b. Let temporalTime be undefined. |
| 691 | + |
| 692 | + // 5. If temporalTime is undefined, then |
| 693 | + // a. Let epochNs be ? GetStartOfDay(timeZone, temporalDate.[[ISODate]]). |
| 694 | + // 6. Else, |
| 695 | + // a. Set temporalTime to ? ToTemporalTime(temporalTime). |
| 696 | + // b. Let isoDateTime be CombineISODateAndTimeRecord(temporalDate.[[ISODate]], temporalTime.[[Time]]). |
| 697 | + // c. If ISODateTimeWithinLimits(isoDateTime) is false, throw a RangeError exception. |
| 698 | + // d. Let epochNs be ? GetEpochNanosecondsFor(timeZone, isoDateTime, compatible). |
| 699 | + let epoch_ns = if let Some(time) = plain_time { |
| 700 | + let result_iso = IsoDateTime::new(self.iso, time.iso); |
| 701 | + |
| 702 | + tz.get_epoch_nanoseconds_for( |
| 703 | + result_iso.unwrap_or_default(), |
| 704 | + Disambiguation::Compatible, |
| 705 | + provider, |
| 706 | + )? |
| 707 | + } else { |
| 708 | + tz.get_start_of_day(&self.iso, provider)? |
| 709 | + }; |
| 710 | + // 7. Return ! CreateTemporalZonedDateTime(epochNs, timeZone, temporalDate.[[Calendar]]). |
| 711 | + ZonedDateTime::try_new(epoch_ns.0, self.calendar.clone(), tz) |
| 712 | + } |
| 713 | +} |
671 | 714 | // ==== Trait impls ====
|
672 | 715 |
|
673 | 716 | impl From<PlainDateTime> for PlainDate {
|
@@ -950,6 +993,28 @@ mod tests {
|
950 | 993 | assert_eq!(with_day.day(), 17);
|
951 | 994 | }
|
952 | 995 |
|
| 996 | + // test toZonedDateTime |
| 997 | + #[cfg(feature = "tzdb")] |
| 998 | + #[test] |
| 999 | + fn to_zoned_date_time() { |
| 1000 | + use crate::tzdb::FsTzdbProvider; |
| 1001 | + let date = PlainDate::from_str("2020-01-01").unwrap(); |
| 1002 | + let tz = TimeZone::try_from_str("UTC").unwrap(); |
| 1003 | + let provider = &FsTzdbProvider::default(); |
| 1004 | + let zdt = date |
| 1005 | + .to_zoned_date_time_with_provider(tz, None, provider) |
| 1006 | + .unwrap(); |
| 1007 | + assert_eq!(zdt.year_with_provider(provider).unwrap(), 2020); |
| 1008 | + assert_eq!(zdt.month_with_provider(provider).unwrap(), 1); |
| 1009 | + assert_eq!(zdt.day_with_provider(provider).unwrap(), 1); |
| 1010 | + assert_eq!(zdt.hour_with_provider(provider).unwrap(), 0); |
| 1011 | + assert_eq!(zdt.minute_with_provider(provider).unwrap(), 0); |
| 1012 | + assert_eq!(zdt.second_with_provider(provider).unwrap(), 0); |
| 1013 | + assert_eq!(zdt.millisecond_with_provider(provider).unwrap(), 0); |
| 1014 | + assert_eq!(zdt.microsecond_with_provider(provider).unwrap(), 0); |
| 1015 | + assert_eq!(zdt.nanosecond_with_provider(provider).unwrap(), 0); |
| 1016 | + } |
| 1017 | + |
953 | 1018 | // test262/test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js
|
954 | 1019 | #[test]
|
955 | 1020 | fn invalid_strings() {
|
|
0 commit comments