@@ -514,8 +514,55 @@ 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 : Option < Disambiguation > ,
521+ offset_option : Option < OffsetDisambiguation > ,
522+ overflow : Option < ArithmeticOverflow > ,
523+ provider : & impl TimeZoneProvider ,
524+ ) -> TemporalResult < Self > {
525+ let overflow = overflow. unwrap_or_default ( ) ;
526+ let disambiguation = disambiguation. unwrap_or_default ( ) ;
527+ let offset_option = offset_option. unwrap_or ( OffsetDisambiguation :: Reject ) ;
528+
529+ let iso_date_time = self . tz . get_iso_datetime_for ( & self . instant , provider) ?;
530+ let plain_date_time = PlainDateTime :: new_unchecked ( iso_date_time, self . calendar . clone ( ) ) ;
531+
532+ // 23. Let dateTimeResult be ? InterpretTemporalDateTimeFields(calendar, fields, overflow).
533+ let result_date = self . calendar . date_from_partial (
534+ & partial. date . with_fallback_datetime ( & plain_date_time) ?,
535+ overflow,
536+ ) ?;
537+
538+ let time = iso_date_time. time . with ( partial. time , overflow) ?;
539+
540+ // 24. Let newOffsetNanoseconds be ! ParseDateTimeUTCOffset(fields.[[OffsetString]]).
541+ let original_offset = self . offset_nanoseconds_with_provider ( provider) ?;
542+ let new_offset_nanos = partial
543+ . offset
544+ . map ( |offset| i64:: from ( offset. 0 ) * 60_000_000_000 )
545+ . or ( Some ( original_offset) ) ;
546+
547+ // 25. Let epochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[ISODate]], dateTimeResult.[[Time]], option, newOffsetNanoseconds, timeZone, disambiguation, offset, match-exactly).
548+ let epoch_nanos = interpret_isodatetime_offset (
549+ result_date. iso ,
550+ Some ( time) ,
551+ false ,
552+ new_offset_nanos,
553+ & self . tz ,
554+ disambiguation,
555+ offset_option,
556+ true ,
557+ provider,
558+ ) ?;
559+
560+ // 26. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
561+ Ok ( Self :: new_unchecked (
562+ Instant :: from ( epoch_nanos) ,
563+ self . calendar . clone ( ) ,
564+ self . tz . clone ( ) ,
565+ ) )
519566 }
520567
521568 /// Creates a new `ZonedDateTime` from the current `ZonedDateTime`
@@ -1227,7 +1274,9 @@ pub(crate) fn nanoseconds_to_formattable_offset_minutes(
12271274mod tests {
12281275 use super :: ZonedDateTime ;
12291276 use crate :: {
1230- options:: { DifferenceSettings , Disambiguation , OffsetDisambiguation , Unit } ,
1277+ options:: {
1278+ ArithmeticOverflow , DifferenceSettings , Disambiguation , OffsetDisambiguation , Unit ,
1279+ } ,
12311280 partial:: { PartialDate , PartialTime , PartialZonedDateTime } ,
12321281 time:: EpochNanoseconds ,
12331282 tzdb:: FsTzdbProvider ,
@@ -1366,4 +1415,85 @@ mod tests {
13661415 assert_eq ! ( diff. microseconds( ) , 0 ) ;
13671416 assert_eq ! ( diff. nanoseconds( ) , 0 ) ;
13681417 }
1418+
1419+ // overflow-reject-throws.js
1420+ #[ test]
1421+ fn overflow_reject_throws ( ) {
1422+ let provider = & FsTzdbProvider :: default ( ) ;
1423+
1424+ let zdt =
1425+ ZonedDateTime :: try_new ( 217178610123456789 , Calendar :: default ( ) , TimeZone :: default ( ) )
1426+ . unwrap ( ) ;
1427+
1428+ let overflow = ArithmeticOverflow :: Reject ;
1429+
1430+ let result_1 = zdt. with (
1431+ PartialZonedDateTime {
1432+ date : PartialDate {
1433+ month : Some ( 29 ) ,
1434+ ..Default :: default ( )
1435+ } ,
1436+ time : PartialTime :: default ( ) ,
1437+ offset : None ,
1438+ timezone : None ,
1439+ } ,
1440+ None ,
1441+ None ,
1442+ Some ( overflow) ,
1443+ provider,
1444+ ) ;
1445+
1446+ let result_2 = zdt. with (
1447+ PartialZonedDateTime {
1448+ date : PartialDate {
1449+ day : Some ( 31 ) ,
1450+ ..Default :: default ( )
1451+ } ,
1452+ time : PartialTime :: default ( ) ,
1453+ offset : None ,
1454+ timezone : None ,
1455+ } ,
1456+ None ,
1457+ None ,
1458+ Some ( overflow) ,
1459+ provider,
1460+ ) ;
1461+
1462+ let result_3 = zdt. with (
1463+ PartialZonedDateTime {
1464+ date : PartialDate :: default ( ) ,
1465+ time : PartialTime {
1466+ hour : Some ( 29 ) ,
1467+ ..Default :: default ( )
1468+ } ,
1469+ offset : None ,
1470+ timezone : None ,
1471+ } ,
1472+ None ,
1473+ None ,
1474+ Some ( overflow) ,
1475+ provider,
1476+ ) ;
1477+
1478+ let result_4 = zdt. with (
1479+ PartialZonedDateTime {
1480+ date : PartialDate :: default ( ) ,
1481+ time : PartialTime {
1482+ nanosecond : Some ( 9000 ) ,
1483+ ..Default :: default ( )
1484+ } ,
1485+ offset : None ,
1486+ timezone : None ,
1487+ } ,
1488+ None ,
1489+ None ,
1490+ Some ( overflow) ,
1491+ provider,
1492+ ) ;
1493+
1494+ assert ! ( result_1. is_err( ) ) ;
1495+ assert ! ( result_2. is_err( ) ) ;
1496+ assert ! ( result_3. is_err( ) ) ;
1497+ assert ! ( result_4. is_err( ) ) ;
1498+ }
13691499}
0 commit comments