1use crate::{FormatFloatValue, FormatIntegerValue, Unit};
2
3const EPSILON: f64 = 1e-10;
5
6#[derive(Debug, Default, PartialEq)]
10pub struct Time {
11 pub days: u64,
12 pub hours: u8,
13 pub minutes: u8,
14 pub seconds: f64,
15}
16
17impl Time {
18 pub fn format_time(&self) -> String {
29 let mut parts = Vec::new();
30
31 if self.days > 0 {
33 parts.push(self.days.format_unit(Unit::Day));
34 }
35
36 if self.hours > 0 || !parts.is_empty() {
38 parts.push(self.hours.format_unit(Unit::Hour));
39 }
40
41 if self.minutes > 0 || !parts.is_empty() {
43 parts.push(self.minutes.format_unit(Unit::Minute));
44 }
45
46 let decimal: usize = self.calculate_decimal();
48
49 parts.push(self.seconds.format_float_unit(decimal, Unit::Second));
51
52 parts.join(", ")
53 }
54
55 fn calculate_decimal(&self) -> usize {
61 let sec = self.seconds;
62
63 if sec < EPSILON {
64 1
66 } else if sec >= 1.0 {
67 3
69 } else if sec >= 0.001 {
70 6
72 } else {
73 9
75 }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use crate::duration_extension::DurationExtension;
83 use std::time::Duration;
84
85 #[test]
86 fn times_new() {
87 let duration = Duration::from_secs(86400 + 3600 + 60 + 1); let time = duration.get_time();
89 assert_eq!(time.days, 1);
90 assert_eq!(time.hours, 1);
91 assert_eq!(time.minutes, 1);
92 assert_eq!(time.seconds, 1.0);
93
94 let duration = Duration::from_secs_f64(3661.5); let time = duration.get_time();
96 assert_eq!(time.days, 0);
97 assert_eq!(time.hours, 1);
98 assert_eq!(time.minutes, 1);
99 assert_eq!(time.seconds, 1.5);
100
101 let duration = Duration::from_secs(0);
102 let time = duration.get_time();
103 assert_eq!(time.days, 0);
104 assert_eq!(time.hours, 0);
105 assert_eq!(time.minutes, 0);
106 assert_eq!(time.seconds, 0.0);
107
108 let duration = Duration::from_secs_f64(2.5 * 86400.0);
109 let time = duration.get_time();
110 assert_eq!(time.days, 2);
111 assert_eq!(time.hours, 12);
112 assert_eq!(time.minutes, 0);
113 assert_eq!(time.seconds, 0.0);
114 }
115
116 #[test]
117 fn times_format() {
118 let time = Time {
119 days: 1,
120 hours: 2,
121 minutes: 3,
122 seconds: 4.567002,
123 };
124 assert_eq!(
125 time.format_time(),
126 "1 day, 2 hours, 3 minutes, 4.567 seconds"
127 );
128
129 let time = Time {
130 days: 0,
131 hours: 2,
132 minutes: 3,
133 seconds: 4.567,
134 };
135 assert_eq!(time.format_time(), "2 hours, 3 minutes, 4.567 seconds");
136
137 let time = Time {
138 days: 0,
139 hours: 0,
140 minutes: 3,
141 seconds: 4.567111,
142 };
143 assert_eq!(time.format_time(), "3 minutes, 4.567 seconds");
144
145 let time = Time {
146 days: 0,
147 hours: 0,
148 minutes: 0,
149 seconds: 4.567000444,
150 };
151 assert_eq!(time.format_time(), "4.567 seconds");
152
153 let time = Time {
154 days: 1,
155 hours: 0,
156 minutes: 0,
157 seconds: 0.0,
158 };
159
160 assert_eq!(time.format_time(), "1 day, 0 hour, 0 minute, 0.0 second");
161
162 let time = Time {
163 days: 1,
164 hours: 2,
165 minutes: 0,
166 seconds: 0.0,
167 };
168 assert_eq!(time.format_time(), "1 day, 2 hours, 0 minute, 0.0 second");
169 }
170
171 #[test]
172 fn times_default() {
173 let time = Time {
174 days: 0,
175 hours: 0,
176 minutes: 0,
177 seconds: 0.0,
178 };
179 let time_default = Time::default();
180
181 assert_eq!(time, time_default);
182 assert_eq!(time.format_time(), "0.0 second");
183 }
184}