Skip to content

Commit 99f1679

Browse files
committed
Add tests for datetimes where the local value is out of range
1 parent 7e249db commit 99f1679

File tree

2 files changed

+153
-2
lines changed

2 files changed

+153
-2
lines changed

src/datetime/tests.rs

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::offset::{FixedOffset, TimeZone, Utc};
44
#[cfg(feature = "clock")]
55
use crate::offset::{Local, Offset};
66
use crate::oldtime::Duration;
7-
use crate::{Datelike, Days, LocalResult, Months, NaiveDateTime};
7+
use crate::{Datelike, Days, LocalResult, Months, NaiveDateTime, Timelike, Weekday};
88

99
#[derive(Clone)]
1010
struct DstTester;
@@ -1347,6 +1347,157 @@ fn test_datetime_sub_assign() {
13471347
assert_eq!(datetime_sub, datetime - Duration::minutes(90));
13481348
}
13491349

1350+
#[test]
1351+
fn test_min_max_datetimes() {
1352+
let offset_min = FixedOffset::west_opt(2 * 60 * 60).unwrap();
1353+
let min = offset_min.from_utc_datetime(&NaiveDateTime::MIN);
1354+
let offset_max = FixedOffset::east_opt(2 * 60 * 60).unwrap();
1355+
let max = offset_max.from_utc_datetime(&NaiveDateTime::MAX);
1356+
1357+
assert_eq!(format!("{:?}", min), "-262144-12-31T22:00:00-02:00");
1358+
// RFC 2822 doesn't support years with more than 4 digits.
1359+
// assert_eq!(min.to_rfc2822(), "");
1360+
#[cfg(any(feature = "alloc", feature = "std"))]
1361+
assert_eq!(min.to_rfc3339(), "-262144-12-31T22:00:00-02:00");
1362+
#[cfg(any(feature = "alloc", feature = "std"))]
1363+
assert_eq!(min.format("%Y-%m-%dT%H:%M:%S%:z").to_string(), "-262144-12-31T22:00:00-02:00");
1364+
assert_eq!(min.year(), -262144);
1365+
assert_eq!(min.month(), 12);
1366+
assert_eq!(min.month0(), 11);
1367+
assert_eq!(min.day(), 31);
1368+
assert_eq!(min.day0(), 30);
1369+
assert_eq!(min.ordinal(), 366);
1370+
assert_eq!(min.ordinal0(), 365);
1371+
assert_eq!(min.weekday(), Weekday::Wed);
1372+
assert_eq!(min.iso_week().year(), -262143);
1373+
assert_eq!(min.iso_week().week(), 1);
1374+
assert_eq!(min.checked_add_days(Days::new(0)), None);
1375+
assert_eq!(
1376+
min.checked_add_days(Days::new(1)),
1377+
Some(offset_min.from_utc_datetime(&(NaiveDate::MIN + Days(1)).and_time(NaiveTime::MIN)))
1378+
);
1379+
assert_eq!(min.checked_sub_days(Days::new(0)), None);
1380+
assert_eq!(min.checked_sub_days(Days::new(1)), None);
1381+
assert_eq!(min.checked_add_months(Months::new(0)), Some(min));
1382+
assert_eq!(
1383+
min.checked_add_months(Months::new(1)),
1384+
Some(offset_min.from_utc_datetime(&(NaiveDate::MIN + Months(1)).and_time(NaiveTime::MIN)))
1385+
);
1386+
assert_eq!(min.checked_sub_months(Months::new(0)), Some(min));
1387+
assert_eq!(min.checked_sub_months(Months::new(1)), None);
1388+
assert_eq!(min.with_year(min.year()), Some(min));
1389+
assert_eq!(
1390+
min.with_year(2020),
1391+
offset_min
1392+
.from_local_datetime(
1393+
&(NaiveDate::MIN.with_year(2021).unwrap().and_time(NaiveTime::MIN) + offset_min)
1394+
)
1395+
.single()
1396+
);
1397+
assert_eq!(min.with_month(min.month()), Some(min));
1398+
assert_eq!(min.with_month(3), None);
1399+
assert_eq!(min.with_month0(min.month0()), Some(min));
1400+
assert_eq!(min.with_month0(3), None);
1401+
assert_eq!(min.with_day(min.day()), Some(min));
1402+
assert_eq!(min.with_day(15), None);
1403+
assert_eq!(min.with_day0(min.day0()), Some(min));
1404+
assert_eq!(min.with_day0(15), None);
1405+
assert_eq!(min.with_ordinal(min.ordinal()), Some(min));
1406+
assert_eq!(min.with_ordinal(200), None);
1407+
assert_eq!(min.with_ordinal0(min.ordinal0()), Some(min));
1408+
assert_eq!(min.with_ordinal0(200), None);
1409+
assert_eq!(min.hour(), 22);
1410+
assert_eq!(min.minute(), 0);
1411+
assert_eq!(min.second(), 0);
1412+
assert_eq!(min.nanosecond(), 0);
1413+
assert_eq!(min.with_hour(min.hour()), Some(min));
1414+
assert_eq!(min.with_hour(23), min.checked_add_signed(Duration::hours(1)));
1415+
assert_eq!(min.with_hour(5), None);
1416+
assert_eq!(min.with_minute(0), Some(min));
1417+
assert_eq!(min.with_second(0), Some(min));
1418+
assert_eq!(min.with_nanosecond(0), Some(min));
1419+
1420+
assert_eq!(format!("{:?}", max), "+262143-01-01T01:59:59.999999999+02:00");
1421+
// RFC 2822 doesn't support years with more than 4 digits.
1422+
// assert_eq!(min.to_rfc2822(), "");
1423+
#[cfg(any(feature = "alloc", feature = "std"))]
1424+
assert_eq!(max.to_rfc3339(), "+262143-01-01T01:59:59.999999999+02:00");
1425+
#[cfg(any(feature = "alloc", feature = "std"))]
1426+
assert_eq!(
1427+
max.format("%Y-%m-%dT%H:%M:%S%.9f%:z").to_string(),
1428+
"+262143-01-01T01:59:59.999999999+02:00"
1429+
);
1430+
assert_eq!(max.year(), 262143);
1431+
assert_eq!(max.month(), 1);
1432+
assert_eq!(max.month0(), 0);
1433+
assert_eq!(max.day(), 1);
1434+
assert_eq!(max.day0(), 0);
1435+
assert_eq!(max.ordinal(), 1);
1436+
assert_eq!(max.ordinal0(), 0);
1437+
assert_eq!(max.weekday(), Weekday::Tue);
1438+
assert_eq!(max.iso_week().year(), 262143);
1439+
assert_eq!(max.iso_week().week(), 1);
1440+
assert_eq!(max.checked_add_days(Days::new(0)), None);
1441+
assert_eq!(max.checked_add_days(Days::new(1)), None);
1442+
assert_eq!(max.checked_sub_days(Days::new(0)), None);
1443+
assert_eq!(
1444+
max.checked_sub_days(Days::new(1)),
1445+
Some(offset_max.from_utc_datetime(&(NaiveDate::MAX - Days(1)).and_time(NaiveTime::MAX)))
1446+
);
1447+
assert_eq!(max.checked_add_months(Months::new(0)), Some(max));
1448+
assert_eq!(max.checked_add_months(Months::new(1)), None);
1449+
assert_eq!(max.checked_sub_months(Months::new(0)), Some(max));
1450+
assert_eq!(
1451+
max.checked_sub_months(Months::new(1)),
1452+
Some(offset_max.from_utc_datetime(&(NaiveDate::MAX - Months(1)).and_time(NaiveTime::MAX)))
1453+
);
1454+
assert_eq!(max.with_year(max.year()), Some(max));
1455+
assert_eq!(
1456+
max.with_year(2020),
1457+
offset_max
1458+
.from_local_datetime(
1459+
&(NaiveDate::MAX.with_year(2019).unwrap().and_time(NaiveTime::MAX) + offset_max)
1460+
)
1461+
.single()
1462+
);
1463+
assert_eq!(max.with_month(max.month()), Some(max));
1464+
assert_eq!(max.with_month(3), None);
1465+
assert_eq!(max.with_month0(max.month0()), Some(max));
1466+
assert_eq!(max.with_month0(3), None);
1467+
assert_eq!(max.with_day(max.day()), Some(max));
1468+
assert_eq!(max.with_day(15), None);
1469+
assert_eq!(max.with_day0(max.day0()), Some(max));
1470+
assert_eq!(max.with_day0(15), None);
1471+
assert_eq!(max.with_ordinal(max.ordinal()), Some(max));
1472+
assert_eq!(max.with_ordinal(200), None);
1473+
assert_eq!(max.with_ordinal0(max.ordinal0()), Some(max));
1474+
assert_eq!(max.with_ordinal0(200), None);
1475+
assert_eq!(max.hour(), 1);
1476+
assert_eq!(max.minute(), 59);
1477+
assert_eq!(max.second(), 59);
1478+
assert_eq!(max.nanosecond(), 999_999_999);
1479+
assert_eq!(max.with_hour(max.hour()), Some(max));
1480+
assert_eq!(max.with_hour(0), max.checked_sub_signed(Duration::hours(1)));
1481+
assert_eq!(max.with_hour(5), None);
1482+
assert_eq!(max.with_minute(max.minute()), Some(max));
1483+
assert_eq!(max.with_second(max.second()), Some(max));
1484+
assert_eq!(max.with_nanosecond(max.nanosecond()), Some(max));
1485+
}
1486+
1487+
#[test]
1488+
#[should_panic]
1489+
fn test_local_beyond_min_datetime() {
1490+
let min = FixedOffset::west_opt(2 * 60 * 60).unwrap().from_utc_datetime(&NaiveDateTime::MIN);
1491+
let _ = min.naive_local();
1492+
}
1493+
1494+
#[test]
1495+
#[should_panic]
1496+
fn test_local_beyond_max_datetime() {
1497+
let max = FixedOffset::east_opt(2 * 60 * 60).unwrap().from_utc_datetime(&NaiveDateTime::MAX);
1498+
let _ = max.naive_local();
1499+
}
1500+
13501501
#[test]
13511502
#[cfg(feature = "clock")]
13521503
fn test_datetime_sub_assign_local() {

src/naive/time/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ impl NaiveTime {
846846

847847
/// The earliest possible `NaiveTime`
848848
pub const MIN: Self = Self { secs: 0, frac: 0 };
849-
pub(super) const MAX: Self = Self { secs: 23 * 3600 + 59 * 60 + 59, frac: 999_999_999 };
849+
pub(crate) const MAX: Self = Self { secs: 23 * 3600 + 59 * 60 + 59, frac: 999_999_999 };
850850
}
851851

852852
impl Timelike for NaiveTime {

0 commit comments

Comments
 (0)