summaryrefslogtreecommitdiffstats
path: root/vendor/chrono/src/round.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chrono/src/round.rs')
-rw-r--r--vendor/chrono/src/round.rs487
1 files changed, 397 insertions, 90 deletions
diff --git a/vendor/chrono/src/round.rs b/vendor/chrono/src/round.rs
index 92d7c3a50..b95f24570 100644
--- a/vendor/chrono/src/round.rs
+++ b/vendor/chrono/src/round.rs
@@ -1,16 +1,15 @@
// This is a part of Chrono.
// See README.md and LICENSE.txt for details.
+use crate::datetime::DateTime;
+use crate::oldtime::Duration;
+use crate::NaiveDateTime;
+use crate::TimeZone;
+use crate::Timelike;
use core::cmp::Ordering;
use core::fmt;
use core::marker::Sized;
use core::ops::{Add, Sub};
-use datetime::DateTime;
-use oldtime::Duration;
-#[cfg(any(feature = "std", test))]
-use std;
-use TimeZone;
-use Timelike;
/// Extension trait for subsecond rounding or truncation to a maximum number
/// of digits. Rounding can be used to decrease the error variance when
@@ -25,8 +24,8 @@ pub trait SubsecRound {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, SubsecRound, Timelike, TimeZone, Utc};
- /// let dt = Utc.ymd(2018, 1, 11).and_hms_milli(12, 0, 0, 154);
+ /// # use chrono::{DateTime, SubsecRound, Timelike, TimeZone, Utc, NaiveDate};
+ /// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.round_subsecs(2).nanosecond(), 150_000_000);
/// assert_eq!(dt.round_subsecs(1).nanosecond(), 200_000_000);
/// ```
@@ -37,8 +36,8 @@ pub trait SubsecRound {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, SubsecRound, Timelike, TimeZone, Utc};
- /// let dt = Utc.ymd(2018, 1, 11).and_hms_milli(12, 0, 0, 154);
+ /// # use chrono::{DateTime, SubsecRound, Timelike, TimeZone, Utc, NaiveDate};
+ /// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.trunc_subsecs(2).nanosecond(), 150_000_000);
/// assert_eq!(dt.trunc_subsecs(1).nanosecond(), 100_000_000);
/// ```
@@ -112,8 +111,8 @@ pub trait DurationRound: Sized {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, TimeZone, Utc};
- /// let dt = Utc.ymd(2018, 1, 11).and_hms_milli(12, 0, 0, 154);
+ /// # use chrono::{DateTime, DurationRound, Duration, TimeZone, Utc, NaiveDate};
+ /// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(
/// dt.duration_round(Duration::milliseconds(10)).unwrap().to_string(),
/// "2018-01-11 12:00:00.150 UTC"
@@ -129,8 +128,8 @@ pub trait DurationRound: Sized {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, TimeZone, Utc};
- /// let dt = Utc.ymd(2018, 1, 11).and_hms_milli(12, 0, 0, 154);
+ /// # use chrono::{DateTime, DurationRound, Duration, TimeZone, Utc, NaiveDate};
+ /// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(
/// dt.duration_trunc(Duration::milliseconds(10)).unwrap().to_string(),
/// "2018-01-11 12:00:00.150 UTC"
@@ -150,52 +149,89 @@ impl<Tz: TimeZone> DurationRound for DateTime<Tz> {
type Err = RoundingError;
fn duration_round(self, duration: Duration) -> Result<Self, Self::Err> {
- if let Some(span) = duration.num_nanoseconds() {
- if self.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
- return Err(RoundingError::TimestampExceedsLimit);
- }
- let stamp = self.timestamp_nanos();
- if span > stamp.abs() {
- return Err(RoundingError::DurationExceedsTimestamp);
- }
- let delta_down = stamp % span;
- if delta_down == 0 {
- Ok(self)
+ duration_round(self.naive_local(), self, duration)
+ }
+
+ fn duration_trunc(self, duration: Duration) -> Result<Self, Self::Err> {
+ duration_trunc(self.naive_local(), self, duration)
+ }
+}
+
+impl DurationRound for NaiveDateTime {
+ type Err = RoundingError;
+
+ fn duration_round(self, duration: Duration) -> Result<Self, Self::Err> {
+ duration_round(self, self, duration)
+ }
+
+ fn duration_trunc(self, duration: Duration) -> Result<Self, Self::Err> {
+ duration_trunc(self, self, duration)
+ }
+}
+
+fn duration_round<T>(
+ naive: NaiveDateTime,
+ original: T,
+ duration: Duration,
+) -> Result<T, RoundingError>
+where
+ T: Timelike + Add<Duration, Output = T> + Sub<Duration, Output = T>,
+{
+ if let Some(span) = duration.num_nanoseconds() {
+ if naive.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
+ return Err(RoundingError::TimestampExceedsLimit);
+ }
+ let stamp = naive.timestamp_nanos();
+ if span > stamp.abs() {
+ return Err(RoundingError::DurationExceedsTimestamp);
+ }
+ if span == 0 {
+ return Ok(original);
+ }
+ let delta_down = stamp % span;
+ if delta_down == 0 {
+ Ok(original)
+ } else {
+ let (delta_up, delta_down) = if delta_down < 0 {
+ (delta_down.abs(), span - delta_down.abs())
+ } else {
+ (span - delta_down, delta_down)
+ };
+ if delta_up <= delta_down {
+ Ok(original + Duration::nanoseconds(delta_up))
} else {
- let (delta_up, delta_down) = if delta_down < 0 {
- (delta_down.abs(), span - delta_down.abs())
- } else {
- (span - delta_down, delta_down)
- };
- if delta_up <= delta_down {
- Ok(self + Duration::nanoseconds(delta_up))
- } else {
- Ok(self - Duration::nanoseconds(delta_down))
- }
+ Ok(original - Duration::nanoseconds(delta_down))
}
- } else {
- Err(RoundingError::DurationExceedsLimit)
}
+ } else {
+ Err(RoundingError::DurationExceedsLimit)
}
+}
- fn duration_trunc(self, duration: Duration) -> Result<Self, Self::Err> {
- if let Some(span) = duration.num_nanoseconds() {
- if self.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
- return Err(RoundingError::TimestampExceedsLimit);
- }
- let stamp = self.timestamp_nanos();
- if span > stamp.abs() {
- return Err(RoundingError::DurationExceedsTimestamp);
- }
- let delta_down = stamp % span;
- match delta_down.cmp(&0) {
- Ordering::Equal => Ok(self),
- Ordering::Greater => Ok(self - Duration::nanoseconds(delta_down)),
- Ordering::Less => Ok(self - Duration::nanoseconds(span - delta_down.abs())),
- }
- } else {
- Err(RoundingError::DurationExceedsLimit)
+fn duration_trunc<T>(
+ naive: NaiveDateTime,
+ original: T,
+ duration: Duration,
+) -> Result<T, RoundingError>
+where
+ T: Timelike + Add<Duration, Output = T> + Sub<Duration, Output = T>,
+{
+ if let Some(span) = duration.num_nanoseconds() {
+ if naive.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
+ return Err(RoundingError::TimestampExceedsLimit);
+ }
+ let stamp = naive.timestamp_nanos();
+ if span > stamp.abs() {
+ return Err(RoundingError::DurationExceedsTimestamp);
}
+ let delta_down = stamp % span;
+ match delta_down.cmp(&0) {
+ Ordering::Equal => Ok(original),
+ Ordering::Greater => Ok(original - Duration::nanoseconds(delta_down)),
+ Ordering::Less => Ok(original - Duration::nanoseconds(span - delta_down.abs())),
+ }
+ } else {
+ Err(RoundingError::DurationExceedsLimit)
}
}
@@ -208,7 +244,7 @@ pub enum RoundingError {
///
/// ``` rust
/// # use chrono::{DateTime, DurationRound, Duration, RoundingError, TimeZone, Utc};
- /// let dt = Utc.ymd(1970, 12, 12).and_hms(0, 0, 0);
+ /// let dt = Utc.with_ymd_and_hms(1970, 12, 12, 0, 0, 0).unwrap();
///
/// assert_eq!(
/// dt.duration_round(Duration::days(365)),
@@ -220,8 +256,8 @@ pub enum RoundingError {
/// Error when `Duration.num_nanoseconds` exceeds the limit.
///
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, RoundingError, TimeZone, Utc};
- /// let dt = Utc.ymd(2260, 12, 31).and_hms_nano(23, 59, 59, 1_75_500_000);
+ /// # use chrono::{DateTime, DurationRound, Duration, RoundingError, TimeZone, Utc, NaiveDate};
+ /// let dt = NaiveDate::from_ymd_opt(2260, 12, 31).unwrap().and_hms_nano_opt(23, 59, 59, 1_75_500_000).unwrap().and_local_timezone(Utc).unwrap();
///
/// assert_eq!(
/// dt.duration_round(Duration::days(300 * 365)),
@@ -234,7 +270,7 @@ pub enum RoundingError {
///
/// ``` rust
/// # use chrono::{DateTime, DurationRound, Duration, RoundingError, TimeZone, Utc};
- /// let dt = Utc.ymd(2300, 12, 12).and_hms(0, 0, 0);
+ /// let dt = Utc.with_ymd_and_hms(2300, 12, 12, 0, 0, 0).unwrap();
///
/// assert_eq!(dt.duration_round(Duration::days(1)), Err(RoundingError::TimestampExceedsLimit),);
/// ```
@@ -258,6 +294,7 @@ impl fmt::Display for RoundingError {
}
#[cfg(any(feature = "std", test))]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for RoundingError {
#[allow(deprecated)]
fn description(&self) -> &str {
@@ -268,29 +305,44 @@ impl std::error::Error for RoundingError {
#[cfg(test)]
mod tests {
use super::{Duration, DurationRound, SubsecRound};
- use offset::{FixedOffset, TimeZone, Utc};
- use Timelike;
+ use crate::offset::{FixedOffset, TimeZone, Utc};
+ use crate::NaiveDate;
+ use crate::Timelike;
#[test]
fn test_round_subsecs() {
- let pst = FixedOffset::east(8 * 60 * 60);
- let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 084_660_684);
+ let pst = FixedOffset::east_opt(8 * 60 * 60).unwrap();
+ let dt = pst
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2018, 1, 11)
+ .unwrap()
+ .and_hms_nano_opt(10, 5, 13, 84_660_684)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(dt.round_subsecs(10), dt);
assert_eq!(dt.round_subsecs(9), dt);
- assert_eq!(dt.round_subsecs(8).nanosecond(), 084_660_680);
- assert_eq!(dt.round_subsecs(7).nanosecond(), 084_660_700);
- assert_eq!(dt.round_subsecs(6).nanosecond(), 084_661_000);
- assert_eq!(dt.round_subsecs(5).nanosecond(), 084_660_000);
- assert_eq!(dt.round_subsecs(4).nanosecond(), 084_700_000);
- assert_eq!(dt.round_subsecs(3).nanosecond(), 085_000_000);
- assert_eq!(dt.round_subsecs(2).nanosecond(), 080_000_000);
+ assert_eq!(dt.round_subsecs(8).nanosecond(), 84_660_680);
+ assert_eq!(dt.round_subsecs(7).nanosecond(), 84_660_700);
+ assert_eq!(dt.round_subsecs(6).nanosecond(), 84_661_000);
+ assert_eq!(dt.round_subsecs(5).nanosecond(), 84_660_000);
+ assert_eq!(dt.round_subsecs(4).nanosecond(), 84_700_000);
+ assert_eq!(dt.round_subsecs(3).nanosecond(), 85_000_000);
+ assert_eq!(dt.round_subsecs(2).nanosecond(), 80_000_000);
assert_eq!(dt.round_subsecs(1).nanosecond(), 100_000_000);
assert_eq!(dt.round_subsecs(0).nanosecond(), 0);
assert_eq!(dt.round_subsecs(0).second(), 13);
- let dt = Utc.ymd(2018, 1, 11).and_hms_nano(10, 5, 27, 750_500_000);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2018, 1, 11)
+ .unwrap()
+ .and_hms_nano_opt(10, 5, 27, 750_500_000)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(dt.round_subsecs(9), dt);
assert_eq!(dt.round_subsecs(4), dt);
assert_eq!(dt.round_subsecs(3).nanosecond(), 751_000_000);
@@ -303,7 +355,14 @@ mod tests {
#[test]
fn test_round_leap_nanos() {
- let dt = Utc.ymd(2016, 12, 31).and_hms_nano(23, 59, 59, 1_750_500_000);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2016, 12, 31)
+ .unwrap()
+ .and_hms_nano_opt(23, 59, 59, 1_750_500_000)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(dt.round_subsecs(9), dt);
assert_eq!(dt.round_subsecs(4), dt);
assert_eq!(dt.round_subsecs(2).nanosecond(), 1_750_000_000);
@@ -316,24 +375,38 @@ mod tests {
#[test]
fn test_trunc_subsecs() {
- let pst = FixedOffset::east(8 * 60 * 60);
- let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 084_660_684);
+ let pst = FixedOffset::east_opt(8 * 60 * 60).unwrap();
+ let dt = pst
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2018, 1, 11)
+ .unwrap()
+ .and_hms_nano_opt(10, 5, 13, 84_660_684)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(dt.trunc_subsecs(10), dt);
assert_eq!(dt.trunc_subsecs(9), dt);
- assert_eq!(dt.trunc_subsecs(8).nanosecond(), 084_660_680);
- assert_eq!(dt.trunc_subsecs(7).nanosecond(), 084_660_600);
- assert_eq!(dt.trunc_subsecs(6).nanosecond(), 084_660_000);
- assert_eq!(dt.trunc_subsecs(5).nanosecond(), 084_660_000);
- assert_eq!(dt.trunc_subsecs(4).nanosecond(), 084_600_000);
- assert_eq!(dt.trunc_subsecs(3).nanosecond(), 084_000_000);
- assert_eq!(dt.trunc_subsecs(2).nanosecond(), 080_000_000);
+ assert_eq!(dt.trunc_subsecs(8).nanosecond(), 84_660_680);
+ assert_eq!(dt.trunc_subsecs(7).nanosecond(), 84_660_600);
+ assert_eq!(dt.trunc_subsecs(6).nanosecond(), 84_660_000);
+ assert_eq!(dt.trunc_subsecs(5).nanosecond(), 84_660_000);
+ assert_eq!(dt.trunc_subsecs(4).nanosecond(), 84_600_000);
+ assert_eq!(dt.trunc_subsecs(3).nanosecond(), 84_000_000);
+ assert_eq!(dt.trunc_subsecs(2).nanosecond(), 80_000_000);
assert_eq!(dt.trunc_subsecs(1).nanosecond(), 0);
assert_eq!(dt.trunc_subsecs(0).nanosecond(), 0);
assert_eq!(dt.trunc_subsecs(0).second(), 13);
- let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 27, 750_500_000);
+ let dt = pst
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2018, 1, 11)
+ .unwrap()
+ .and_hms_nano_opt(10, 5, 27, 750_500_000)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(dt.trunc_subsecs(9), dt);
assert_eq!(dt.trunc_subsecs(4), dt);
assert_eq!(dt.trunc_subsecs(3).nanosecond(), 750_000_000);
@@ -346,7 +419,14 @@ mod tests {
#[test]
fn test_trunc_leap_nanos() {
- let dt = Utc.ymd(2016, 12, 31).and_hms_nano(23, 59, 59, 1_750_500_000);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2016, 12, 31)
+ .unwrap()
+ .and_hms_nano_opt(23, 59, 59, 1_750_500_000)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(dt.trunc_subsecs(9), dt);
assert_eq!(dt.trunc_subsecs(4), dt);
assert_eq!(dt.trunc_subsecs(2).nanosecond(), 1_750_000_000);
@@ -359,7 +439,19 @@ mod tests {
#[test]
fn test_duration_round() {
- let dt = Utc.ymd(2016, 12, 31).and_hms_nano(23, 59, 59, 175_500_000);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2016, 12, 31)
+ .unwrap()
+ .and_hms_nano_opt(23, 59, 59, 175_500_000)
+ .unwrap(),
+ )
+ .unwrap();
+
+ assert_eq!(
+ dt.duration_round(Duration::zero()).unwrap().to_string(),
+ "2016-12-31 23:59:59.175500 UTC"
+ );
assert_eq!(
dt.duration_round(Duration::milliseconds(10)).unwrap().to_string(),
@@ -367,13 +459,27 @@ mod tests {
);
// round up
- let dt = Utc.ymd(2012, 12, 12).and_hms_milli(18, 22, 30, 0);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 30, 0)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(
dt.duration_round(Duration::minutes(5)).unwrap().to_string(),
"2012-12-12 18:25:00 UTC"
);
// round down
- let dt = Utc.ymd(2012, 12, 12).and_hms_milli(18, 22, 29, 999);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 29, 999)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(
dt.duration_round(Duration::minutes(5)).unwrap().to_string(),
"2012-12-12 18:20:00 UTC"
@@ -395,11 +501,104 @@ mod tests {
dt.duration_round(Duration::days(1)).unwrap().to_string(),
"2012-12-13 00:00:00 UTC"
);
+
+ // timezone east
+ let dt =
+ FixedOffset::east_opt(3600).unwrap().with_ymd_and_hms(2020, 10, 27, 15, 0, 0).unwrap();
+ assert_eq!(
+ dt.duration_round(Duration::days(1)).unwrap().to_string(),
+ "2020-10-28 00:00:00 +01:00"
+ );
+ assert_eq!(
+ dt.duration_round(Duration::weeks(1)).unwrap().to_string(),
+ "2020-10-29 00:00:00 +01:00"
+ );
+
+ // timezone west
+ let dt =
+ FixedOffset::west_opt(3600).unwrap().with_ymd_and_hms(2020, 10, 27, 15, 0, 0).unwrap();
+ assert_eq!(
+ dt.duration_round(Duration::days(1)).unwrap().to_string(),
+ "2020-10-28 00:00:00 -01:00"
+ );
+ assert_eq!(
+ dt.duration_round(Duration::weeks(1)).unwrap().to_string(),
+ "2020-10-29 00:00:00 -01:00"
+ );
+ }
+
+ #[test]
+ fn test_duration_round_naive() {
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2016, 12, 31)
+ .unwrap()
+ .and_hms_nano_opt(23, 59, 59, 175_500_000)
+ .unwrap(),
+ )
+ .unwrap()
+ .naive_utc();
+
+ assert_eq!(
+ dt.duration_round(Duration::zero()).unwrap().to_string(),
+ "2016-12-31 23:59:59.175500"
+ );
+
+ assert_eq!(
+ dt.duration_round(Duration::milliseconds(10)).unwrap().to_string(),
+ "2016-12-31 23:59:59.180"
+ );
+
+ // round up
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 30, 0)
+ .unwrap(),
+ )
+ .unwrap()
+ .naive_utc();
+ assert_eq!(
+ dt.duration_round(Duration::minutes(5)).unwrap().to_string(),
+ "2012-12-12 18:25:00"
+ );
+ // round down
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 29, 999)
+ .unwrap(),
+ )
+ .unwrap()
+ .naive_utc();
+ assert_eq!(
+ dt.duration_round(Duration::minutes(5)).unwrap().to_string(),
+ "2012-12-12 18:20:00"
+ );
+
+ assert_eq!(
+ dt.duration_round(Duration::minutes(10)).unwrap().to_string(),
+ "2012-12-12 18:20:00"
+ );
+ assert_eq!(
+ dt.duration_round(Duration::minutes(30)).unwrap().to_string(),
+ "2012-12-12 18:30:00"
+ );
+ assert_eq!(
+ dt.duration_round(Duration::hours(1)).unwrap().to_string(),
+ "2012-12-12 18:00:00"
+ );
+ assert_eq!(
+ dt.duration_round(Duration::days(1)).unwrap().to_string(),
+ "2012-12-13 00:00:00"
+ );
}
#[test]
fn test_duration_round_pre_epoch() {
- let dt = Utc.ymd(1969, 12, 12).and_hms(12, 12, 12);
+ let dt = Utc.with_ymd_and_hms(1969, 12, 12, 12, 12, 12).unwrap();
assert_eq!(
dt.duration_round(Duration::minutes(10)).unwrap().to_string(),
"1969-12-12 12:10:00 UTC"
@@ -408,7 +607,14 @@ mod tests {
#[test]
fn test_duration_trunc() {
- let dt = Utc.ymd(2016, 12, 31).and_hms_nano(23, 59, 59, 1_75_500_000);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2016, 12, 31)
+ .unwrap()
+ .and_hms_nano_opt(23, 59, 59, 175_500_000)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(
dt.duration_trunc(Duration::milliseconds(10)).unwrap().to_string(),
@@ -416,13 +622,27 @@ mod tests {
);
// would round up
- let dt = Utc.ymd(2012, 12, 12).and_hms_milli(18, 22, 30, 0);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 30, 0)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(
dt.duration_trunc(Duration::minutes(5)).unwrap().to_string(),
"2012-12-12 18:20:00 UTC"
);
// would round down
- let dt = Utc.ymd(2012, 12, 12).and_hms_milli(18, 22, 29, 999);
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 29, 999)
+ .unwrap(),
+ )
+ .unwrap();
assert_eq!(
dt.duration_trunc(Duration::minutes(5)).unwrap().to_string(),
"2012-12-12 18:20:00 UTC"
@@ -443,11 +663,98 @@ mod tests {
dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
"2012-12-12 00:00:00 UTC"
);
+
+ // timezone east
+ let dt =
+ FixedOffset::east_opt(3600).unwrap().with_ymd_and_hms(2020, 10, 27, 15, 0, 0).unwrap();
+ assert_eq!(
+ dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
+ "2020-10-27 00:00:00 +01:00"
+ );
+ assert_eq!(
+ dt.duration_trunc(Duration::weeks(1)).unwrap().to_string(),
+ "2020-10-22 00:00:00 +01:00"
+ );
+
+ // timezone west
+ let dt =
+ FixedOffset::west_opt(3600).unwrap().with_ymd_and_hms(2020, 10, 27, 15, 0, 0).unwrap();
+ assert_eq!(
+ dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
+ "2020-10-27 00:00:00 -01:00"
+ );
+ assert_eq!(
+ dt.duration_trunc(Duration::weeks(1)).unwrap().to_string(),
+ "2020-10-22 00:00:00 -01:00"
+ );
+ }
+
+ #[test]
+ fn test_duration_trunc_naive() {
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2016, 12, 31)
+ .unwrap()
+ .and_hms_nano_opt(23, 59, 59, 175_500_000)
+ .unwrap(),
+ )
+ .unwrap()
+ .naive_utc();
+
+ assert_eq!(
+ dt.duration_trunc(Duration::milliseconds(10)).unwrap().to_string(),
+ "2016-12-31 23:59:59.170"
+ );
+
+ // would round up
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 30, 0)
+ .unwrap(),
+ )
+ .unwrap()
+ .naive_utc();
+ assert_eq!(
+ dt.duration_trunc(Duration::minutes(5)).unwrap().to_string(),
+ "2012-12-12 18:20:00"
+ );
+ // would round down
+ let dt = Utc
+ .from_local_datetime(
+ &NaiveDate::from_ymd_opt(2012, 12, 12)
+ .unwrap()
+ .and_hms_milli_opt(18, 22, 29, 999)
+ .unwrap(),
+ )
+ .unwrap()
+ .naive_utc();
+ assert_eq!(
+ dt.duration_trunc(Duration::minutes(5)).unwrap().to_string(),
+ "2012-12-12 18:20:00"
+ );
+ assert_eq!(
+ dt.duration_trunc(Duration::minutes(10)).unwrap().to_string(),
+ "2012-12-12 18:20:00"
+ );
+ assert_eq!(
+ dt.duration_trunc(Duration::minutes(30)).unwrap().to_string(),
+ "2012-12-12 18:00:00"
+ );
+ assert_eq!(
+ dt.duration_trunc(Duration::hours(1)).unwrap().to_string(),
+ "2012-12-12 18:00:00"
+ );
+ assert_eq!(
+ dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
+ "2012-12-12 00:00:00"
+ );
}
#[test]
fn test_duration_trunc_pre_epoch() {
- let dt = Utc.ymd(1969, 12, 12).and_hms(12, 12, 12);
+ let dt = Utc.with_ymd_and_hms(1969, 12, 12, 12, 12, 12).unwrap();
assert_eq!(
dt.duration_trunc(Duration::minutes(10)).unwrap().to_string(),
"1969-12-12 12:10:00 UTC"