Skip to content

Commit ba73ed6

Browse files
committed
zoneddatetime_with progress
1 parent 2db9b2a commit ba73ed6

2 files changed

Lines changed: 161 additions & 3 deletions

File tree

src/builtins/core/date.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,62 @@ impl PartialDate {
8181
crate::impl_with_fallback_method!(with_fallback_year_month, () PlainYearMonth); // excludes day
8282
crate::impl_with_fallback_method!(with_fallback_date, (with_day: day) PlainDate);
8383
crate::impl_with_fallback_method!(with_fallback_datetime, (with_day:day) PlainDateTime);
84+
crate::impl_with_fallback_method_zoned!(with_fallback_zoneddatetime, (with_day:day), ZonedDateTime);
85+
}
86+
87+
#[doc(hidden)]
88+
#[macro_export]
89+
macro_rules! impl_with_fallback_method_zoned {
90+
($method_name:ident, (with_day: $day:ident), $component_type:ty) => {
91+
pub(crate) fn $method_name(
92+
&self,
93+
fallback: &$component_type,
94+
provider: &impl TimeZoneProvider,
95+
) -> TemporalResult<Self> {
96+
let era = if let Some(era) = self.era {
97+
Some(era)
98+
} else {
99+
let era = fallback.era_with_provider(provider)?;
100+
era.map(|e| {
101+
TinyAsciiStr::<19>::try_from_utf8(e.as_bytes())
102+
.map_err(|e| TemporalError::general(format!("{e}")))
103+
})
104+
.transpose()?
105+
};
84106

85-
// TODO: ZonedDateTime
107+
let fallback_era_year = fallback.era_year_with_provider(provider)?;
108+
let era_year = self
109+
.era_year
110+
.map_or_else(|| fallback_era_year, |ey| Some(ey));
111+
112+
let (month, month_code) = match (self.month, self.month_code) {
113+
(Some(month), Some(mc)) => (Some(month), Some(mc)),
114+
(Some(month), None) => (Some(month), Some(month_to_month_code(month)?)),
115+
(None, Some(mc)) => (Some(mc.to_month_integer()).map(Into::into), Some(mc)),
116+
(None, None) => (
117+
Some(fallback.month_with_provider(provider)?).map(Into::into),
118+
Some(fallback.month_code_with_provider(provider)?),
119+
),
120+
};
121+
122+
#[allow(clippy::needless_update)]
123+
{
124+
Ok(Self {
125+
year: Some(self.year.unwrap_or(fallback.year_with_provider(provider)?)),
126+
month,
127+
month_code,
128+
$day: Some(
129+
self.day
130+
.unwrap_or(fallback.day_with_provider(provider)?.into()),
131+
),
132+
era,
133+
era_year,
134+
calendar: fallback.calendar().clone(),
135+
..Default::default()
136+
})
137+
}
138+
}
139+
};
86140
}
87141

88142
// Use macro to impl fallback methods to avoid having a trait method.

src/builtins/core/zoneddatetime.rs

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,52 @@ impl ZonedDateTime {
514514
self.instant
515515
}
516516

