1use cxx::{type_id, ExternType};
7use std::fmt;
8
9#[cxx::bridge]
10mod ffi {
11 #[namespace = "Qt"]
12 unsafe extern "C++" {
13 include!("cxx-qt-lib/qt.h");
14 type DateFormat = crate::DateFormat;
15 }
16
17 unsafe extern "C++" {
18 include!("cxx-qt-lib/qtime.h");
19 include!("cxx-qt-lib/qstring.h");
20
21 type QTime = super::QTime;
22 type QString = crate::QString;
23
24 #[rust_name = "add_msecs"]
27 fn addMSecs(self: &QTime, ms: i32) -> QTime;
28
29 #[rust_name = "add_secs"]
32 fn addSecs(self: &QTime, s: i32) -> QTime;
33
34 fn hour(self: &QTime) -> i32;
36
37 #[rust_name = "is_null"]
41 fn isNull(self: &QTime) -> bool;
42
43 #[rust_name = "is_valid"]
45 fn isValid(self: &QTime) -> bool;
46
47 fn minute(self: &QTime) -> i32;
49
50 fn msec(self: &QTime) -> i32;
52
53 #[rust_name = "msecs_since_start_of_day"]
55 fn msecsSinceStartOfDay(self: &QTime) -> i32;
56
57 fn second(self: &QTime) -> i32;
59
60 #[rust_name = "set_hms"]
62 fn setHMS(self: &mut QTime, h: i32, m: i32, s: i32, ms: i32) -> bool;
63
64 #[rust_name = "format"]
66 fn toString(self: &QTime, format: &QString) -> QString;
67
68 #[rust_name = "format_enum"]
70 fn toString(self: &QTime, format: DateFormat) -> QString;
71 }
72
73 #[namespace = "rust::cxxqtlib1"]
74 unsafe extern "C++" {
75 #[doc(hidden)]
76 #[rust_name = "qtime_current_time"]
77 fn qtimeCurrentTime() -> QTime;
78
79 #[doc(hidden)]
80 #[rust_name = "qtime_from_msecs_since_start_of_day"]
81 fn qtimeFromMSecsSinceStartOfDay(msecs: i32) -> QTime;
82
83 #[doc(hidden)]
84 #[rust_name = "qtime_from_string"]
85 fn qtimeFromString(string: &QString, format: &QString) -> QTime;
86 #[doc(hidden)]
87 #[rust_name = "qtime_from_string_enum"]
88 fn qtimeFromString(string: &QString, format: DateFormat) -> QTime;
89
90 #[doc(hidden)]
91 #[rust_name = "qtime_msecs_to"]
92 fn qtimeMSecsTo(time: &QTime, t: QTime) -> i32;
93
94 #[doc(hidden)]
95 #[rust_name = "qtime_secs_to"]
96 fn qtimeSecsTo(time: &QTime, t: QTime) -> i32;
97
98 #[doc(hidden)]
99 #[rust_name = "qtime_is_valid"]
100 fn qtimeIsValid(h: i32, m: i32, s: i32, ms: i32) -> bool;
101 }
102
103 #[namespace = "rust::cxxqtlib1"]
104 unsafe extern "C++" {
105 include!("cxx-qt-lib/common.h");
106
107 #[doc(hidden)]
108 #[rust_name = "qtime_init_default"]
109 fn construct() -> QTime;
110 #[doc(hidden)]
111 #[rust_name = "qtime_init"]
112 fn construct(h: i32, m: i32, s: i32, ms: i32) -> QTime;
113 #[doc(hidden)]
114 #[rust_name = "qtime_to_qstring"]
115 fn toQString(value: &QTime) -> QString;
116 }
117}
118
119#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
121#[repr(C)]
122pub struct QTime {
123 mds: i32,
124}
125
126impl QTime {
127 pub fn current_time() -> Self {
129 ffi::qtime_current_time()
130 }
131
132 pub fn from_msecs_since_start_of_day(msecs: i32) -> Self {
135 ffi::qtime_from_msecs_since_start_of_day(msecs)
136 }
137
138 pub fn from_string(string: &ffi::QString, format: &ffi::QString) -> Self {
140 ffi::qtime_from_string(string, format)
141 }
142
143 pub fn from_string_enum(string: &ffi::QString, format: ffi::DateFormat) -> Self {
145 ffi::qtime_from_string_enum(string, format)
146 }
147
148 pub fn msecs_to(&self, t: Self) -> i32 {
151 ffi::qtime_msecs_to(self, t)
152 }
153
154 pub fn new(h: i32, m: i32, s: i32, ms: i32) -> Self {
156 ffi::qtime_init(h, m, s, ms)
157 }
158
159 pub fn secs_to(&self, t: Self) -> i32 {
162 ffi::qtime_secs_to(self, t)
163 }
164
165 pub fn is_valid_time(h: i32, m: i32, s: i32, ms: i32) -> bool {
168 ffi::qtime_is_valid(h, m, s, ms)
169 }
170}
171
172impl Default for QTime {
173 fn default() -> Self {
175 ffi::qtime_init_default()
176 }
177}
178
179impl fmt::Display for QTime {
180 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181 write!(f, "{}", ffi::qtime_to_qstring(self))
182 }
183}
184
185impl fmt::Debug for QTime {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 write!(f, "{self}")
188 }
189}
190
191#[cfg(feature = "chrono")]
192use chrono::Timelike;
193
194#[cfg(feature = "chrono")]
195impl TryFrom<chrono::NaiveTime> for QTime {
196 type Error = &'static str;
197
198 fn try_from(value: chrono::NaiveTime) -> Result<Self, Self::Error> {
201 let ms = (value.nanosecond() / 1_000_000) as i32;
202 if ms > 999 {
208 return Err("leap second is not supported in Qt");
209 }
210
211 Ok(QTime::new(
212 value.hour() as i32,
213 value.minute() as i32,
214 value.second() as i32,
215 ms,
216 ))
217 }
218}
219
220#[cfg(feature = "chrono")]
221impl TryFrom<QTime> for chrono::NaiveTime {
222 type Error = &'static str;
223
224 fn try_from(value: QTime) -> Result<Self, Self::Error> {
225 chrono::NaiveTime::from_hms_milli_opt(
226 value.hour() as u32,
227 value.minute() as u32,
228 value.second() as u32,
229 value.msec() as u32,
230 )
231 .ok_or("invalid hour, minute, second and/or millisecond")
232 }
233}
234
235#[cfg(feature = "time")]
236impl From<time::Time> for QTime {
237 fn from(value: time::Time) -> Self {
238 QTime::new(
239 value.hour() as i32,
240 value.minute() as i32,
241 value.second() as i32,
242 value.millisecond() as i32,
243 )
244 }
245}
246
247#[cfg(feature = "time")]
248impl TryFrom<QTime> for time::Time {
249 type Error = time::error::ComponentRange;
250
251 fn try_from(value: QTime) -> Result<Self, Self::Error> {
252 time::Time::from_hms_milli(
253 value.hour() as u8,
254 value.minute() as u8,
255 value.second() as u8,
256 value.msec() as u16,
257 )
258 }
259}
260
261unsafe impl ExternType for QTime {
265 type Id = type_id!("QTime");
266 type Kind = cxx::kind::Trivial;
267}
268
269#[cfg(test)]
270#[cfg(feature = "chrono")]
271mod test_chrono {
272 use super::*;
273
274 #[test]
275 fn qtime_from_chrono_naive() {
276 let naive = chrono::NaiveTime::from_hms_milli_opt(1, 2, 3, 4).unwrap();
277 let qtime = QTime::new(1, 2, 3, 4);
278 assert_eq!(QTime::try_from(naive).unwrap(), qtime);
279 }
280
281 #[test]
282 fn qtime_from_chrono_naive_leap_second() {
283 let naive = chrono::NaiveTime::from_hms_milli_opt(1, 2, 59, 1_999).unwrap();
284 assert!(QTime::try_from(naive).is_err());
285 }
286
287 #[test]
288 fn qtime_to_chrono_naive() {
289 let naive = chrono::NaiveTime::from_hms_milli_opt(1, 2, 3, 4).unwrap();
290 let qtime = QTime::new(1, 2, 3, 4);
291 assert_eq!(chrono::NaiveTime::try_from(qtime).unwrap(), naive);
292 }
293}
294
295#[cfg(test)]
296#[cfg(feature = "time")]
297mod test_time {
298 use super::*;
299
300 #[test]
301 fn qtime_from_time_time() {
302 let time_time = time::Time::from_hms_milli(1, 2, 3, 4).unwrap();
303 let qtime = QTime::new(1, 2, 3, 4);
304 assert_eq!(QTime::from(time_time), qtime);
305 }
306
307 #[test]
308 fn qtime_to_time_time() {
309 let time_time = time::Time::from_hms_milli(1, 2, 3, 4).unwrap();
310 let qtime = QTime::new(1, 2, 3, 4);
311 assert_eq!(time::Time::try_from(qtime).unwrap(), time_time);
312 }
313}