collectd_plugin/api/
cdtime.rs1use crate::bindings::cdtime_t;
13use chrono::prelude::*;
14use chrono::Duration;
15
16#[derive(Debug, PartialEq, Eq, Clone, Copy)]
19pub struct CdTime(pub u64);
20
21impl<Tz: TimeZone> From<DateTime<Tz>> for CdTime {
22 fn from(dt: DateTime<Tz>) -> Self {
23 let sec_nanos = (dt.timestamp() as u64) * 1_000_000_000;
24 let nanos = u64::from(dt.timestamp_subsec_nanos());
25 CdTime(sec_nanos + nanos)
26 }
27}
28
29impl From<CdTime> for DateTime<Utc> {
30 fn from(v: CdTime) -> DateTime<Utc> {
31 let CdTime(ns) = v;
32 let secs = ns / 1_000_000_000;
33 let left = ns % 1_000_000_000;
34 Utc.timestamp_opt(secs as i64, left as u32)
35 .latest()
36 .unwrap_or_default()
37 }
38}
39
40impl From<Duration> for CdTime {
41 fn from(d: Duration) -> Self {
42 CdTime(d.num_nanoseconds().unwrap() as u64)
43 }
44}
45
46impl From<CdTime> for Duration {
47 fn from(v: CdTime) -> Self {
48 let CdTime(ns) = v;
49 Duration::nanoseconds(ns as i64)
50 }
51}
52
53impl From<cdtime_t> for CdTime {
54 fn from(d: cdtime_t) -> Self {
55 CdTime(collectd_to_nanos(d))
56 }
57}
58
59impl From<CdTime> for cdtime_t {
60 fn from(d: CdTime) -> Self {
61 let CdTime(x) = d;
62 nanos_to_collectd(x)
63 }
64}
65
66pub fn nanos_to_collectd(nanos: u64) -> cdtime_t {
68 ((nanos / 1_000_000_000) << 30)
69 | ((((nanos % 1_000_000_000) << 30) + 500_000_000) / 1_000_000_000)
70}
71
72fn collectd_to_nanos(cd: cdtime_t) -> u64 {
74 ((cd >> 30) * 1_000_000_000) + (((cd & 0x3fff_ffff) * 1_000_000_000 + (1 << 29)) >> 30)
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_nanos_to_collectd() {
83 assert_eq!(nanos_to_collectd(1439981652801860766), 1546168526406004689);
86 assert_eq!(nanos_to_collectd(1439981836985281914), 1546168724171447263);
87 assert_eq!(nanos_to_collectd(1439981880053705608), 1546168770415815077);
88 }
89
90 #[test]
91 fn test_collectd_to_nanos() {
92 assert_eq!(collectd_to_nanos(1546168526406004689), 1439981652801860766);
93 assert_eq!(collectd_to_nanos(1546168724171447263), 1439981836985281914);
94 assert_eq!(collectd_to_nanos(1546168770415815077), 1439981880053705608);
95 }
96
97 #[test]
98 fn test_collectd_to_duration() {
99 let v: cdtime_t = nanos_to_collectd(1_000_000_000);
100 let dur = Duration::from(CdTime::from(v));
101 assert_eq!(dur.num_seconds(), 1);
102 }
103
104 #[test]
105 fn test_collectd_to_datetime() {
106 let v: cdtime_t = nanos_to_collectd(1_000_000_000);
107 let dt: DateTime<Utc> = CdTime::from(v).into();
108 let res = Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 1);
109 assert_eq!(res.unwrap(), dt);
110 }
111
112 #[test]
113 fn test_datetime_to_collectd() {
114 let res = Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 1);
115 let cd = CdTime::from(res.unwrap());
116 assert_eq!(cd.0, 1_000_000_000);
117 }
118}