@@ -4,7 +4,7 @@ use crate::naive::{NaiveDate, NaiveTime};
44use crate :: offset:: { FixedOffset , TimeZone , Utc } ;
55#[ cfg( feature = "clock" ) ]
66use crate :: offset:: { Local , Offset } ;
7- use crate :: { Datelike , Days , LocalResult , Months , NaiveDateTime , Timelike } ;
7+ use crate :: { Datelike , Days , LocalResult , Months , NaiveDateTime , Timelike , Weekday } ;
88
99#[ derive( Clone ) ]
1010struct DstTester ;
@@ -1331,6 +1331,163 @@ fn test_datetime_sub_assign() {
13311331 assert_eq ! ( datetime_sub, datetime - OldDuration :: minutes( 90 ) ) ;
13321332}
13331333
1334+ #[ test]
1335+ fn test_min_max_datetimes ( ) {
1336+ let offset_min = FixedOffset :: west_opt ( 2 * 60 * 60 ) . unwrap ( ) ;
1337+ let beyond_min = offset_min. from_utc_datetime ( & NaiveDateTime :: MIN ) ;
1338+ let offset_max = FixedOffset :: east_opt ( 2 * 60 * 60 ) . unwrap ( ) ;
1339+ let beyond_max = offset_max. from_utc_datetime ( & NaiveDateTime :: MAX ) ;
1340+ let max_time = NaiveTime :: from_hms_nano_opt ( 23 , 59 , 59 , 999_999_999 ) . unwrap ( ) ;
1341+
1342+ assert_eq ! ( format!( "{:?}" , beyond_min) , "-262144-12-31T22:00:00-02:00" ) ;
1343+ // RFC 2822 doesn't support years with more than 4 digits.
1344+ // assert_eq!(beyond_min.to_rfc2822(), "");
1345+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1346+ assert_eq ! ( beyond_min. to_rfc3339( ) , "-262144-12-31T22:00:00-02:00" ) ;
1347+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1348+ assert_eq ! (
1349+ beyond_min. format( "%Y-%m-%dT%H:%M:%S%:z" ) . to_string( ) ,
1350+ "-262144-12-31T22:00:00-02:00"
1351+ ) ;
1352+ assert_eq ! ( beyond_min. year( ) , -262144 ) ;
1353+ assert_eq ! ( beyond_min. month( ) , 12 ) ;
1354+ assert_eq ! ( beyond_min. month0( ) , 11 ) ;
1355+ assert_eq ! ( beyond_min. day( ) , 31 ) ;
1356+ assert_eq ! ( beyond_min. day0( ) , 30 ) ;
1357+ assert_eq ! ( beyond_min. ordinal( ) , 366 ) ;
1358+ assert_eq ! ( beyond_min. ordinal0( ) , 365 ) ;
1359+ assert_eq ! ( beyond_min. weekday( ) , Weekday :: Wed ) ;
1360+ assert_eq ! ( beyond_min. iso_week( ) . year( ) , -262143 ) ;
1361+ assert_eq ! ( beyond_min. iso_week( ) . week( ) , 1 ) ;
1362+ assert_eq ! ( beyond_min. checked_add_days( Days :: new( 0 ) ) , Some ( beyond_min) ) ;
1363+ assert_eq ! (
1364+ beyond_min. checked_add_days( Days :: new( 1 ) ) ,
1365+ Some ( offset_min. from_utc_datetime( & ( NaiveDate :: MIN + Days ( 1 ) ) . and_time( NaiveTime :: MIN ) ) )
1366+ ) ;
1367+ assert_eq ! ( beyond_min. checked_sub_days( Days :: new( 0 ) ) , Some ( beyond_min) ) ;
1368+ assert_eq ! ( beyond_min. checked_sub_days( Days :: new( 1 ) ) , None ) ;
1369+ assert_eq ! ( beyond_min. checked_add_months( Months :: new( 0 ) ) , Some ( beyond_min) ) ;
1370+ assert_eq ! (
1371+ beyond_min. checked_add_months( Months :: new( 1 ) ) ,
1372+ Some ( offset_min. from_utc_datetime( & ( NaiveDate :: MIN + Months ( 1 ) ) . and_time( NaiveTime :: MIN ) ) )
1373+ ) ;
1374+ assert_eq ! ( beyond_min. checked_sub_months( Months :: new( 0 ) ) , Some ( beyond_min) ) ;
1375+ assert_eq ! ( beyond_min. checked_sub_months( Months :: new( 1 ) ) , None ) ;
1376+ assert_eq ! ( beyond_min. with_year( beyond_min. year( ) ) , Some ( beyond_min) ) ;
1377+ let res = NaiveDate :: MIN . with_year ( 2021 ) . unwrap ( ) . and_time ( NaiveTime :: MIN ) + offset_min;
1378+ assert_eq ! ( beyond_min. with_year( 2020 ) , offset_min. from_local_datetime( & res) . single( ) ) ;
1379+ assert_eq ! (
1380+ offset_min
1381+ . from_utc_datetime(
1382+ & NaiveDate :: from_ymd_opt( 2023 , 1 , 1 ) . unwrap( ) . and_time( NaiveTime :: MIN )
1383+ )
1384+ . with_year( NaiveDate :: MIN . year( ) - 1 ) ,
1385+ Some ( beyond_min)
1386+ ) ;
1387+ assert_eq ! ( beyond_min. with_month( beyond_min. month( ) ) , Some ( beyond_min) ) ;
1388+ assert_eq ! ( beyond_min. with_month( 3 ) , None ) ;
1389+ assert_eq ! ( beyond_min. with_month0( beyond_min. month0( ) ) , Some ( beyond_min) ) ;
1390+ assert_eq ! ( beyond_min. with_month0( 3 ) , None ) ;
1391+ assert_eq ! ( beyond_min. with_day( beyond_min. day( ) ) , Some ( beyond_min) ) ;
1392+ assert_eq ! ( beyond_min. with_day( 15 ) , None ) ;
1393+ assert_eq ! ( beyond_min. with_day0( beyond_min. day0( ) ) , Some ( beyond_min) ) ;
1394+ assert_eq ! ( beyond_min. with_day0( 15 ) , None ) ;
1395+ assert_eq ! ( beyond_min. with_ordinal( beyond_min. ordinal( ) ) , Some ( beyond_min) ) ;
1396+ assert_eq ! ( beyond_min. with_ordinal( 200 ) , None ) ;
1397+ assert_eq ! ( beyond_min. with_ordinal0( beyond_min. ordinal0( ) ) , Some ( beyond_min) ) ;
1398+ assert_eq ! ( beyond_min. with_ordinal0( 200 ) , None ) ;
1399+ assert_eq ! ( beyond_min. hour( ) , 22 ) ;
1400+ assert_eq ! ( beyond_min. minute( ) , 0 ) ;
1401+ assert_eq ! ( beyond_min. second( ) , 0 ) ;
1402+ assert_eq ! ( beyond_min. nanosecond( ) , 0 ) ;
1403+ assert_eq ! ( beyond_min. with_hour( beyond_min. hour( ) ) , Some ( beyond_min) ) ;
1404+ assert_eq ! ( beyond_min. with_hour( 23 ) , beyond_min. checked_add_signed( OldDuration :: hours( 1 ) ) ) ;
1405+ assert_eq ! ( beyond_min. with_hour( 5 ) , None ) ;
1406+ assert_eq ! ( beyond_min. with_minute( 0 ) , Some ( beyond_min) ) ;
1407+ assert_eq ! ( beyond_min. with_second( 0 ) , Some ( beyond_min) ) ;
1408+ assert_eq ! ( beyond_min. with_nanosecond( 0 ) , Some ( beyond_min) ) ;
1409+
1410+ assert_eq ! ( format!( "{:?}" , beyond_max) , "+262143-01-01T01:59:59.999999999+02:00" ) ;
1411+ // RFC 2822 doesn't support years with more than 4 digits.
1412+ // assert_eq!(beyond_max.to_rfc2822(), "");
1413+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1414+ assert_eq ! ( beyond_max. to_rfc3339( ) , "+262143-01-01T01:59:59.999999999+02:00" ) ;
1415+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1416+ assert_eq ! (
1417+ beyond_max. format( "%Y-%m-%dT%H:%M:%S%.9f%:z" ) . to_string( ) ,
1418+ "+262143-01-01T01:59:59.999999999+02:00"
1419+ ) ;
1420+ assert_eq ! ( beyond_max. year( ) , 262143 ) ;
1421+ assert_eq ! ( beyond_max. month( ) , 1 ) ;
1422+ assert_eq ! ( beyond_max. month0( ) , 0 ) ;
1423+ assert_eq ! ( beyond_max. day( ) , 1 ) ;
1424+ assert_eq ! ( beyond_max. day0( ) , 0 ) ;
1425+ assert_eq ! ( beyond_max. ordinal( ) , 1 ) ;
1426+ assert_eq ! ( beyond_max. ordinal0( ) , 0 ) ;
1427+ assert_eq ! ( beyond_max. weekday( ) , Weekday :: Tue ) ;
1428+ assert_eq ! ( beyond_max. iso_week( ) . year( ) , 262143 ) ;
1429+ assert_eq ! ( beyond_max. iso_week( ) . week( ) , 1 ) ;
1430+ assert_eq ! ( beyond_max. checked_add_days( Days :: new( 0 ) ) , Some ( beyond_max) ) ;
1431+ assert_eq ! ( beyond_max. checked_add_days( Days :: new( 1 ) ) , None ) ;
1432+ assert_eq ! ( beyond_max. checked_sub_days( Days :: new( 0 ) ) , Some ( beyond_max) ) ;
1433+ assert_eq ! (
1434+ beyond_max. checked_sub_days( Days :: new( 1 ) ) ,
1435+ Some ( offset_max. from_utc_datetime( & ( NaiveDate :: MAX - Days ( 1 ) ) . and_time( max_time) ) )
1436+ ) ;
1437+ assert_eq ! ( beyond_max. checked_add_months( Months :: new( 0 ) ) , Some ( beyond_max) ) ;
1438+ assert_eq ! ( beyond_max. checked_add_months( Months :: new( 1 ) ) , None ) ;
1439+ assert_eq ! ( beyond_max. checked_sub_months( Months :: new( 0 ) ) , Some ( beyond_max) ) ;
1440+ assert_eq ! (
1441+ beyond_max. checked_sub_months( Months :: new( 1 ) ) ,
1442+ Some ( offset_max. from_utc_datetime( & ( NaiveDate :: MAX - Months ( 1 ) ) . and_time( max_time) ) )
1443+ ) ;
1444+ assert_eq ! ( beyond_max. with_year( beyond_max. year( ) ) , Some ( beyond_max) ) ;
1445+ let res = NaiveDate :: MAX . with_year ( 2019 ) . unwrap ( ) . and_time ( max_time) + offset_max;
1446+ assert_eq ! ( beyond_max. with_year( 2020 ) , offset_max. from_local_datetime( & res) . single( ) ) ;
1447+ assert_eq ! (
1448+ offset_max
1449+ . from_utc_datetime( & NaiveDate :: from_ymd_opt( 2023 , 12 , 31 ) . unwrap( ) . and_time( max_time) )
1450+ . with_year( NaiveDate :: MAX . year( ) + 1 ) ,
1451+ Some ( beyond_max)
1452+ ) ;
1453+ assert_eq ! ( beyond_max. with_month( beyond_max. month( ) ) , Some ( beyond_max) ) ;
1454+ assert_eq ! ( beyond_max. with_month( 3 ) , None ) ;
1455+ assert_eq ! ( beyond_max. with_month0( beyond_max. month0( ) ) , Some ( beyond_max) ) ;
1456+ assert_eq ! ( beyond_max. with_month0( 3 ) , None ) ;
1457+ assert_eq ! ( beyond_max. with_day( beyond_max. day( ) ) , Some ( beyond_max) ) ;
1458+ assert_eq ! ( beyond_max. with_day( 15 ) , None ) ;
1459+ assert_eq ! ( beyond_max. with_day0( beyond_max. day0( ) ) , Some ( beyond_max) ) ;
1460+ assert_eq ! ( beyond_max. with_day0( 15 ) , None ) ;
1461+ assert_eq ! ( beyond_max. with_ordinal( beyond_max. ordinal( ) ) , Some ( beyond_max) ) ;
1462+ assert_eq ! ( beyond_max. with_ordinal( 200 ) , None ) ;
1463+ assert_eq ! ( beyond_max. with_ordinal0( beyond_max. ordinal0( ) ) , Some ( beyond_max) ) ;
1464+ assert_eq ! ( beyond_max. with_ordinal0( 200 ) , None ) ;
1465+ assert_eq ! ( beyond_max. hour( ) , 1 ) ;
1466+ assert_eq ! ( beyond_max. minute( ) , 59 ) ;
1467+ assert_eq ! ( beyond_max. second( ) , 59 ) ;
1468+ assert_eq ! ( beyond_max. nanosecond( ) , 999_999_999 ) ;
1469+ assert_eq ! ( beyond_max. with_hour( beyond_max. hour( ) ) , Some ( beyond_max) ) ;
1470+ assert_eq ! ( beyond_max. with_hour( 0 ) , beyond_max. checked_sub_signed( OldDuration :: hours( 1 ) ) ) ;
1471+ assert_eq ! ( beyond_max. with_hour( 5 ) , None ) ;
1472+ assert_eq ! ( beyond_max. with_minute( beyond_max. minute( ) ) , Some ( beyond_max) ) ;
1473+ assert_eq ! ( beyond_max. with_second( beyond_max. second( ) ) , Some ( beyond_max) ) ;
1474+ assert_eq ! ( beyond_max. with_nanosecond( beyond_max. nanosecond( ) ) , Some ( beyond_max) ) ;
1475+ }
1476+
1477+ #[ test]
1478+ #[ should_panic]
1479+ fn test_local_beyond_min_datetime ( ) {
1480+ let min = FixedOffset :: west_opt ( 2 * 60 * 60 ) . unwrap ( ) . from_utc_datetime ( & NaiveDateTime :: MIN ) ;
1481+ let _ = min. naive_local ( ) ;
1482+ }
1483+
1484+ #[ test]
1485+ #[ should_panic]
1486+ fn test_local_beyond_max_datetime ( ) {
1487+ let max = FixedOffset :: east_opt ( 2 * 60 * 60 ) . unwrap ( ) . from_utc_datetime ( & NaiveDateTime :: MAX ) ;
1488+ let _ = max. naive_local ( ) ;
1489+ }
1490+
13341491#[ test]
13351492#[ cfg( feature = "clock" ) ]
13361493fn test_datetime_sub_assign_local ( ) {
0 commit comments