@@ -4,7 +4,7 @@ use crate::naive::{NaiveDate, NaiveTime};
4
4
use crate :: offset:: { FixedOffset , TimeZone , Utc } ;
5
5
#[ cfg( feature = "clock" ) ]
6
6
use crate :: offset:: { Local , Offset } ;
7
- use crate :: { Datelike , Days , LocalResult , Months , NaiveDateTime , Timelike } ;
7
+ use crate :: { Datelike , Days , LocalResult , Months , NaiveDateTime , Timelike , Weekday } ;
8
8
9
9
#[ derive( Clone ) ]
10
10
struct DstTester ;
@@ -1331,6 +1331,163 @@ fn test_datetime_sub_assign() {
1331
1331
assert_eq ! ( datetime_sub, datetime - OldDuration :: minutes( 90 ) ) ;
1332
1332
}
1333
1333
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
+
1334
1491
#[ test]
1335
1492
#[ cfg( feature = "clock" ) ]
1336
1493
fn test_datetime_sub_assign_local ( ) {
0 commit comments