Skip to content

Commit 74b087f

Browse files
committed
change NaiveDateTime and DateTime<Tz> to use TimeDelta
* these are done in one commit as they are very intertwined, eg via round.rs * removing OldTimeDelta where it is no longer used
1 parent 7b40d1a commit 74b087f

File tree

12 files changed

+542
-1262
lines changed

12 files changed

+542
-1262
lines changed

src/datetime/mod.rs

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use alloc::string::{String, ToString};
1212
use core::borrow::Borrow;
1313
use core::cmp::Ordering;
1414
use core::ops::{Add, AddAssign, Sub, SubAssign};
15+
use core::time::Duration;
1516
use core::{fmt, hash, str};
1617
#[cfg(feature = "std")]
1718
use std::string::ToString;
@@ -31,7 +32,7 @@ use crate::naive::{Days, IsoWeek, NaiveDate, NaiveDateTime, NaiveTime};
3132
#[cfg(feature = "clock")]
3233
use crate::offset::Local;
3334
use crate::offset::{FixedOffset, Offset, TimeZone, Utc};
34-
use crate::{Date, Datelike, Months, OldTimeDelta, Timelike, Weekday};
35+
use crate::{Date, Datelike, Months, TimeDelta, Timelike, Weekday};
3536

3637
/// documented at re-export site
3738
#[cfg(feature = "serde")]
@@ -318,8 +319,8 @@ impl<Tz: TimeZone> DateTime<Tz> {
318319
///
319320
/// Returns `None` when it will result in overflow.
320321
#[inline]
321-
pub fn checked_add_signed(self, rhs: OldTimeDelta) -> Option<DateTime<Tz>> {
322-
let datetime = self.datetime.checked_add_signed(rhs)?;
322+
pub fn checked_add(self, rhs: Duration) -> Option<DateTime<Tz>> {
323+
let datetime = self.datetime.checked_add(rhs)?;
323324
let tz = self.timezone();
324325
Some(tz.from_utc_datetime(&datetime))
325326
}
@@ -341,8 +342,8 @@ impl<Tz: TimeZone> DateTime<Tz> {
341342
///
342343
/// Returns `None` when it will result in overflow.
343344
#[inline]
344-
pub fn checked_sub_signed(self, rhs: OldTimeDelta) -> Option<DateTime<Tz>> {
345-
let datetime = self.datetime.checked_sub_signed(rhs)?;
345+
pub fn checked_sub(self, rhs: Duration) -> Option<DateTime<Tz>> {
346+
let datetime = self.datetime.checked_sub(rhs)?;
346347
let tz = self.timezone();
347348
Some(tz.from_utc_datetime(&datetime))
348349
}
@@ -383,8 +384,8 @@ impl<Tz: TimeZone> DateTime<Tz> {
383384
/// Subtracts another `DateTime` from the current date and time.
384385
/// This does not overflow or underflow at all.
385386
#[inline]
386-
pub fn signed_duration_since<Tz2: TimeZone>(self, rhs: DateTime<Tz2>) -> OldTimeDelta {
387-
self.datetime.signed_duration_since(rhs.datetime)
387+
pub fn duration_since<Tz2: TimeZone>(self, rhs: DateTime<Tz2>) -> TimeDelta {
388+
self.datetime.duration_since(rhs.datetime)
388389
}
389390

390391
/// Returns a view to the naive UTC datetime.
@@ -966,20 +967,19 @@ impl<Tz: TimeZone> hash::Hash for DateTime<Tz> {
966967
}
967968
}
968969

969-
impl<Tz: TimeZone> Add<OldTimeDelta> for DateTime<Tz> {
970+
impl<Tz: TimeZone> Add<Duration> for DateTime<Tz> {
970971
type Output = DateTime<Tz>;
971972

972973
#[inline]
973-
fn add(self, rhs: OldTimeDelta) -> DateTime<Tz> {
974-
self.checked_add_signed(rhs).expect("`DateTime + Duration` overflowed")
974+
fn add(self, rhs: Duration) -> DateTime<Tz> {
975+
self.checked_add(rhs).expect("`DateTime + Duration` overflowed")
975976
}
976977
}
977978

978-
impl<Tz: TimeZone> AddAssign<OldTimeDelta> for DateTime<Tz> {
979+
impl<Tz: TimeZone> AddAssign<Duration> for DateTime<Tz> {
979980
#[inline]
980-
fn add_assign(&mut self, rhs: OldTimeDelta) {
981-
let datetime =
982-
self.datetime.checked_add_signed(rhs).expect("`DateTime + Duration` overflowed");
981+
fn add_assign(&mut self, rhs: Duration) {
982+
let datetime = self.datetime.checked_add(rhs).expect("`DateTime + Duration` overflowed");
983983
let tz = self.timezone();
984984
*self = tz.from_utc_datetime(&datetime);
985985
}
@@ -993,20 +993,19 @@ impl<Tz: TimeZone> Add<Months> for DateTime<Tz> {
993993
}
994994
}
995995

996-
impl<Tz: TimeZone> Sub<OldTimeDelta> for DateTime<Tz> {
996+
impl<Tz: TimeZone> Sub<Duration> for DateTime<Tz> {
997997
type Output = DateTime<Tz>;
998998

999999
#[inline]
1000-
fn sub(self, rhs: OldTimeDelta) -> DateTime<Tz> {
1001-
self.checked_sub_signed(rhs).expect("`DateTime - Duration` overflowed")
1000+
fn sub(self, rhs: Duration) -> DateTime<Tz> {
1001+
self.checked_sub(rhs).expect("`DateTime - Duration` overflowed")
10021002
}
10031003
}
10041004

1005-
impl<Tz: TimeZone> SubAssign<OldTimeDelta> for DateTime<Tz> {
1005+
impl<Tz: TimeZone> SubAssign<Duration> for DateTime<Tz> {
10061006
#[inline]
1007-
fn sub_assign(&mut self, rhs: OldTimeDelta) {
1008-
let datetime =
1009-
self.datetime.checked_sub_signed(rhs).expect("`DateTime - Duration` overflowed");
1007+
fn sub_assign(&mut self, rhs: Duration) {
1008+
let datetime = self.datetime.checked_sub(rhs).expect("`DateTime - Duration` overflowed");
10101009
let tz = self.timezone();
10111010
*self = tz.from_utc_datetime(&datetime)
10121011
}
@@ -1020,15 +1019,6 @@ impl<Tz: TimeZone> Sub<Months> for DateTime<Tz> {
10201019
}
10211020
}
10221021

1023-
impl<Tz: TimeZone> Sub<DateTime<Tz>> for DateTime<Tz> {
1024-
type Output = OldTimeDelta;
1025-
1026-
#[inline]
1027-
fn sub(self, rhs: DateTime<Tz>) -> OldTimeDelta {
1028-
self.signed_duration_since(rhs)
1029-
}
1030-
}
1031-
10321022
impl<Tz: TimeZone> Add<Days> for DateTime<Tz> {
10331023
type Output = DateTime<Tz>;
10341024

@@ -1133,8 +1123,6 @@ impl From<SystemTime> for DateTime<Local> {
11331123
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
11341124
impl<Tz: TimeZone> From<DateTime<Tz>> for SystemTime {
11351125
fn from(dt: DateTime<Tz>) -> SystemTime {
1136-
use std::time::Duration;
1137-
11381126
let sec = dt.timestamp();
11391127
let nsec = dt.timestamp_subsec_nanos();
11401128
if sec < 0 {

src/datetime/tests.rs

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::time::Duration;
12
use std::time::{SystemTime, UNIX_EPOCH};
23

34
use super::DateTime;
@@ -7,10 +8,10 @@ use crate::offset::Local;
78
use crate::offset::{FixedOffset, TimeZone, Utc};
89
#[cfg(feature = "clock")]
910
use crate::Datelike;
10-
use crate::OldTimeDelta;
11+
use crate::TimeDelta;
1112

1213
#[test]
13-
fn test_datetime_offset() {
14+
fn test_datetime_offset_duration() {
1415
let est = FixedOffset::west_opt(5 * 60 * 60).unwrap();
1516
let edt = FixedOffset::west_opt(4 * 60 * 60).unwrap();
1617
let kst = FixedOffset::east_opt(9 * 60 * 60).unwrap();
@@ -69,12 +70,12 @@ fn test_datetime_offset() {
6970
let dt = Utc.ymd_opt(2014, 5, 6).unwrap().and_hms_opt(7, 8, 9).unwrap();
7071
assert_eq!(dt, edt.ymd_opt(2014, 5, 6).unwrap().and_hms_opt(3, 8, 9).unwrap());
7172
assert_eq!(
72-
dt + OldTimeDelta::seconds(3600 + 60 + 1),
73+
dt + Duration::from_secs(3600 + 60 + 1),
7374
Utc.ymd_opt(2014, 5, 6).unwrap().and_hms_opt(8, 9, 10).unwrap()
7475
);
7576
assert_eq!(
76-
dt.signed_duration_since(edt.ymd_opt(2014, 5, 6).unwrap().and_hms_opt(10, 11, 12).unwrap()),
77-
OldTimeDelta::seconds(-7 * 3600 - 3 * 60 - 3)
77+
dt.duration_since(edt.ymd_opt(2014, 5, 6).unwrap().and_hms_opt(10, 11, 12).unwrap()),
78+
TimeDelta::Backwards(Duration::from_secs(7 * 3600 + 3 * 60 + 3))
7879
);
7980

8081
assert_eq!(*Utc.ymd_opt(2014, 5, 6).unwrap().and_hms_opt(7, 8, 9).unwrap().offset(), Utc);
@@ -362,8 +363,6 @@ fn test_subsecond_part() {
362363
#[test]
363364
#[cfg(not(target_os = "windows"))]
364365
fn test_from_system_time() {
365-
use std::time::Duration;
366-
367366
let epoch = Utc.ymd_opt(1970, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
368367
let nanos = 999_999_999;
369368

@@ -411,8 +410,6 @@ fn test_from_system_time() {
411410
#[test]
412411
#[cfg(target_os = "windows")]
413412
fn test_from_system_time() {
414-
use std::time::Duration;
415-
416413
let nanos = 999_999_000;
417414

418415
let epoch = Utc.ymd_opt(1970, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
@@ -513,98 +510,95 @@ fn test_datetime_from_local() {
513510

514511
#[test]
515512
#[cfg(feature = "clock")]
516-
fn test_years_elapsed() {
517-
use crate::Days;
518-
513+
fn test_years_elapsed_duration() {
519514
const WEEKS_PER_YEAR: f32 = 52.1775;
520515

521516
// This is always at least one year because 1 year = 52.1775 weeks.
522-
let one_year_ago = Utc.from_utc_date(
523-
&(Utc::today().naive_utc() - Days::new((WEEKS_PER_YEAR * 1.5 * 7.0).ceil() as u64)),
524-
);
517+
let one_year_ago = Utc::today().and_hms_opt(0, 0, 0).unwrap()
518+
- Duration::from_secs(7 * 24 * 60 * 60 * (WEEKS_PER_YEAR * 1.5).ceil() as u64);
525519
// A bit more than 2 years.
526-
let two_year_ago = Utc.from_utc_date(
527-
&(Utc::today().naive_utc() - Days::new((WEEKS_PER_YEAR * 2.5 * 7.0).ceil() as u64)),
528-
);
520+
let two_year_ago = Utc::today().and_hms_opt(0, 0, 0).unwrap()
521+
- Duration::from_secs(7 * 24 * 60 * 60 * (WEEKS_PER_YEAR * 2.5).ceil() as u64);
529522

530-
assert_eq!(Utc::today().years_since(one_year_ago), Some(1));
531-
assert_eq!(Utc::today().years_since(two_year_ago), Some(2));
523+
assert_eq!(Utc::today().and_hms_opt(0, 0, 0).unwrap().years_since(one_year_ago), Some(1));
524+
assert_eq!(Utc::today().and_hms_opt(0, 0, 0).unwrap().years_since(two_year_ago), Some(2));
532525

533526
// If the given DateTime is later than now, the function will always return 0.
534-
let future = Utc.from_utc_date(&(Utc::today().naive_utc() + Days::new(12 * 7)));
535-
assert_eq!(Utc::today().years_since(future), None);
527+
let future =
528+
Utc::today().and_hms_opt(0, 0, 0).unwrap() + Duration::from_secs(7 * 24 * 60 * 60 * 12);
529+
assert_eq!(Utc::today().and_hms_opt(0, 0, 0).unwrap().years_since(future), None);
536530
}
537531

538532
#[test]
539-
fn test_datetime_add_assign() {
533+
fn test_datetime_add_assign_duration() {
540534
let naivedatetime = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
541535
let datetime = DateTime::<Utc>::from_utc(naivedatetime, Utc);
542536
let mut datetime_add = datetime;
543537

544-
datetime_add += OldTimeDelta::seconds(60);
545-
assert_eq!(datetime_add, datetime + OldTimeDelta::seconds(60));
538+
datetime_add += Duration::from_secs(60);
539+
assert_eq!(datetime_add, datetime + Duration::from_secs(60));
546540

547541
let timezone = FixedOffset::east_opt(60 * 60).unwrap();
548542
let datetime = datetime.with_timezone(&timezone);
549543
let datetime_add = datetime_add.with_timezone(&timezone);
550544

551-
assert_eq!(datetime_add, datetime + OldTimeDelta::seconds(60));
545+
assert_eq!(datetime_add, datetime + Duration::from_secs(60));
552546

553547
let timezone = FixedOffset::west_opt(2 * 60 * 60).unwrap();
554548
let datetime = datetime.with_timezone(&timezone);
555549
let datetime_add = datetime_add.with_timezone(&timezone);
556550

557-
assert_eq!(datetime_add, datetime + OldTimeDelta::seconds(60));
551+
assert_eq!(datetime_add, datetime + Duration::from_secs(60));
558552
}
559553

560554
#[test]
561555
#[cfg(feature = "clock")]
562-
fn test_datetime_add_assign_local() {
556+
fn test_datetime_add_assign_local_duration() {
563557
let naivedatetime = NaiveDate::from_ymd_opt(2022, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
564558

565559
let datetime = Local.from_utc_datetime(&naivedatetime);
566560
let mut datetime_add = Local.from_utc_datetime(&naivedatetime);
567561

568562
// ensure we cross a DST transition
569563
for i in 1..=365 {
570-
datetime_add += OldTimeDelta::days(1);
571-
assert_eq!(datetime_add, datetime + OldTimeDelta::days(i))
564+
datetime_add += Duration::from_secs(24 * 60 * 60);
565+
assert_eq!(datetime_add, datetime + Duration::from_secs(24 * 60 * 60 * i))
572566
}
573567
}
574568

575569
#[test]
576-
fn test_datetime_sub_assign() {
570+
fn test_datetime_sub_assign_duration() {
577571
let naivedatetime = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap().and_hms_opt(12, 0, 0).unwrap();
578572
let datetime = DateTime::<Utc>::from_utc(naivedatetime, Utc);
579573
let mut datetime_sub = datetime;
580574

581-
datetime_sub -= OldTimeDelta::minutes(90);
582-
assert_eq!(datetime_sub, datetime - OldTimeDelta::minutes(90));
575+
datetime_sub -= Duration::from_secs(60 * 90);
576+
assert_eq!(datetime_sub, datetime - Duration::from_secs(60 * 90));
583577

584578
let timezone = FixedOffset::east_opt(60 * 60).unwrap();
585579
let datetime = datetime.with_timezone(&timezone);
586580
let datetime_sub = datetime_sub.with_timezone(&timezone);
587581

588-
assert_eq!(datetime_sub, datetime - OldTimeDelta::minutes(90));
582+
assert_eq!(datetime_sub, datetime - Duration::from_secs(60 * 90));
589583

590584
let timezone = FixedOffset::west_opt(2 * 60 * 60).unwrap();
591585
let datetime = datetime.with_timezone(&timezone);
592586
let datetime_sub = datetime_sub.with_timezone(&timezone);
593587

594-
assert_eq!(datetime_sub, datetime - OldTimeDelta::minutes(90));
588+
assert_eq!(datetime_sub, datetime - Duration::from_secs(60 * 90));
595589
}
596590

597591
#[test]
598592
#[cfg(feature = "clock")]
599-
fn test_datetime_sub_assign_local() {
593+
fn test_datetime_sub_assign_local_duration() {
600594
let naivedatetime = NaiveDate::from_ymd_opt(2022, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
601595

602596
let datetime = Local.from_utc_datetime(&naivedatetime);
603597
let mut datetime_sub = Local.from_utc_datetime(&naivedatetime);
604598

605599
// ensure we cross a DST transition
606600
for i in 1..=365 {
607-
datetime_sub -= OldTimeDelta::days(1);
608-
assert_eq!(datetime_sub, datetime - OldTimeDelta::days(i))
601+
datetime_sub -= Duration::from_secs(24 * 60 * 60);
602+
assert_eq!(datetime_sub, datetime - Duration::from_secs(24 * 60 * 60 * i))
609603
}
610604
}

src/format/parsed.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
//! They can be constructed incrementally while being checked for consistency.
66
77
use core::convert::TryFrom;
8+
use core::time::Duration;
89

910
use num_integer::div_rem;
1011

1112
use super::{ParseResult, IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
1213
use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
1314
use crate::offset::{FixedOffset, LocalResult, Offset, TimeZone};
14-
use crate::{DateTime, Datelike, Days, OldTimeDelta, Timelike, Weekday};
15+
use crate::{DateTime, Datelike, Days, Timelike, Weekday};
1516

1617
/// Parsed parts of date and time. There are two classes of methods:
1718
///
@@ -601,7 +602,7 @@ impl Parsed {
601602
59 => {}
602603
// `datetime` is known to be off by one second.
603604
0 => {
604-
datetime -= OldTimeDelta::seconds(1);
605+
datetime -= Duration::from_secs(1);
605606
}
606607
// otherwise it is impossible.
607608
_ => return Err(IMPOSSIBLE),
@@ -644,9 +645,17 @@ impl Parsed {
644645
let offset = FixedOffset::east_opt(offset).ok_or(OUT_OF_RANGE)?;
645646

646647
// this is used to prevent an overflow when calling FixedOffset::from_local_datetime
647-
datetime
648-
.checked_sub_signed(OldTimeDelta::seconds(i64::from(offset.local_minus_utc())))
649-
.ok_or(OUT_OF_RANGE)?;
648+
if offset.local_minus_utc() < 0 {
649+
datetime
650+
.checked_add(Duration::from_secs(
651+
u64::try_from(offset.local_minus_utc().abs()).unwrap(),
652+
))
653+
.ok_or(OUT_OF_RANGE)?;
654+
} else {
655+
datetime
656+
.checked_sub(Duration::from_secs(u64::try_from(offset.local_minus_utc()).unwrap()))
657+
.ok_or(OUT_OF_RANGE)?;
658+
}
650659

651660
match offset.from_local_datetime(&datetime) {
652661
LocalResult::None => Err(IMPOSSIBLE),

0 commit comments

Comments
 (0)