autd3_core/ethercat/
dc_sys_time.rs1#[cfg(feature = "time")]
2#[derive(Debug, PartialEq, Clone)]
3pub struct InvalidDateTime;
4
5#[cfg(feature = "time")]
6impl core::fmt::Display for InvalidDateTime {
7 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8 write!(f, "Invalid date time")
9 }
10}
11
12#[cfg(feature = "time")]
13impl std::error::Error for InvalidDateTime {}
14
15#[cfg(feature = "time")]
16use super::ECAT_DC_SYS_TIME_BASE;
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[repr(C)]
25pub struct DcSysTime {
26 dc_sys_time: u64,
27}
28
29impl DcSysTime {
30 pub const ZERO: Self = Self { dc_sys_time: 0 };
32
33 pub const fn new(dc_sys_time: u64) -> Self {
35 Self { dc_sys_time }
36 }
37
38 #[must_use]
40 pub const fn sys_time(&self) -> u64 {
41 self.dc_sys_time
42 }
43
44 #[must_use]
46 #[cfg(feature = "time")]
47 pub fn to_utc(&self) -> time::OffsetDateTime {
48 ECAT_DC_SYS_TIME_BASE + core::time::Duration::from_nanos(self.dc_sys_time)
49 }
50
51 #[cfg(feature = "time")]
53 pub fn from_utc(utc: time::OffsetDateTime) -> Result<Self, InvalidDateTime> {
54 Ok(Self {
55 dc_sys_time: u64::try_from((utc - ECAT_DC_SYS_TIME_BASE).whole_nanoseconds())
56 .map_err(|_| InvalidDateTime)?,
57 })
58 }
59
60 #[must_use]
62 #[cfg(feature = "time")]
63 pub fn now() -> Self {
64 Self::from_utc(time::OffsetDateTime::now_utc()).expect("system time is invalid")
65 }
66}
67
68impl core::ops::Add<core::time::Duration> for DcSysTime {
69 type Output = Self;
70
71 fn add(self, rhs: core::time::Duration) -> Self::Output {
72 Self {
73 dc_sys_time: self.dc_sys_time + rhs.as_nanos() as u64,
74 }
75 }
76}
77
78impl core::ops::AddAssign<core::time::Duration> for DcSysTime {
79 fn add_assign(&mut self, rhs: core::time::Duration) {
80 self.dc_sys_time += rhs.as_nanos() as u64;
81 }
82}
83
84impl core::ops::Sub<core::time::Duration> for DcSysTime {
85 type Output = Self;
86
87 fn sub(self, rhs: core::time::Duration) -> Self::Output {
88 Self {
89 dc_sys_time: self.dc_sys_time - rhs.as_nanos() as u64,
90 }
91 }
92}
93
94impl core::ops::SubAssign<core::time::Duration> for DcSysTime {
95 fn sub_assign(&mut self, rhs: core::time::Duration) {
96 self.dc_sys_time -= rhs.as_nanos() as u64;
97 }
98}
99
100impl core::ops::Sub for DcSysTime {
101 type Output = core::time::Duration;
102
103 fn sub(self, rhs: Self) -> Self::Output {
104 core::time::Duration::from_nanos(self.dc_sys_time - rhs.dc_sys_time)
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn new() {
114 let t = DcSysTime::new(123456789);
115 assert_eq!(123456789, t.sys_time());
116 }
117
118 #[cfg(feature = "time")]
119 #[test]
120 fn err_display() {
121 let err = InvalidDateTime;
122 assert_eq!("Invalid date time", format!("{}", err));
123 }
124
125 #[cfg(feature = "time")]
126 #[test]
127 fn now_dc_sys_time() {
128 let t = DcSysTime::now();
129 assert!(t.sys_time() > 0);
130 }
131
132 #[cfg(feature = "time")]
133 #[rstest::rstest]
134 #[case(Ok(DcSysTime { dc_sys_time: 0 }), time::macros::datetime!(2000-01-01 0:0:0 UTC))]
135 #[case(Ok(DcSysTime { dc_sys_time: 1000000000 }), time::macros::datetime!(2000-01-01 0:0:1 UTC))]
136 #[case(Ok(DcSysTime { dc_sys_time: 31622400000000000 }), time::macros::datetime!(2001-01-01 0:0:0 UTC))]
137 #[case(Err(InvalidDateTime), time::macros::datetime!(1999-01-01 0:0:1 UTC))]
138 #[case(Err(InvalidDateTime), time::macros::datetime!(9999-01-01 0:0:1 UTC))]
139 fn from_utc(
140 #[case] expect: Result<DcSysTime, InvalidDateTime>,
141 #[case] utc: time::OffsetDateTime,
142 ) {
143 assert_eq!(expect, DcSysTime::from_utc(utc));
144 }
145
146 #[cfg(feature = "time")]
147 #[rstest::rstest]
148 #[case(time::macros::datetime!(2000-01-01 0:0:1 UTC))]
149 #[case(time::macros::datetime!(2001-01-01 0:0:0 UTC))]
150 fn to_utc(#[case] utc: time::OffsetDateTime) {
151 assert_eq!(utc, DcSysTime::from_utc(utc).unwrap().to_utc());
152 }
153
154 #[cfg(feature = "time")]
155 #[test]
156 fn add_sub() {
157 let t = DcSysTime::ZERO;
158
159 let mut t = t + core::time::Duration::from_secs(1);
160 assert_eq!(1000000000, t.sys_time());
161 t += core::time::Duration::from_secs(2);
162 assert_eq!(3000000000, t.sys_time());
163
164 let mut t = t - core::time::Duration::from_secs(1);
165 assert_eq!(2000000000, t.sys_time());
166 t -= core::time::Duration::from_secs(2);
167 assert_eq!(0, t.sys_time());
168
169 assert_eq!(
170 core::time::Duration::from_secs(2),
171 (DcSysTime::ZERO + core::time::Duration::from_secs(3))
172 - (DcSysTime::ZERO + core::time::Duration::from_secs(1))
173 );
174 }
175}