@@ -549,13 +549,25 @@ impl PlainDateTime {
549
549
550
550
// Converts a UTF-8 encoded string into a `PlainDateTime`.
551
551
pub fn from_utf8 ( s : & [ u8 ] ) -> TemporalResult < Self > {
552
- let parser = TemporalParser :: new ( ) ;
553
- let parsed = parser. parse_date_time ( core:: str:: from_utf8 ( s) . map_err ( |_| {
554
- TemporalError :: syntax ( ) . with_message ( "Invalid UTF-8 in datetime string" )
555
- } ) ?) ?;
552
+ let parser = TemporalParser :: from_utf8 ( s) ;
553
+ let parsed = parser. parse_date_time ( ) ?;
556
554
557
- let calendar = if let Some ( cal_str) = & parsed. calendar {
558
- Calendar :: try_from_utf8 ( cal_str. as_bytes ( ) ) ?
555
+ let calendar = if let Some ( cal_bytes) = parsed. calendar {
556
+ Calendar :: try_from_utf8 ( & cal_bytes) ?
557
+ } else {
558
+ Calendar :: default ( )
559
+ } ;
560
+
561
+ Ok ( Self :: new_unchecked ( parsed. iso , calendar) )
562
+ }
563
+
564
+ /// Converts a UTF-16 encoded string into a `PlainDateTime`.
565
+ pub fn from_utf16 ( s : & [ u16 ] ) -> TemporalResult < Self > {
566
+ let parser = TemporalParser :: from_utf16 ( s) ;
567
+ let parsed = parser. parse_date_time ( ) ?;
568
+
569
+ let calendar = if let Some ( cal_bytes) = parsed. calendar {
570
+ Calendar :: try_from_utf8 ( & cal_bytes) ?
559
571
} else {
560
572
Calendar :: default ( )
561
573
} ;
@@ -1518,4 +1530,136 @@ mod tests {
1518
1530
"pads 4 decimal places to 9"
1519
1531
) ;
1520
1532
}
1533
+
1534
+ #[ test]
1535
+ fn test_utf16_datetime_parsing ( ) {
1536
+ use alloc:: vec:: Vec ;
1537
+
1538
+ let datetime_str = "2023-05-15T14:30:45.123" ;
1539
+ let datetime_utf16: Vec < u16 > = datetime_str. encode_utf16 ( ) . collect ( ) ;
1540
+
1541
+ // Test UTF-16 parsing
1542
+ let datetime_utf16_result = PlainDateTime :: from_utf16 ( & datetime_utf16) . unwrap ( ) ;
1543
+
1544
+ // Test UTF-8 parsing for comparison
1545
+ let datetime_utf8_result = PlainDateTime :: from_utf8 ( datetime_str. as_bytes ( ) ) . unwrap ( ) ;
1546
+
1547
+ // Compare results
1548
+ assert_eq ! ( datetime_utf16_result. year( ) , datetime_utf8_result. year( ) ) ;
1549
+ assert_eq ! ( datetime_utf16_result. month( ) , datetime_utf8_result. month( ) ) ;
1550
+ assert_eq ! ( datetime_utf16_result. day( ) , datetime_utf8_result. day( ) ) ;
1551
+ assert_eq ! ( datetime_utf16_result. hour( ) , datetime_utf8_result. hour( ) ) ;
1552
+ assert_eq ! (
1553
+ datetime_utf16_result. minute( ) ,
1554
+ datetime_utf8_result. minute( )
1555
+ ) ;
1556
+ assert_eq ! (
1557
+ datetime_utf16_result. second( ) ,
1558
+ datetime_utf8_result. second( )
1559
+ ) ;
1560
+ assert_eq ! (
1561
+ datetime_utf16_result. millisecond( ) ,
1562
+ datetime_utf8_result. millisecond( )
1563
+ ) ;
1564
+
1565
+ // Test specific values
1566
+ assert_eq ! ( datetime_utf16_result. year( ) , 2023 ) ;
1567
+ assert_eq ! ( datetime_utf16_result. month( ) , 5 ) ;
1568
+ assert_eq ! ( datetime_utf16_result. day( ) , 15 ) ;
1569
+ assert_eq ! ( datetime_utf16_result. hour( ) , 14 ) ;
1570
+ assert_eq ! ( datetime_utf16_result. minute( ) , 30 ) ;
1571
+ assert_eq ! ( datetime_utf16_result. second( ) , 45 ) ;
1572
+ assert_eq ! ( datetime_utf16_result. millisecond( ) , 123 ) ;
1573
+ }
1574
+
1575
+ #[ test]
1576
+ fn test_temporal_parser_from_str_as_utf8 ( ) {
1577
+ use crate :: parsers:: TemporalParser ;
1578
+
1579
+ let datetime_str = "2023-05-15T14:30:45.123" ;
1580
+ let parser = TemporalParser :: from_str_as_utf8 ( datetime_str) ;
1581
+
1582
+ // Test that the parser works correctly with the renamed method
1583
+ let parsed = parser. parse_date_time ( ) . unwrap ( ) ;
1584
+
1585
+ assert_eq ! ( parsed. iso. date. year, 2023 ) ;
1586
+ assert_eq ! ( parsed. iso. date. month, 5 ) ;
1587
+ assert_eq ! ( parsed. iso. date. day, 15 ) ;
1588
+ assert_eq ! ( parsed. iso. time. hour, 14 ) ;
1589
+ assert_eq ! ( parsed. iso. time. minute, 30 ) ;
1590
+ assert_eq ! ( parsed. iso. time. second, 45 ) ;
1591
+ assert_eq ! ( parsed. iso. time. millisecond, 123 ) ;
1592
+ }
1593
+
1594
+ #[ test]
1595
+ fn test_all_temporal_types_utf16_support ( ) {
1596
+ use crate :: { Instant , PlainDate , PlainMonthDay , PlainTime , PlainYearMonth } ;
1597
+ use alloc:: vec:: Vec ;
1598
+
1599
+ // Test all temporal types have consistent UTF-16 support
1600
+ let datetime_str = "2023-05-15T14:30:45.123" ;
1601
+ let datetime_utf16: Vec < u16 > = datetime_str. encode_utf16 ( ) . collect ( ) ;
1602
+
1603
+ let time_str = "14:30:45.123" ;
1604
+ let time_utf16: Vec < u16 > = time_str. encode_utf16 ( ) . collect ( ) ;
1605
+
1606
+ let date_str = "2023-05-15T00:00:00" ;
1607
+ let date_utf16: Vec < u16 > = date_str. encode_utf16 ( ) . collect ( ) ;
1608
+
1609
+ let year_month_str = "2023-05" ;
1610
+ let year_month_utf16: Vec < u16 > = year_month_str. encode_utf16 ( ) . collect ( ) ;
1611
+
1612
+ let month_day_str = "05-15" ;
1613
+ let month_day_utf16: Vec < u16 > = month_day_str. encode_utf16 ( ) . collect ( ) ;
1614
+
1615
+ let instant_str = "2023-05-15T14:30:45.123Z" ;
1616
+ let instant_utf16: Vec < u16 > = instant_str. encode_utf16 ( ) . collect ( ) ;
1617
+
1618
+ // Test that all types can parse UTF-16
1619
+ let datetime = PlainDateTime :: from_utf16 ( & datetime_utf16) . unwrap ( ) ;
1620
+ assert_eq ! ( datetime. year( ) , 2023 ) ;
1621
+ assert_eq ! ( datetime. month( ) , 5 ) ;
1622
+ assert_eq ! ( datetime. day( ) , 15 ) ;
1623
+ assert_eq ! ( datetime. hour( ) , 14 ) ;
1624
+ assert_eq ! ( datetime. minute( ) , 30 ) ;
1625
+ assert_eq ! ( datetime. second( ) , 45 ) ;
1626
+ assert_eq ! ( datetime. millisecond( ) , 123 ) ;
1627
+
1628
+ let time = PlainTime :: from_utf16 ( & time_utf16) . unwrap ( ) ;
1629
+ assert_eq ! ( time. hour( ) , 14 ) ;
1630
+ assert_eq ! ( time. minute( ) , 30 ) ;
1631
+ assert_eq ! ( time. second( ) , 45 ) ;
1632
+ assert_eq ! ( time. millisecond( ) , 123 ) ;
1633
+
1634
+ let date = PlainDate :: from_utf16 ( & date_utf16) . unwrap ( ) ;
1635
+ assert_eq ! ( date. year( ) , 2023 ) ;
1636
+ assert_eq ! ( date. month( ) , 5 ) ;
1637
+ assert_eq ! ( date. day( ) , 15 ) ;
1638
+
1639
+ let year_month = PlainYearMonth :: from_utf16 ( & year_month_utf16) . unwrap ( ) ;
1640
+ assert_eq ! ( year_month. year( ) , 2023 ) ;
1641
+ assert_eq ! ( year_month. month( ) , 5 ) ;
1642
+
1643
+ let month_day = PlainMonthDay :: from_utf16 ( & month_day_utf16) . unwrap ( ) ;
1644
+ assert_eq ! ( month_day. iso_month( ) , 5 ) ;
1645
+ assert_eq ! ( month_day. day( ) , 15 ) ;
1646
+
1647
+ let instant = Instant :: from_utf16 ( & instant_utf16) . unwrap ( ) ;
1648
+ assert_eq ! ( instant. epoch_milliseconds( ) , 1684161045123 ) ;
1649
+
1650
+ // Test UTF-16 vs UTF-8 equivalence
1651
+ let datetime_utf8 = PlainDateTime :: from_utf8 ( datetime_str. as_bytes ( ) ) . unwrap ( ) ;
1652
+ let time_utf8 = PlainTime :: from_utf8 ( time_str. as_bytes ( ) ) . unwrap ( ) ;
1653
+ let date_utf8 = PlainDate :: from_utf8 ( date_str. as_bytes ( ) ) . unwrap ( ) ;
1654
+ let year_month_utf8 = PlainYearMonth :: from_utf8 ( year_month_str. as_bytes ( ) ) . unwrap ( ) ;
1655
+ let month_day_utf8 = PlainMonthDay :: from_utf8 ( month_day_str. as_bytes ( ) ) . unwrap ( ) ;
1656
+ let instant_utf8 = Instant :: from_utf8 ( instant_str. as_bytes ( ) ) . unwrap ( ) ;
1657
+
1658
+ assert_eq ! ( datetime, datetime_utf8) ;
1659
+ assert_eq ! ( time, time_utf8) ;
1660
+ assert_eq ! ( date, date_utf8) ;
1661
+ assert_eq ! ( year_month, year_month_utf8) ;
1662
+ assert_eq ! ( month_day, month_day_utf8) ;
1663
+ assert_eq ! ( instant, instant_utf8) ;
1664
+ }
1521
1665
}
0 commit comments