517-
pub fn with(&self, _partial: PartialZonedDateTime) -> TemporalResult<Self> {
518-
Err(TemporalError::general("Not yet implemented"))
517+
pub fn with(
518+
&self,
519+
partial: PartialZonedDateTime,
520+
disambiguation: Disambiguation,
521+
offset_option: OffsetDisambiguation,
522+
overflow: Option<ArithmeticOverflow>,
523+
provider: &impl TimeZoneProvider,
524+
) -> TemporalResult<Self> {
525+
// 23. Let dateTimeResult be ? InterpretTemporalDateTimeFields(calendar, fields, overflow).
526+
let result_date = self.calendar.date_from_partial(
527+
&partial.date.with_fallback_zoneddatetime(self, provider)?,
528+
overflow.unwrap_or(ArithmeticOverflow::Constrain),
529+
)?;
530+
531+
let original_iso = self.tz.get_iso_datetime_for(&self.instant, provider)?.time;
532+
let time = original_iso.with(
533+
partial.time,
534+
overflow.unwrap_or(ArithmeticOverflow::Constrain),
535+
)?;
536+
537+
// 24. Let newOffsetNanoseconds be ! ParseDateTimeUTCOffset(fields.[[OffsetString]]).
538+
let original_offset = self.offset_nanoseconds_with_provider(provider)?;
539+
let new_offset_nanos = partial
540+
.offset
541+
.map(|offset| i64::from(offset.0) * 60_000_000_000)
542+
.or(Some(original_offset));
543+
544+
// 25. Let epochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[ISODate]], dateTimeResult.[[Time]], option, newOffsetNanoseconds, timeZone, disambiguation, offset, match-exactly).
545+
let epoch_nanos = interpret_isodatetime_offset(
546+
result_date.iso,
547+
Some(time),
548+
false,
549+
new_offset_nanos,
550+
&self.tz,
551+
disambiguation,
552+
offset_option,
553+
true,
554+
provider,
555+
)?;
556+
557+
// 26. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
558+
Ok(Self::new_unchecked(
559+
Instant::from(epoch_nanos),
560+
self.calendar.clone(),
561+
self.tz.clone(),
562+
))
519563
}
520564

521565
/// Creates a new `ZonedDateTime` from the current `ZonedDateTime`
@@ -1366,4 +1410,64 @@ mod tests {
13661410
assert_eq!(diff.microseconds(), 0);
13671411
assert_eq!(diff.nanoseconds(), 0);
13681412
}
1413+
1414+
#[test]
1415+
// subclassing_ignored.js
1416+
fn subclassing_ignored() {
1417+
// Javacript
1418+
// TemporalHelpers.checkSubclassingIgnored(
1419+
// Temporal.ZonedDateTime,
1420+
// [10n, "UTC"],
1421+
// "with",
1422+
// [{ year: 2000 }],
1423+
// (result) => {
1424+
// assert.sameValue(result.epochNanoseconds, 946684800_000_000_010n, "epochNanoseconds result");
1425+
// assert.sameValue(result.year, 2000, "year result");
1426+
// assert.sameValue(result.month, 1, "month result");
1427+
// assert.sameValue(result.day, 1, "day result");
1428+
// assert.sameValue(result.hour, 0, "hour result");
1429+
// assert.sameValue(result.minute, 0, "minute result");
1430+
// assert.sameValue(result.second, 0, "second result");
1431+
// assert.sameValue(result.millisecond, 0, "millisecond result");
1432+
// assert.sameValue(result.microsecond, 0, "microsecond result");
1433+
// assert.sameValue(result.nanosecond, 10, "nanosecond result");
1434+
// },
1435+
// );
1436+
1437+
let provider = &FsTzdbProvider::default();
1438+
let zdt = ZonedDateTime::try_new(10_000_000_010, Calendar::default(), TimeZone::default())
1439+
.unwrap();
1440+
1441+
let partial_zdt = PartialZonedDateTime {
1442+
date: PartialDate {
1443+
year: Some(2000),
1444+
..Default::default()
1445+
},
1446+
..Default::default()
1447+
};
1448+
1449+
let result = zdt
1450+
.with(
1451+
partial_zdt,
1452+
Disambiguation::Compatible,
1453+
OffsetDisambiguation::Prefer,
1454+
None,
1455+
provider,
1456+
)
1457+
.unwrap();
1458+
1459+
assert_eq!(
1460+
result.epoch_nanoseconds(),
1461+
&EpochNanoseconds(946684800_000_000_010)
1462+
);
1463+
assert_eq!(result.year_with_provider(provider).unwrap(), 2000);
1464+
assert_eq!(result.month_with_provider(provider).unwrap(), 1);
1465+
assert_eq!(result.day_with_provider(provider).unwrap(), 1);
1466+
assert_eq!(result.hour_with_provider(provider).unwrap(), 0);
1467+
assert_eq!(result.minute_with_provider(provider).unwrap(), 0);
1468+
assert_eq!(result.second_with_provider(provider).unwrap(), 0);
1469+
assert_eq!(result.millisecond_with_provider(provider).unwrap(), 0);
1470+
assert_eq!(result.microsecond_with_provider(provider).unwrap(), 0);
1471+
assert_eq!(result.nanosecond_with_provider(provider).unwrap(), 10);
1472+
}
13691473
}

0 commit comments

Comments
 (0)