make the API even more similar
This commit is contained in:
parent
05b6503851
commit
83c84bb31d
21
CHANGELOG.md
21
CHANGELOG.md
@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
# [unreleased]
|
||||
|
||||
Major API changes for the time API. If you are using the time API, it is strongly recommended
|
||||
to check all the API changes.
|
||||
to check all the API changes in the **Changed** chapter.
|
||||
|
||||
## Fixed
|
||||
|
||||
@ -21,18 +21,23 @@ to check all the API changes.
|
||||
|
||||
- `From<$EcssEnum$TY> from $TY` for the ECSS enum type definitions.
|
||||
- Added basic support conversions to the `time` library. Introduce new `chrono` and `timelib`
|
||||
feature gate
|
||||
feature gate.
|
||||
- Added `CcsdsTimeProvider::timelib_date_time`.
|
||||
|
||||
## Changed
|
||||
|
||||
- `UnixTimestamp::new` renamed to `UnixTimestamp::new_checked`.
|
||||
- `UnixTimestamp` now has a nanosecond subsecond precision. The `new` constructor now expects
|
||||
- Renamed `CcsdsTimeProvider::date_time` to `CcsdsTimeProvider::chrono_date_time`.
|
||||
- `UnixTimestamp` renamed to `UnixTime`
|
||||
- `UnixTime` seconds are now private and can be retrieved using the `secs` member method.
|
||||
- `UnixTime::new` renamed to `UnixTime::new_checked`.
|
||||
- `UnixTime` now has a nanosecond subsecond precision. The `new` constructor now expects
|
||||
nanoseconds as the second argument.
|
||||
- Added new `UnixTimestamp::new_subsec_millis` and `UnixTimestamp::new_subsec_millis_checked` API
|
||||
- Added new `UnixTime::new_subsec_millis` and `UnixTime::new_subsec_millis_checked` API
|
||||
to still allow creating a timestamp with only millisecond subsecond resolution.
|
||||
- `CcsdsTimeProvider` now has a new `subsecond_nanos` method in addition to a default
|
||||
implementation for the `subsecond_millis` method.
|
||||
- `CcsdsTimeProvider::date_time` renamed to `CcsdsTimeProvider::chrono_date_time`
|
||||
- `CcsdsTimeProvider` now has a new `subsec_nanos` method in addition to a default
|
||||
implementation for the `subsec_millis` method.
|
||||
- `CcsdsTimeProvider::date_time` renamed to `CcsdsTimeProvider::chrono_date_time`.
|
||||
- Added `UnixTime::MIN`, `UnixTime::MAX` and `UnixTime::EPOCH`.
|
||||
|
||||
# [v0.11.0-rc.0] 2024-03-04
|
||||
|
||||
|
@ -35,7 +35,7 @@ use serde::{Serialize, Deserialize};
|
||||
|
||||
use super::{
|
||||
ccsds_to_unix_days, unix_to_ccsds_days, CcsdsTimeCodes, CcsdsTimeProvider, TimeReader,
|
||||
TimeWriter, TimestampError, UnixTimestamp, MS_PER_DAY, SECONDS_PER_DAY,
|
||||
TimeWriter, TimestampError, UnixTime, MS_PER_DAY, SECONDS_PER_DAY,
|
||||
};
|
||||
|
||||
/// Base value for the preamble field for a time field parser to determine the time field type.
|
||||
@ -188,7 +188,7 @@ pub struct TimeProvider<DaysLen: ProvidesDaysLength = DaysLen16Bits> {
|
||||
submillis: u32,
|
||||
/// This is not strictly necessary but still cached because it significantly simplifies the
|
||||
/// calculation of [`DateTime<Utc>`].
|
||||
unix_stamp: UnixTimestamp,
|
||||
unix_stamp: UnixTime,
|
||||
}
|
||||
|
||||
/// Common properties for all CDS time providers.
|
||||
@ -231,7 +231,7 @@ impl ConversionFromUnix {
|
||||
let ccsds_days = unix_to_ccsds_days(unix_days);
|
||||
if ccsds_days == 0 && (secs_of_day > 0 || subsec_nanos > 0) || ccsds_days < 0 {
|
||||
return Err(TimestampError::DateBeforeCcsdsEpoch(
|
||||
UnixTimestamp::new_checked(unix_seconds, subsec_nanos)
|
||||
UnixTime::new_checked(unix_seconds, subsec_nanos)
|
||||
.expect("unix timestamp creation failed"),
|
||||
));
|
||||
}
|
||||
@ -341,7 +341,7 @@ impl ConversionFromChronoDatetime {
|
||||
) -> Result<Self, TimestampError> {
|
||||
// The CDS timestamp does not support timestamps before the CCSDS epoch.
|
||||
if dt.year() < 1958 {
|
||||
return Err(TimestampError::DateBeforeCcsdsEpoch(UnixTimestamp::from(
|
||||
return Err(TimestampError::DateBeforeCcsdsEpoch(UnixTime::from(
|
||||
*dt,
|
||||
)));
|
||||
}
|
||||
@ -643,7 +643,7 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
|
||||
if let Some(precision) = self.precision_as_ns() {
|
||||
subsec_nanos += precision;
|
||||
}
|
||||
self.unix_stamp = UnixTimestamp::new(unix_days_seconds, subsec_nanos);
|
||||
self.unix_stamp = UnixTime::new(unix_days_seconds, subsec_nanos);
|
||||
}
|
||||
|
||||
fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), TimestampError> {
|
||||
@ -706,13 +706,13 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
|
||||
}
|
||||
|
||||
fn from_unix_generic(
|
||||
unix_stamp: &UnixTimestamp,
|
||||
unix_stamp: &UnixTime,
|
||||
days_len: LengthOfDaySegment,
|
||||
submillis_prec: SubmillisPrecision,
|
||||
) -> Result<Self, TimestampError> {
|
||||
let conv_from_dt = ConversionFromUnix::new(
|
||||
unix_stamp.unix_seconds,
|
||||
unix_stamp.subsecond_nanos,
|
||||
unix_stamp.secs,
|
||||
unix_stamp.subsec_nanos,
|
||||
submillis_prec,
|
||||
)?;
|
||||
Self::generic_from_conversion(days_len, conv_from_dt)
|
||||
@ -844,7 +844,7 @@ impl TimeProvider<DaysLen24Bits> {
|
||||
/// [TimestampError::Cds] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00)
|
||||
/// or the CCSDS days value exceeds the allowed bit width (24 bits).
|
||||
pub fn from_unix_stamp_with_u24_days(
|
||||
unix_stamp: &UnixTimestamp,
|
||||
unix_stamp: &UnixTime,
|
||||
submillis_prec: SubmillisPrecision,
|
||||
) -> Result<Self, TimestampError> {
|
||||
Self::from_unix_generic(unix_stamp, LengthOfDaySegment::Long24Bits, submillis_prec)
|
||||
@ -941,7 +941,7 @@ impl TimeProvider<DaysLen16Bits> {
|
||||
/// [TimestampError::Cds] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00)
|
||||
/// or the CCSDS days value exceeds the allowed bit width (24 bits).
|
||||
pub fn from_unix_stamp_with_u16_days(
|
||||
unix_stamp: &UnixTimestamp,
|
||||
unix_stamp: &UnixTime,
|
||||
submillis_prec: SubmillisPrecision,
|
||||
) -> Result<Self, TimestampError> {
|
||||
Self::from_unix_generic(unix_stamp, LengthOfDaySegment::Short16Bits, submillis_prec)
|
||||
@ -1205,16 +1205,16 @@ impl<ProvidesDaysLen: ProvidesDaysLength> CcsdsTimeProvider for TimeProvider<Pro
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unix_seconds(&self) -> i64 {
|
||||
self.unix_stamp.unix_seconds
|
||||
fn unix_secs(&self) -> i64 {
|
||||
self.unix_stamp.secs
|
||||
}
|
||||
#[inline]
|
||||
fn subsecond_nanos(&self) -> u32 {
|
||||
self.unix_stamp.subsecond_nanos
|
||||
fn subsec_nanos(&self) -> u32 {
|
||||
self.unix_stamp.subsec_nanos
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unix_stamp(&self) -> UnixTimestamp {
|
||||
fn unix_stamp(&self) -> UnixTime {
|
||||
self.unix_stamp
|
||||
}
|
||||
}
|
||||
@ -1351,7 +1351,7 @@ impl TryFrom<TimeProvider<DaysLen24Bits>> for TimeProvider<DaysLen16Bits> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::time::TimestampError::{ByteConversion, InvalidTimeCode};
|
||||
use crate::time::{UnixTimestamp, DAYS_CCSDS_TO_UNIX, MS_PER_DAY};
|
||||
use crate::time::{UnixTime, DAYS_CCSDS_TO_UNIX, MS_PER_DAY};
|
||||
use crate::ByteConversionError::{FromSliceTooSmall, ToSliceTooSmall};
|
||||
use alloc::string::ToString;
|
||||
use chrono::{Datelike, NaiveDate, Timelike};
|
||||
@ -1364,16 +1364,16 @@ mod tests {
|
||||
let time_stamper = TimeProvider::new_with_u16_days(0, 0);
|
||||
let unix_stamp = time_stamper.unix_stamp();
|
||||
assert_eq!(
|
||||
unix_stamp.unix_seconds,
|
||||
unix_stamp.secs,
|
||||
(DAYS_CCSDS_TO_UNIX * SECONDS_PER_DAY as i32) as i64
|
||||
);
|
||||
let subsecond_millis = unix_stamp.subsecond_nanos;
|
||||
let subsecond_millis = unix_stamp.subsec_nanos;
|
||||
assert_eq!(subsecond_millis, 0);
|
||||
assert_eq!(
|
||||
time_stamper.submillis_precision(),
|
||||
SubmillisPrecision::Absent
|
||||
);
|
||||
assert_eq!(time_stamper.subsecond_nanos(), 0);
|
||||
assert_eq!(time_stamper.subsec_nanos(), 0);
|
||||
assert_eq!(time_stamper.ccdsd_time_code(), CcsdsTimeCodes::Cds);
|
||||
assert_eq!(
|
||||
time_stamper.p_field(),
|
||||
@ -1391,7 +1391,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_time_stamp_unix_epoch() {
|
||||
let time_stamper = TimeProvider::new_with_u16_days((-DAYS_CCSDS_TO_UNIX) as u16, 0);
|
||||
assert_eq!(time_stamper.unix_stamp().unix_seconds, 0);
|
||||
assert_eq!(time_stamper.unix_stamp().secs, 0);
|
||||
assert_eq!(
|
||||
time_stamper.submillis_precision(),
|
||||
SubmillisPrecision::Absent
|
||||
@ -1404,11 +1404,11 @@ mod tests {
|
||||
assert_eq!(date_time.minute(), 0);
|
||||
assert_eq!(date_time.second(), 0);
|
||||
let time_stamper = TimeProvider::new_with_u16_days((-DAYS_CCSDS_TO_UNIX) as u16, 40);
|
||||
assert_eq!(time_stamper.subsecond_nanos(), 40 * 10_u32.pow(6));
|
||||
assert_eq!(time_stamper.subsecond_millis(), 40);
|
||||
assert_eq!(time_stamper.subsec_nanos(), 40 * 10_u32.pow(6));
|
||||
assert_eq!(time_stamper.subsec_millis(), 40);
|
||||
let time_stamper = TimeProvider::new_with_u16_days((-DAYS_CCSDS_TO_UNIX) as u16, 1040);
|
||||
assert_eq!(time_stamper.subsecond_nanos(), 40 * 10_u32.pow(6));
|
||||
assert_eq!(time_stamper.subsecond_millis(), 40);
|
||||
assert_eq!(time_stamper.subsec_nanos(), 40 * 10_u32.pow(6));
|
||||
assert_eq!(time_stamper.subsec_millis(), 40);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1470,7 +1470,7 @@ mod tests {
|
||||
let time_stamper_0 = TimeProvider::new_with_u16_days(0, 0);
|
||||
let unix_stamp = time_stamper_0.unix_stamp();
|
||||
assert_eq!(
|
||||
unix_stamp.unix_seconds,
|
||||
unix_stamp.secs,
|
||||
(DAYS_CCSDS_TO_UNIX * SECONDS_PER_DAY as i32).into()
|
||||
);
|
||||
let mut res = time_stamper_0.write_to_bytes(&mut buf);
|
||||
@ -1932,7 +1932,7 @@ mod tests {
|
||||
let unix_secs = 0;
|
||||
let subsec_millis = 0;
|
||||
let time_provider = TimeProvider::from_unix_stamp_with_u16_days(
|
||||
&UnixTimestamp::new(unix_secs, subsec_millis),
|
||||
&UnixTime::new(unix_secs, subsec_millis),
|
||||
SubmillisPrecision::Absent,
|
||||
)
|
||||
.expect("creating provider from unix stamp failed");
|
||||
@ -1944,7 +1944,7 @@ mod tests {
|
||||
let unix_secs = 0;
|
||||
let subsec_millis = 0;
|
||||
let time_provider = TimeProvider::from_unix_stamp_with_u24_days(
|
||||
&UnixTimestamp::new(unix_secs, subsec_millis),
|
||||
&UnixTime::new(unix_secs, subsec_millis),
|
||||
SubmillisPrecision::Absent,
|
||||
)
|
||||
.expect("creating provider from unix stamp failed");
|
||||
@ -1981,7 +1981,7 @@ mod tests {
|
||||
let unix_secs = DAYS_CCSDS_TO_UNIX as i64 * SECONDS_PER_DAY as i64;
|
||||
let subsec_millis = 0;
|
||||
let time_provider = TimeProvider::from_unix_stamp_with_u16_days(
|
||||
&UnixTimestamp::new(unix_secs, subsec_millis),
|
||||
&UnixTime::new(unix_secs, subsec_millis),
|
||||
SubmillisPrecision::Absent,
|
||||
)
|
||||
.expect("creating provider from unix stamp failed");
|
||||
@ -1993,7 +1993,7 @@ mod tests {
|
||||
let invalid_unix_secs: i64 = (u16::MAX as i64 + 1) * SECONDS_PER_DAY as i64;
|
||||
let subsec_millis = 0;
|
||||
match TimeProvider::from_unix_stamp_with_u16_days(
|
||||
&UnixTimestamp::new(invalid_unix_secs, subsec_millis),
|
||||
&UnixTime::new(invalid_unix_secs, subsec_millis),
|
||||
SubmillisPrecision::Absent,
|
||||
) {
|
||||
Ok(_) => {
|
||||
@ -2020,7 +2020,7 @@ mod tests {
|
||||
let unix_secs = DAYS_CCSDS_TO_UNIX * SECONDS_PER_DAY as i32 - 5;
|
||||
let subsec_millis = 0;
|
||||
match TimeProvider::from_unix_stamp_with_u16_days(
|
||||
&UnixTimestamp::new(unix_secs as i64, subsec_millis),
|
||||
&UnixTime::new(unix_secs as i64, subsec_millis),
|
||||
SubmillisPrecision::Absent,
|
||||
) {
|
||||
Ok(_) => {
|
||||
@ -2028,7 +2028,7 @@ mod tests {
|
||||
}
|
||||
Err(e) => {
|
||||
if let TimestampError::DateBeforeCcsdsEpoch(dt) = e {
|
||||
let dt = dt.as_date_time();
|
||||
let dt = dt.chrono_date_time();
|
||||
if let chrono::LocalResult::Single(dt) = dt {
|
||||
assert_eq!(dt.year(), 1957);
|
||||
assert_eq!(dt.month(), 12);
|
||||
@ -2304,7 +2304,7 @@ mod tests {
|
||||
fn test_update_from_now() {
|
||||
let mut stamp = TimeProvider::new_with_u16_days(0, 0);
|
||||
let _ = stamp.update_from_now();
|
||||
let dt = stamp.unix_stamp().as_date_time().unwrap();
|
||||
let dt = stamp.unix_stamp().chrono_date_time().unwrap();
|
||||
assert!(dt.year() > 2020);
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,12 @@ use core::u64;
|
||||
|
||||
use crate::ByteConversionError;
|
||||
|
||||
use super::{CcsdsTimeCodes, TimestampError, unix_epoch_to_ccsds_epoch, UnixTimestamp, ccsds_epoch_to_unix_epoch, TimeReader, TimeWriter, CcsdsTimeProvider};
|
||||
#[cfg(feature = "std")]
|
||||
use super::StdTimestampError;
|
||||
use super::{
|
||||
ccsds_epoch_to_unix_epoch, unix_epoch_to_ccsds_epoch, CcsdsTimeCodes, CcsdsTimeProvider,
|
||||
TimeReader, TimeWriter, TimestampError, UnixTime,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
#[cfg(feature = "std")]
|
||||
@ -315,7 +318,6 @@ impl TimeProviderCcsdsEpoch {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
pub fn update_from_now(&mut self) -> Result<(), StdTimestampError> {
|
||||
|
||||
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
|
||||
self.counter.1 = unix_epoch_to_ccsds_epoch(now.as_secs() as i64) as u32;
|
||||
self.counter
|
||||
@ -340,9 +342,7 @@ impl TimeProviderCcsdsEpoch {
|
||||
) -> Result<Self, TimestampError> {
|
||||
// Year before CCSDS epoch is invalid.
|
||||
if dt.year() < 1958 {
|
||||
return Err(TimestampError::DateBeforeCcsdsEpoch(UnixTimestamp::from(
|
||||
*dt,
|
||||
)));
|
||||
return Err(TimestampError::DateBeforeCcsdsEpoch(UnixTime::from(*dt)));
|
||||
}
|
||||
let counter = dt
|
||||
.timestamp()
|
||||
@ -359,11 +359,11 @@ impl TimeProviderCcsdsEpoch {
|
||||
/// Generates a CUC timestamp from a UNIX timestamp with a width of 4. This width is able
|
||||
/// to accomodate all possible UNIX timestamp values.
|
||||
pub fn from_unix_stamp(
|
||||
unix_stamp: &UnixTimestamp,
|
||||
unix_stamp: &UnixTime,
|
||||
res: FractionalResolution,
|
||||
leap_seconds: u32,
|
||||
) -> Result<Self, TimestampError> {
|
||||
let ccsds_epoch = unix_epoch_to_ccsds_epoch(unix_stamp.unix_seconds);
|
||||
let ccsds_epoch = unix_epoch_to_ccsds_epoch(unix_stamp.secs);
|
||||
// Negative CCSDS epoch is invalid.
|
||||
if ccsds_epoch < 0 {
|
||||
return Err(TimestampError::DateBeforeCcsdsEpoch(*unix_stamp));
|
||||
@ -371,10 +371,8 @@ impl TimeProviderCcsdsEpoch {
|
||||
ccsds_epoch
|
||||
.checked_add(i64::from(leap_seconds))
|
||||
.ok_or(TimestampError::Cuc(CucError::LeapSecondCorrectionError))?;
|
||||
let fractions = fractional_part_from_subsec_ns(
|
||||
res,
|
||||
unix_stamp.subsecond_millis() as u64 * 10_u64.pow(6),
|
||||
);
|
||||
let fractions =
|
||||
fractional_part_from_subsec_ns(res, unix_stamp.subsec_millis() as u64 * 10_u64.pow(6));
|
||||
Self::new_generic(
|
||||
WidthCounterPair(4, ccsds_epoch as u32),
|
||||
fractions,
|
||||
@ -693,11 +691,11 @@ impl CcsdsTimeProvider for TimeProviderCcsdsEpoch {
|
||||
CcsdsTimeCodes::CucCcsdsEpoch
|
||||
}
|
||||
|
||||
fn unix_seconds(&self) -> i64 {
|
||||
fn unix_secs(&self) -> i64 {
|
||||
self.unix_seconds()
|
||||
}
|
||||
|
||||
fn subsecond_nanos(&self) -> u32 {
|
||||
fn subsec_nanos(&self) -> u32 {
|
||||
if let Some(fractions) = self.fractions {
|
||||
if fractions.0 == FractionalResolution::Seconds {
|
||||
return 0;
|
||||
@ -806,7 +804,7 @@ impl Add<Duration> for &TimeProviderCcsdsEpoch {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::time::{UnixTimestamp, DAYS_CCSDS_TO_UNIX, SECONDS_PER_DAY};
|
||||
use crate::time::{UnixTime, DAYS_CCSDS_TO_UNIX, SECONDS_PER_DAY};
|
||||
|
||||
use super::*;
|
||||
use alloc::string::ToString;
|
||||
@ -852,7 +850,7 @@ mod tests {
|
||||
let zero_cuc = zero_cuc.unwrap();
|
||||
let res = zero_cuc.write_to_bytes(&mut buf);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(zero_cuc.subsecond_nanos(), 0);
|
||||
assert_eq!(zero_cuc.subsec_nanos(), 0);
|
||||
assert_eq!(zero_cuc.len_as_bytes(), 5);
|
||||
assert_eq!(pfield_len(buf[0]), 1);
|
||||
let written = res.unwrap();
|
||||
@ -1245,7 +1243,7 @@ mod tests {
|
||||
// What I would roughly expect
|
||||
assert_eq!(cuc_stamp2.counter.1, 203);
|
||||
assert!(cuc_stamp2.fractions.unwrap().1 < 100);
|
||||
assert!(cuc_stamp2.subsecond_millis() <= 1);
|
||||
assert!(cuc_stamp2.subsec_millis() <= 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1327,7 +1325,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn from_unix_stamp() {
|
||||
let unix_stamp = UnixTimestamp::new(0, 0);
|
||||
let unix_stamp = UnixTime::new(0, 0);
|
||||
let cuc = TimeProviderCcsdsEpoch::from_unix_stamp(
|
||||
&unix_stamp,
|
||||
FractionalResolution::Seconds,
|
||||
|
249
src/time/mod.rs
249
src/time/mod.rs
@ -29,6 +29,7 @@ pub mod cuc;
|
||||
pub const DAYS_CCSDS_TO_UNIX: i32 = -4383;
|
||||
pub const SECONDS_PER_DAY: u32 = 86400;
|
||||
pub const MS_PER_DAY: u32 = SECONDS_PER_DAY * 1000;
|
||||
pub const NANOS_PER_SECOND: u32 = 1_000_000_000;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
@ -70,7 +71,7 @@ pub enum TimestampError {
|
||||
ByteConversion(ByteConversionError),
|
||||
Cds(cds::CdsError),
|
||||
Cuc(cuc::CucError),
|
||||
DateBeforeCcsdsEpoch(UnixTimestamp),
|
||||
DateBeforeCcsdsEpoch(UnixTime),
|
||||
CustomEpochNotSupported,
|
||||
}
|
||||
|
||||
@ -232,21 +233,21 @@ pub trait CcsdsTimeProvider {
|
||||
fn p_field(&self) -> (usize, [u8; 2]);
|
||||
fn ccdsd_time_code(&self) -> CcsdsTimeCodes;
|
||||
|
||||
fn unix_seconds(&self) -> i64;
|
||||
fn subsecond_nanos(&self) -> u32;
|
||||
fn unix_secs(&self) -> i64;
|
||||
fn subsec_nanos(&self) -> u32;
|
||||
|
||||
fn subsecond_millis(&self) -> u16 {
|
||||
(self.subsecond_nanos() / 1_000_000) as u16
|
||||
fn subsec_millis(&self) -> u16 {
|
||||
(self.subsec_nanos() / 1_000_000) as u16
|
||||
}
|
||||
|
||||
fn unix_stamp(&self) -> UnixTimestamp {
|
||||
UnixTimestamp::new(self.unix_seconds(), self.subsecond_nanos())
|
||||
fn unix_stamp(&self) -> UnixTime {
|
||||
UnixTime::new(self.unix_secs(), self.subsec_nanos())
|
||||
}
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "chrono")))]
|
||||
fn chrono_date_time(&self) -> chrono::LocalResult<chrono::DateTime<chrono::Utc>> {
|
||||
chrono::Utc.timestamp_opt(self.unix_seconds(), self.subsecond_nanos())
|
||||
chrono::Utc.timestamp_opt(self.unix_secs(), self.subsec_nanos())
|
||||
}
|
||||
|
||||
#[cfg(feature = "timelib")]
|
||||
@ -259,22 +260,41 @@ pub trait CcsdsTimeProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/// UNIX timestamp: Elapsed seconds since 1970-01-01T00:00:00+00:00.
|
||||
/// UNIX time: Elapsed non-leap seconds since 1970-01-01T00:00:00+00:00 UTC.
|
||||
///
|
||||
/// Also can optionally include subsecond millisecond for greater accuracy.
|
||||
/// It is assumed that leap second correction was already applied and the reference time is UTC.
|
||||
/// This is a commonly used time format and can therefore also be used as a generic format to
|
||||
/// convert other CCSDS time formats to and from. The subsecond precision is in nanoseconds
|
||||
/// similarly to other common time formats and libraries.
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct UnixTimestamp {
|
||||
pub unix_seconds: i64,
|
||||
subsecond_nanos: u32,
|
||||
pub struct UnixTime {
|
||||
secs: i64,
|
||||
subsec_nanos: u32,
|
||||
}
|
||||
|
||||
impl UnixTimestamp {
|
||||
impl UnixTime {
|
||||
/// The UNIX epoch time: 1970-01-01T00:00:00+00:00 UTC.
|
||||
pub const EPOCH: Self = Self {
|
||||
secs: 0,
|
||||
subsec_nanos: 0,
|
||||
};
|
||||
|
||||
/// The minimum possible `UnixTime`.
|
||||
pub const MIN: Self = Self {
|
||||
secs: i64::MIN,
|
||||
subsec_nanos: 0,
|
||||
};
|
||||
|
||||
/// The maximum possible `UnixTime`.
|
||||
pub const MAX: Self = Self {
|
||||
secs: i64::MAX,
|
||||
subsec_nanos: NANOS_PER_SECOND - 1,
|
||||
};
|
||||
|
||||
/// Returns [None] if the subsecond nanosecond value is invalid (larger than fraction of a
|
||||
/// second)
|
||||
pub fn new_checked(unix_seconds: i64, subsec_nanos: u32) -> Option<Self> {
|
||||
if subsec_nanos > 1_000_000_000 - 1 {
|
||||
if subsec_nanos >= NANOS_PER_SECOND {
|
||||
return None;
|
||||
}
|
||||
Some(Self::new(unix_seconds, subsec_nanos))
|
||||
@ -283,7 +303,7 @@ impl UnixTimestamp {
|
||||
/// Returns [None] if the subsecond millisecond value is invalid (larger than fraction of a
|
||||
/// second)
|
||||
pub fn new_subsec_millis_checked(unix_seconds: i64, subsec_millis: u16) -> Option<Self> {
|
||||
if subsec_millis > 999 {
|
||||
if subsec_millis >= 1000 {
|
||||
return None;
|
||||
}
|
||||
Self::new_checked(unix_seconds, subsec_millis as u32 * 1_000_000)
|
||||
@ -292,42 +312,41 @@ impl UnixTimestamp {
|
||||
/// This function will panic if the subsecond value is larger than the fraction of a second.
|
||||
/// Use [new_checked] if you want to handle this case without a panic.
|
||||
pub const fn new(unix_seconds: i64, subsecond_nanos: u32) -> Self {
|
||||
// This could actually be used to model leap seconds, but we will ignore that for now.
|
||||
if subsecond_nanos > 1_000_000_000 - 1 {
|
||||
if subsecond_nanos >= NANOS_PER_SECOND {
|
||||
panic!("invalid subsecond nanos value");
|
||||
}
|
||||
Self {
|
||||
unix_seconds,
|
||||
subsecond_nanos,
|
||||
secs: unix_seconds,
|
||||
subsec_nanos: subsecond_nanos,
|
||||
}
|
||||
}
|
||||
|
||||
/// This function will panic if the subsecond value is larger than the fraction of a second.
|
||||
/// Use [new_subsecond_millis_checked] if you want to handle this case without a panic.
|
||||
pub const fn new_subsec_millis(unix_seconds: i64, subsecond_millis: u16) -> Self {
|
||||
// This could actually be used to model leap seconds, but we will ignore that for now.
|
||||
if subsecond_millis > 999 {
|
||||
if subsecond_millis >= 1000 {
|
||||
panic!("invalid subsecond millisecond value");
|
||||
}
|
||||
Self {
|
||||
unix_seconds,
|
||||
subsecond_nanos: subsecond_millis as u32 * 1_000_000,
|
||||
secs: unix_seconds,
|
||||
subsec_nanos: subsecond_millis as u32 * 1_000_000,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_only_seconds(unix_seconds: i64) -> Self {
|
||||
pub fn new_only_secs(unix_seconds: i64) -> Self {
|
||||
Self {
|
||||
unix_seconds,
|
||||
subsecond_nanos: 0,
|
||||
secs: unix_seconds,
|
||||
subsec_nanos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subsecond_millis(&self) -> u16 {
|
||||
(self.subsecond_nanos / 1_000_000) as u16
|
||||
#[inline]
|
||||
pub fn subsec_millis(&self) -> u16 {
|
||||
(self.subsec_nanos / 1_000_000) as u16
|
||||
}
|
||||
|
||||
pub fn subsecond_nanos(&self) -> u32 {
|
||||
self.subsecond_nanos
|
||||
pub fn subsec_nanos(&self) -> u32 {
|
||||
self.subsec_nanos
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@ -339,61 +358,76 @@ impl UnixTimestamp {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn unix_seconds_f64(&self) -> f64 {
|
||||
self.unix_seconds as f64 + (self.subsecond_nanos as f64 / 1_000_000_000.0)
|
||||
pub fn unix_secs_f64(&self) -> f64 {
|
||||
self.secs as f64 + (self.subsec_nanos as f64 / 1_000_000_000.0)
|
||||
}
|
||||
|
||||
pub fn as_date_time(&self) -> LocalResult<DateTime<Utc>> {
|
||||
Utc.timestamp_opt(self.unix_seconds, self.subsecond_nanos)
|
||||
pub fn secs(&self) -> i64 {
|
||||
self.secs
|
||||
}
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "chrono")))]
|
||||
pub fn chrono_date_time(&self) -> LocalResult<DateTime<Utc>> {
|
||||
Utc.timestamp_opt(self.secs, self.subsec_nanos)
|
||||
}
|
||||
|
||||
#[cfg(feature = "timelib")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "timelib")))]
|
||||
fn timelib_date_time(&self) -> Result<time::OffsetDateTime, time::error::ComponentRange> {
|
||||
Ok(
|
||||
time::OffsetDateTime::from_unix_timestamp(self.unix_seconds())?
|
||||
+ time::Duration::nanoseconds(self.subsecond_nanos().into()),
|
||||
)
|
||||
}
|
||||
|
||||
// Calculate the difference in milliseconds between two UnixTimestamps
|
||||
pub fn difference_in_millis(&self, other: &UnixTimestamp) -> i64 {
|
||||
let seconds_difference = self.unix_seconds - other.unix_seconds;
|
||||
pub fn diff_in_millis(&self, other: &UnixTime) -> i64 {
|
||||
let seconds_difference = self.secs - other.secs;
|
||||
// Convert seconds difference to milliseconds
|
||||
let milliseconds_difference = seconds_difference * 1000;
|
||||
|
||||
// Calculate the difference in subsecond milliseconds directly
|
||||
let subsecond_difference_nanos = self.subsecond_nanos as i64 - other.subsecond_nanos as i64;
|
||||
let subsecond_difference_nanos = self.subsec_nanos as i64 - other.subsec_nanos as i64;
|
||||
|
||||
// Combine the differences
|
||||
milliseconds_difference + (subsecond_difference_nanos / 1_000_000)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DateTime<Utc>> for UnixTimestamp {
|
||||
impl From<DateTime<Utc>> for UnixTime {
|
||||
fn from(value: DateTime<Utc>) -> Self {
|
||||
Self::new(value.timestamp(), value.timestamp_subsec_nanos())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for UnixTimestamp {
|
||||
impl PartialOrd for UnixTime {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for UnixTimestamp {
|
||||
impl Ord for UnixTime {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
if self == other {
|
||||
return Ordering::Equal;
|
||||
}
|
||||
match self.unix_seconds.cmp(&other.unix_seconds) {
|
||||
match self.secs.cmp(&other.secs) {
|
||||
Ordering::Less => return Ordering::Less,
|
||||
Ordering::Greater => return Ordering::Greater,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
match self.subsecond_millis().cmp(&other.subsecond_millis()) {
|
||||
match self.subsec_millis().cmp(&other.subsec_millis()) {
|
||||
Ordering::Less => {
|
||||
return if self.unix_seconds < 0 {
|
||||
return if self.secs < 0 {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Less
|
||||
}
|
||||
}
|
||||
Ordering::Greater => {
|
||||
return if self.unix_seconds < 0 {
|
||||
return if self.secs < 0 {
|
||||
Ordering::Less
|
||||
} else {
|
||||
Ordering::Greater
|
||||
@ -413,11 +447,11 @@ pub struct StampDiff {
|
||||
pub duration_absolute: Duration,
|
||||
}
|
||||
|
||||
impl Sub for UnixTimestamp {
|
||||
impl Sub for UnixTime {
|
||||
type Output = StampDiff;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
let difference = self.difference_in_millis(&rhs);
|
||||
let difference = self.diff_in_millis(&rhs);
|
||||
if difference < 0 {
|
||||
StampDiff {
|
||||
positive_duration: false,
|
||||
@ -432,12 +466,9 @@ impl Sub for UnixTimestamp {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_new_stamp_after_addition(
|
||||
current_stamp: &UnixTimestamp,
|
||||
duration: Duration,
|
||||
) -> UnixTimestamp {
|
||||
let mut new_subsec_nanos = current_stamp.subsecond_nanos() + duration.subsec_nanos();
|
||||
let mut new_unix_seconds = current_stamp.unix_seconds;
|
||||
fn get_new_stamp_after_addition(current_stamp: &UnixTime, duration: Duration) -> UnixTime {
|
||||
let mut new_subsec_nanos = current_stamp.subsec_nanos() + duration.subsec_nanos();
|
||||
let mut new_unix_seconds = current_stamp.secs;
|
||||
let mut increment_seconds = |value: u32| {
|
||||
if new_unix_seconds < 0 {
|
||||
new_unix_seconds = new_unix_seconds
|
||||
@ -459,7 +490,7 @@ fn get_new_stamp_after_addition(
|
||||
.try_into()
|
||||
.expect("duration seconds exceeds u32::MAX"),
|
||||
);
|
||||
UnixTimestamp::new(new_unix_seconds, new_subsec_nanos)
|
||||
UnixTime::new(new_unix_seconds, new_subsec_nanos)
|
||||
}
|
||||
|
||||
/// Please note that this operation will panic on the following conditions:
|
||||
@ -467,7 +498,7 @@ fn get_new_stamp_after_addition(
|
||||
/// - Unix seconds after subtraction for stamps before the unix epoch exceeds [i64::MIN].
|
||||
/// - Unix seconds after addition exceeds [i64::MAX].
|
||||
/// - Seconds from duration to add exceeds [u32::MAX].
|
||||
impl AddAssign<Duration> for UnixTimestamp {
|
||||
impl AddAssign<Duration> for UnixTime {
|
||||
fn add_assign(&mut self, duration: Duration) {
|
||||
*self = get_new_stamp_after_addition(self, duration);
|
||||
}
|
||||
@ -478,7 +509,7 @@ impl AddAssign<Duration> for UnixTimestamp {
|
||||
/// - Unix seconds after subtraction for stamps before the unix epoch exceeds [i64::MIN].
|
||||
/// - Unix seconds after addition exceeds [i64::MAX].
|
||||
/// - Unix seconds exceeds [u32::MAX].
|
||||
impl Add<Duration> for UnixTimestamp {
|
||||
impl Add<Duration> for UnixTime {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, duration: Duration) -> Self::Output {
|
||||
@ -486,8 +517,8 @@ impl Add<Duration> for UnixTimestamp {
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Duration> for &UnixTimestamp {
|
||||
type Output = UnixTimestamp;
|
||||
impl Add<Duration> for &UnixTime {
|
||||
type Output = UnixTime;
|
||||
|
||||
fn add(self, duration: Duration) -> Self::Output {
|
||||
get_new_stamp_after_addition(self, duration)
|
||||
@ -503,9 +534,9 @@ mod tests {
|
||||
use super::{cuc::CucError, *};
|
||||
|
||||
#[allow(dead_code)]
|
||||
const UNIX_STAMP_CONST: UnixTimestamp = UnixTimestamp::new(5, 999_999_999);
|
||||
const UNIX_STAMP_CONST: UnixTime = UnixTime::new(5, 999_999_999);
|
||||
#[allow(dead_code)]
|
||||
const UNIX_STAMP_CONST_2: UnixTimestamp = UnixTimestamp::new_subsec_millis(5, 999);
|
||||
const UNIX_STAMP_CONST_2: UnixTime = UnixTime::new_subsec_millis(5, 999);
|
||||
|
||||
#[test]
|
||||
fn test_days_conversion() {
|
||||
@ -542,29 +573,29 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn basic_unix_stamp_test() {
|
||||
let stamp = UnixTimestamp::new_only_seconds(-200);
|
||||
assert_eq!(stamp.unix_seconds, -200);
|
||||
assert_eq!(stamp.subsecond_millis(), 0);
|
||||
let stamp = UnixTimestamp::new_only_seconds(250);
|
||||
assert_eq!(stamp.unix_seconds, 250);
|
||||
assert_eq!(stamp.subsecond_millis(), 0);
|
||||
let stamp = UnixTime::new_only_secs(-200);
|
||||
assert_eq!(stamp.secs, -200);
|
||||
assert_eq!(stamp.subsec_millis(), 0);
|
||||
let stamp = UnixTime::new_only_secs(250);
|
||||
assert_eq!(stamp.secs, 250);
|
||||
assert_eq!(stamp.subsec_millis(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_float_unix_stamp_test() {
|
||||
let stamp = UnixTimestamp::new_subsec_millis_checked(500, 600).unwrap();
|
||||
assert_eq!(stamp.unix_seconds, 500);
|
||||
let subsec_millis = stamp.subsecond_millis();
|
||||
let stamp = UnixTime::new_subsec_millis_checked(500, 600).unwrap();
|
||||
assert_eq!(stamp.secs, 500);
|
||||
let subsec_millis = stamp.subsec_millis();
|
||||
assert_eq!(subsec_millis, 600);
|
||||
println!("{:?}", (500.6 - stamp.unix_seconds_f64()).to_string());
|
||||
assert!((500.6 - stamp.unix_seconds_f64()).abs() < 0.0001);
|
||||
println!("{:?}", (500.6 - stamp.unix_secs_f64()).to_string());
|
||||
assert!((500.6 - stamp.unix_secs_f64()).abs() < 0.0001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ord_larger() {
|
||||
let stamp0 = UnixTimestamp::new_only_seconds(5);
|
||||
let stamp1 = UnixTimestamp::new_subsec_millis_checked(5, 500).unwrap();
|
||||
let stamp2 = UnixTimestamp::new_only_seconds(6);
|
||||
let stamp0 = UnixTime::new_only_secs(5);
|
||||
let stamp1 = UnixTime::new_subsec_millis_checked(5, 500).unwrap();
|
||||
let stamp2 = UnixTime::new_only_secs(6);
|
||||
assert!(stamp1 > stamp0);
|
||||
assert!(stamp2 > stamp0);
|
||||
assert!(stamp2 > stamp1);
|
||||
@ -572,9 +603,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_ord_smaller() {
|
||||
let stamp0 = UnixTimestamp::new_only_seconds(5);
|
||||
let stamp1 = UnixTimestamp::new_subsec_millis_checked(5, 500).unwrap();
|
||||
let stamp2 = UnixTimestamp::new_only_seconds(6);
|
||||
let stamp0 = UnixTime::new_only_secs(5);
|
||||
let stamp1 = UnixTime::new_subsec_millis_checked(5, 500).unwrap();
|
||||
let stamp2 = UnixTime::new_only_secs(6);
|
||||
assert!(stamp0 < stamp1);
|
||||
assert!(stamp0 < stamp2);
|
||||
assert!(stamp1 < stamp2);
|
||||
@ -582,9 +613,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_ord_larger_neg_numbers() {
|
||||
let stamp0 = UnixTimestamp::new_only_seconds(-5);
|
||||
let stamp1 = UnixTimestamp::new_subsec_millis_checked(-5, 500).unwrap();
|
||||
let stamp2 = UnixTimestamp::new_only_seconds(-6);
|
||||
let stamp0 = UnixTime::new_only_secs(-5);
|
||||
let stamp1 = UnixTime::new_subsec_millis_checked(-5, 500).unwrap();
|
||||
let stamp2 = UnixTime::new_only_secs(-6);
|
||||
assert!(stamp0 > stamp1);
|
||||
assert!(stamp0 > stamp2);
|
||||
assert!(stamp1 > stamp2);
|
||||
@ -594,9 +625,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_ord_smaller_neg_numbers() {
|
||||
let stamp0 = UnixTimestamp::new_only_seconds(-5);
|
||||
let stamp1 = UnixTimestamp::new_subsec_millis_checked(-5, 500).unwrap();
|
||||
let stamp2 = UnixTimestamp::new_only_seconds(-6);
|
||||
let stamp0 = UnixTime::new_only_secs(-5);
|
||||
let stamp1 = UnixTime::new_subsec_millis_checked(-5, 500).unwrap();
|
||||
let stamp2 = UnixTime::new_only_secs(-6);
|
||||
assert!(stamp2 < stamp1);
|
||||
assert!(stamp2 < stamp0);
|
||||
assert!(stamp1 < stamp0);
|
||||
@ -607,8 +638,8 @@ mod tests {
|
||||
#[allow(clippy::nonminimal_bool)]
|
||||
#[test]
|
||||
fn test_eq() {
|
||||
let stamp0 = UnixTimestamp::new(5, 0);
|
||||
let stamp1 = UnixTimestamp::new_only_seconds(5);
|
||||
let stamp0 = UnixTime::new(5, 0);
|
||||
let stamp1 = UnixTime::new_only_secs(5);
|
||||
assert_eq!(stamp0, stamp1);
|
||||
assert!(stamp0 <= stamp1);
|
||||
assert!(stamp0 >= stamp1);
|
||||
@ -618,27 +649,27 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_addition() {
|
||||
let mut stamp0 = UnixTimestamp::new_only_seconds(1);
|
||||
let mut stamp0 = UnixTime::new_only_secs(1);
|
||||
stamp0 += Duration::from_secs(5);
|
||||
assert_eq!(stamp0.unix_seconds, 6);
|
||||
assert_eq!(stamp0.subsecond_millis(), 0);
|
||||
assert_eq!(stamp0.secs, 6);
|
||||
assert_eq!(stamp0.subsec_millis(), 0);
|
||||
let stamp1 = stamp0 + Duration::from_millis(500);
|
||||
assert_eq!(stamp1.unix_seconds, 6);
|
||||
assert_eq!(stamp1.subsecond_millis(), 500);
|
||||
assert_eq!(stamp1.secs, 6);
|
||||
assert_eq!(stamp1.subsec_millis(), 500);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_addition_on_ref() {
|
||||
let stamp0 = &UnixTimestamp::new_subsec_millis_checked(20, 500).unwrap();
|
||||
let stamp0 = &UnixTime::new_subsec_millis_checked(20, 500).unwrap();
|
||||
let stamp1 = stamp0 + Duration::from_millis(2500);
|
||||
assert_eq!(stamp1.unix_seconds, 23);
|
||||
assert_eq!(stamp1.subsecond_millis(), 0);
|
||||
assert_eq!(stamp1.secs, 23);
|
||||
assert_eq!(stamp1.subsec_millis(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_as_dt() {
|
||||
let stamp = UnixTimestamp::new_only_seconds(0);
|
||||
let dt = stamp.as_date_time().unwrap();
|
||||
let stamp = UnixTime::new_only_secs(0);
|
||||
let dt = stamp.chrono_date_time().unwrap();
|
||||
assert_eq!(dt.year(), 1970);
|
||||
assert_eq!(dt.month(), 1);
|
||||
assert_eq!(dt.day(), 1);
|
||||
@ -649,26 +680,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_from_now() {
|
||||
let stamp_now = UnixTimestamp::from_now().unwrap();
|
||||
let dt_now = stamp_now.as_date_time().unwrap();
|
||||
let stamp_now = UnixTime::from_now().unwrap();
|
||||
let dt_now = stamp_now.chrono_date_time().unwrap();
|
||||
assert!(dt_now.year() >= 2020);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stamp_diff_positive_0() {
|
||||
let stamp_later = UnixTimestamp::new(2, 0);
|
||||
let stamp_later = UnixTime::new(2, 0);
|
||||
let StampDiff {
|
||||
positive_duration,
|
||||
duration_absolute,
|
||||
} = stamp_later - UnixTimestamp::new(1, 0);
|
||||
} = stamp_later - UnixTime::new(1, 0);
|
||||
assert!(positive_duration);
|
||||
assert_eq!(duration_absolute, Duration::from_secs(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stamp_diff_positive_1() {
|
||||
let stamp_later = UnixTimestamp::new(3, 800 * 1_000_000);
|
||||
let stamp_earlier = UnixTimestamp::new_subsec_millis_checked(1, 900).unwrap();
|
||||
let stamp_later = UnixTime::new(3, 800 * 1_000_000);
|
||||
let stamp_earlier = UnixTime::new_subsec_millis_checked(1, 900).unwrap();
|
||||
let StampDiff {
|
||||
positive_duration,
|
||||
duration_absolute,
|
||||
@ -679,8 +710,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_stamp_diff_negative() {
|
||||
let stamp_later = UnixTimestamp::new_subsec_millis_checked(3, 800).unwrap();
|
||||
let stamp_earlier = UnixTimestamp::new_subsec_millis_checked(1, 900).unwrap();
|
||||
let stamp_later = UnixTime::new_subsec_millis_checked(3, 800).unwrap();
|
||||
let stamp_earlier = UnixTime::new_subsec_millis_checked(1, 900).unwrap();
|
||||
let StampDiff {
|
||||
positive_duration,
|
||||
duration_absolute,
|
||||
@ -691,13 +722,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_addition_spillover() {
|
||||
let mut stamp0 = UnixTimestamp::new_subsec_millis_checked(1, 900).unwrap();
|
||||
let mut stamp0 = UnixTime::new_subsec_millis_checked(1, 900).unwrap();
|
||||
stamp0 += Duration::from_millis(100);
|
||||
assert_eq!(stamp0.unix_seconds, 2);
|
||||
assert_eq!(stamp0.subsecond_millis(), 0);
|
||||
assert_eq!(stamp0.secs, 2);
|
||||
assert_eq!(stamp0.subsec_millis(), 0);
|
||||
stamp0 += Duration::from_millis(1100);
|
||||
assert_eq!(stamp0.unix_seconds, 3);
|
||||
assert_eq!(stamp0.subsecond_millis(), 100);
|
||||
assert_eq!(stamp0.secs, 3);
|
||||
assert_eq!(stamp0.subsec_millis(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user