1use cxx::{type_id, ExternType};
6use std::mem::MaybeUninit;
7use std::{cmp::Ordering, fmt};
8
9use crate::{QDate, QTime};
10
11#[cxx::bridge]
12mod ffi {
13 #[namespace = "Qt"]
14 unsafe extern "C++" {
15 include!("cxx-qt-lib/qt.h");
16 type TimeSpec = crate::TimeSpec;
17 }
18
19 unsafe extern "C++" {
20 include!("cxx-qt-lib/qdate.h");
21 type QDate = crate::QDate;
22 include!("cxx-qt-lib/qdatetime.h");
23 type QDateTime = super::QDateTime;
24 include!("cxx-qt-lib/qtime.h");
25 type QTime = crate::QTime;
26 include!("cxx-qt-lib/qstring.h");
27 type QString = crate::QString;
28 include!("cxx-qt-lib/qtimezone.h");
29 type QTimeZone = crate::QTimeZone;
30
31 #[rust_name = "add_months"]
33 fn addMonths(self: &QDateTime, nmonths: i32) -> QDateTime;
34
35 #[rust_name = "add_years"]
37 fn addYears(self: &QDateTime, nyears: i32) -> QDateTime;
38
39 fn date(self: &QDateTime) -> QDate;
41
42 #[rust_name = "is_daylight_time"]
44 fn isDaylightTime(self: &QDateTime) -> bool;
45
46 #[rust_name = "is_null"]
48 fn isNull(self: &QDateTime) -> bool;
49
50 #[rust_name = "is_valid"]
52 fn isValid(self: &QDateTime) -> bool;
53
54 #[rust_name = "offset_from_utc"]
56 fn offsetFromUtc(self: &QDateTime) -> i32;
57
58 #[cfg(not(cxxqt_qt_version_at_least_6_8))]
62 #[rust_name = "set_offset_from_utc"]
63 fn setOffsetFromUtc(self: &mut QDateTime, offset_seconds: i32);
64
65 #[cfg(not(cxxqt_qt_version_at_least_6_8))]
69 #[rust_name = "set_time_spec"]
70 fn setTimeSpec(self: &mut QDateTime, spec: TimeSpec);
71
72 fn time(self: &QDateTime) -> QTime;
74
75 #[rust_name = "time_spec"]
77 fn timeSpec(self: &QDateTime) -> TimeSpec;
78
79 #[rust_name = "time_zone_abbreviation"]
81 fn timeZoneAbbreviation(self: &QDateTime) -> QString;
82
83 #[rust_name = "to_local_time"]
85 fn toLocalTime(self: &QDateTime) -> QDateTime;
86
87 #[rust_name = "to_offset_from_utc"]
89 fn toOffsetFromUtc(self: &QDateTime, offset_seconds: i32) -> QDateTime;
90
91 #[cfg(not(cxxqt_qt_version_at_least_6_8))]
95 #[rust_name = "to_time_spec"]
96 fn toTimeSpec(self: &QDateTime, spec: TimeSpec) -> QDateTime;
97
98 #[rust_name = "to_time_zone"]
100 fn toTimeZone(self: &QDateTime, timeZone: &QTimeZone) -> QDateTime;
101
102 #[rust_name = "to_utc"]
104 fn toUTC(self: &QDateTime) -> QDateTime;
105 }
106
107 #[namespace = "rust::cxxqtlib1"]
108 unsafe extern "C++" {
109 #[doc(hidden)]
110 #[rust_name = "qdatetime_add_days"]
111 fn qdatetimeAddDays(datetime: &QDateTime, ndays: i64) -> QDateTime;
112 #[doc(hidden)]
113 #[rust_name = "qdatetime_add_msecs"]
114 fn qdatetimeAddMSecs(datetime: &QDateTime, msecs: i64) -> QDateTime;
115 #[doc(hidden)]
116 #[rust_name = "qdatetime_add_secs"]
117 fn qdatetimeAddSecs(datetime: &QDateTime, secs: i64) -> QDateTime;
118 #[doc(hidden)]
119 #[rust_name = "qdatetime_current_date_time"]
120 fn qdatetimeCurrentDateTime() -> QDateTime;
121 #[doc(hidden)]
122 #[rust_name = "qdatetime_current_date_time_utc"]
123 fn qdatetimeCurrentDateTimeUtc() -> QDateTime;
124 #[doc(hidden)]
125 #[rust_name = "qdatetime_current_msecs_since_epoch"]
126 fn qdatetimeCurrentMSecsSinceEpoch() -> i64;
127 #[doc(hidden)]
128 #[rust_name = "qdatetime_current_secs_since_epoch"]
129 fn qdatetimeCurrentSecsSinceEpoch() -> i64;
130 #[doc(hidden)]
131 #[rust_name = "qdatetime_days_to"]
132 fn qdatetimeDaysTo(datetime: &QDateTime, other: &QDateTime) -> i64;
133 #[doc(hidden)]
134 #[rust_name = "qdatetime_from_msecs_since_epoch"]
135 fn qdatetimeFromMSecsSinceEpoch(msecs: i64, time_zone: &QTimeZone) -> QDateTime;
136 #[doc(hidden)]
137 #[rust_name = "qdatetime_from_secs_since_epoch"]
138 fn qdatetimeFromSecsSinceEpoch(secs: i64, time_zone: &QTimeZone) -> QDateTime;
139 #[doc(hidden)]
140 #[rust_name = "qdatetime_msecs_to"]
141 fn qdatetimeMSecsTo(datetime: &QDateTime, other: &QDateTime) -> i64;
142 #[doc(hidden)]
143 #[rust_name = "qdatetime_secs_to"]
144 fn qdatetimeSecsTo(datetime: &QDateTime, other: &QDateTime) -> i64;
145 #[doc(hidden)]
150 #[rust_name = "qdatetime_set_date"]
151 fn qdatetimeSetDate(datetime: &mut QDateTime, date: QDate);
152 #[doc(hidden)]
153 #[rust_name = "qdatetime_set_msecs_since_epoch"]
154 fn qdatetimeSetMSecsSinceEpoch(datetime: &mut QDateTime, msecs: i64);
155 #[doc(hidden)]
156 #[rust_name = "qdatetime_set_secs_since_epoch"]
157 fn qdatetimeSetSecsSinceEpoch(datetime: &mut QDateTime, secs: i64);
158 #[doc(hidden)]
159 #[rust_name = "qdatetime_set_time"]
160 fn qdatetimeSetTime(datetime: &mut QDateTime, time: QTime);
161 #[doc(hidden)]
162 #[rust_name = "qdatetime_time_zone"]
163 fn qdatetimeTimeZone(datetime: &QDateTime) -> UniquePtr<QTimeZone>;
164 #[doc(hidden)]
165 #[rust_name = "qdatetime_to_msecs_since_epoch"]
166 fn qdatetimeToMSecsSinceEpoch(datetime: &QDateTime) -> i64;
167 #[doc(hidden)]
168 #[rust_name = "qdatetime_to_secs_since_epoch"]
169 fn qdatetimeToSecsSinceEpoch(datetime: &QDateTime) -> i64;
170 #[rust_name = "qdatetime_settimezone"]
171 fn qdatetimeSetTimeZone(datetime: &mut QDateTime, time_zone: &QTimeZone);
172 }
173
174 #[namespace = "rust::cxxqtlib1"]
175 unsafe extern "C++" {
176 include!("cxx-qt-lib/common.h");
177
178 #[doc(hidden)]
179 #[rust_name = "qdatetime_drop"]
180 fn drop(datetime: &mut QDateTime);
181 #[doc(hidden)]
182 #[rust_name = "qdatetime_init_default"]
183 fn construct() -> QDateTime;
184 #[doc(hidden)]
185 #[rust_name = "qdatetime_init_from_date_and_time_time_zone"]
186 fn construct(date: &QDate, time: &QTime, time_zone: &QTimeZone) -> QDateTime;
187 #[cfg(not(cxxqt_qt_version_at_least_6_8))]
188 #[doc(hidden)]
189 #[rust_name = "qdatetime_init_from_date_and_time_time_spec"]
190 fn construct(
191 date: &QDate,
192 time: &QTime,
193 time_spec: TimeSpec,
194 offset_seconds: i32,
195 ) -> QDateTime;
196 #[doc(hidden)]
197 #[rust_name = "qdatetime_init_from_qdatetime"]
198 fn construct(datetime: &QDateTime) -> QDateTime;
199
200 #[doc(hidden)]
201 #[rust_name = "qdatetime_eq"]
202 fn operatorEq(a: &QDateTime, b: &QDateTime) -> bool;
203 #[doc(hidden)]
204 #[rust_name = "qdatetime_cmp"]
205 fn operatorCmp(a: &QDateTime, b: &QDateTime) -> i8;
206 #[doc(hidden)]
207 #[rust_name = "qdatetime_to_qstring"]
208 fn toQString(value: &QDateTime) -> QString;
209 }
210}
211
212#[repr(C)]
214pub struct QDateTime {
215 _space: MaybeUninit<usize>,
216}
217
218impl QDateTime {
219 pub fn set_time_zone(&mut self, time_zone: &ffi::QTimeZone) {
221 ffi::qdatetime_settimezone(self, time_zone)
222 }
223
224 pub fn add_days(&self, ndays: i64) -> Self {
226 ffi::qdatetime_add_days(self, ndays)
227 }
228
229 pub fn add_msecs(&self, msecs: i64) -> Self {
231 ffi::qdatetime_add_msecs(self, msecs)
232 }
233
234 pub fn add_secs(&self, secs: i64) -> Self {
236 ffi::qdatetime_add_secs(self, secs)
237 }
238
239 pub fn current_date_time() -> Self {
241 ffi::qdatetime_current_date_time()
242 }
243
244 pub fn current_date_time_utc() -> Self {
246 ffi::qdatetime_current_date_time_utc()
247 }
248
249 pub fn current_msecs_since_epoch() -> i64 {
252 ffi::qdatetime_current_msecs_since_epoch()
253 }
254
255 pub fn current_secs_since_epoch() -> i64 {
257 ffi::qdatetime_current_secs_since_epoch()
258 }
259
260 pub fn days_to(&self, other: &Self) -> i64 {
264 ffi::qdatetime_days_to(self, other)
265 }
266
267 pub fn from_date_and_time_time_zone(
269 date: &QDate,
270 time: &QTime,
271 time_zone: &ffi::QTimeZone,
272 ) -> Self {
273 ffi::qdatetime_init_from_date_and_time_time_zone(date, time, time_zone)
274 }
275
276 #[cfg(not(cxxqt_qt_version_at_least_6_8))]
280 pub fn from_date_and_time_time_spec(
281 date: &QDate,
282 time: &QTime,
283 time_spec: ffi::TimeSpec,
284 offset_seconds: i32,
285 ) -> Self {
286 ffi::qdatetime_init_from_date_and_time_time_spec(date, time, time_spec, offset_seconds)
287 }
288
289 pub fn from_msecs_since_epoch(msecs: i64, time_zone: &ffi::QTimeZone) -> Self {
292 ffi::qdatetime_from_msecs_since_epoch(msecs, time_zone)
293 }
294
295 pub fn from_secs_since_epoch(secs: i64, time_zone: &ffi::QTimeZone) -> Self {
298 ffi::qdatetime_from_secs_since_epoch(secs, time_zone)
299 }
300
301 pub fn msecs_to(&self, other: &Self) -> i64 {
304 ffi::qdatetime_msecs_to(self, other)
305 }
306
307 pub fn secs_to(&self, other: &Self) -> i64 {
310 ffi::qdatetime_secs_to(self, other)
311 }
312
313 pub fn set_date(&mut self, date: QDate) {
316 ffi::qdatetime_set_date(self, date);
317 }
318
319 pub fn set_msecs_since_epoch(&mut self, msecs: i64) {
322 ffi::qdatetime_set_msecs_since_epoch(self, msecs);
323 }
324
325 pub fn set_secs_since_epoch(&mut self, secs: i64) {
328 ffi::qdatetime_set_secs_since_epoch(self, secs);
329 }
330
331 pub fn set_time(&mut self, time: QTime) {
334 ffi::qdatetime_set_time(self, time);
335 }
336
337 pub fn time_zone(&self) -> cxx::UniquePtr<ffi::QTimeZone> {
339 ffi::qdatetime_time_zone(self)
340 }
341
342 pub fn to_msecs_since_epoch(&self) -> i64 {
344 ffi::qdatetime_to_msecs_since_epoch(self)
345 }
346
347 pub fn to_secs_since_epoch(&self) -> i64 {
349 ffi::qdatetime_to_secs_since_epoch(self)
350 }
351}
352
353impl Clone for QDateTime {
354 fn clone(&self) -> Self {
356 ffi::qdatetime_init_from_qdatetime(self)
357 }
358}
359
360impl Default for QDateTime {
361 fn default() -> Self {
363 ffi::qdatetime_init_default()
364 }
365}
366
367impl PartialEq for QDateTime {
368 fn eq(&self, other: &Self) -> bool {
369 ffi::qdatetime_eq(self, other)
370 }
371}
372
373impl Eq for QDateTime {}
374
375impl PartialOrd for QDateTime {
376 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
377 Some(self.cmp(other))
378 }
379}
380
381impl Ord for QDateTime {
382 fn cmp(&self, other: &Self) -> Ordering {
383 ffi::qdatetime_cmp(self, other).cmp(&0)
384 }
385}
386
387impl fmt::Display for QDateTime {
388 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
389 write!(f, "{}", ffi::qdatetime_to_qstring(self))
390 }
391}
392
393impl fmt::Debug for QDateTime {
394 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
395 write!(f, "{self}")
396 }
397}
398
399impl Drop for QDateTime {
400 fn drop(&mut self) {
402 ffi::qdatetime_drop(self);
403 }
404}
405
406#[cfg(feature = "chrono")]
407use chrono::Offset;
408
409#[cfg(feature = "chrono")]
410impl<Tz: chrono::TimeZone> TryFrom<chrono::DateTime<Tz>> for QDateTime {
411 type Error = &'static str;
412
413 fn try_from(value: chrono::DateTime<Tz>) -> Result<Self, Self::Error> {
414 let tz = crate::QTimeZone::from_offset_seconds(value.offset().fix().local_minus_utc());
415 Ok(QDateTime::from_date_and_time_time_zone(
416 &QDate::from(value.date_naive()),
417 &QTime::try_from(value.time())?,
418 tz.as_ref().ok_or("Could not construct timezone")?,
419 ))
420 }
421}
422
423#[cfg(feature = "chrono")]
424impl TryFrom<QDateTime> for chrono::DateTime<chrono::FixedOffset> {
425 type Error = &'static str;
426
427 fn try_from(value: QDateTime) -> Result<Self, Self::Error> {
428 let timezone_east = chrono::FixedOffset::east_opt(value.offset_from_utc())
429 .expect("out-of-bound offset secs");
430 let value_utc = value.to_utc();
431 let naivedatetime_east = chrono::NaiveDate::try_from(value_utc.date())?
432 .and_time(chrono::NaiveTime::try_from(value_utc.time())?);
433 Ok(
434 chrono::DateTime::<chrono::FixedOffset>::from_naive_utc_and_offset(
435 naivedatetime_east,
436 timezone_east,
437 ),
438 )
439 }
440}
441
442#[cfg(feature = "chrono")]
443impl TryFrom<QDateTime> for chrono::DateTime<chrono::Utc> {
444 type Error = &'static str;
445
446 fn try_from(value: QDateTime) -> Result<Self, Self::Error> {
447 let value_utc = value.to_utc();
448 let naivedatetime_utc = chrono::NaiveDate::try_from(value_utc.date())?
449 .and_time(chrono::NaiveTime::try_from(value_utc.time())?);
450 Ok(chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(
451 naivedatetime_utc,
452 chrono::Utc,
453 ))
454 }
455}
456
457#[cfg(feature = "time")]
458impl From<time::OffsetDateTime> for QDateTime {
459 fn from(value: time::OffsetDateTime) -> Self {
460 let tz = crate::QTimeZone::from_offset_seconds(value.offset().whole_seconds());
461 QDateTime::from_date_and_time_time_zone(
462 &QDate::from(value.date()),
463 &QTime::from(value.time()),
464 tz.as_ref().expect("Could not construct timezone"),
465 )
466 }
467}
468
469#[cfg(feature = "time")]
470impl From<time::PrimitiveDateTime> for QDateTime {
471 fn from(value: time::PrimitiveDateTime) -> Self {
472 let tz = crate::QTimeZone::utc();
473 QDateTime::from_date_and_time_time_zone(
474 &QDate::from(value.date()),
475 &QTime::from(value.time()),
476 tz.as_ref().expect("Could not construct timezone"),
477 )
478 }
479}
480
481#[cfg(feature = "time")]
482impl TryFrom<QDateTime> for time::OffsetDateTime {
483 type Error = time::error::ComponentRange;
484
485 fn try_from(value: QDateTime) -> Result<Self, Self::Error> {
486 Ok(time::Date::try_from(value.date())?
487 .with_time(time::Time::try_from(value.time())?)
488 .assume_offset(time::UtcOffset::from_whole_seconds(
489 value.offset_from_utc(),
490 )?))
491 }
492}
493
494#[cfg(feature = "time")]
495impl TryFrom<QDateTime> for time::PrimitiveDateTime {
496 type Error = time::error::ComponentRange;
497
498 fn try_from(value: QDateTime) -> Result<Self, Self::Error> {
499 let value_utc = value.to_utc();
500 Ok(time::Date::try_from(value_utc.date())?
501 .with_time(time::Time::try_from(value_utc.time())?))
502 }
503}
504
505unsafe impl ExternType for QDateTime {
509 type Id = type_id!("QDateTime");
510 type Kind = cxx::kind::Trivial;
511}
512
513#[cfg(test)]
514mod test {
515 use super::*;
516
517 #[test]
518 fn test_ordering() {
519 let qdatetime_a = QDateTime::from_date_and_time_time_zone(
520 &QDate::new(2023, 1, 1),
521 &QTime::new(1, 1, 1, 1),
522 &ffi::QTimeZone::utc(),
523 );
524 let qdatetime_b = QDateTime::from_date_and_time_time_zone(
525 &QDate::new(2023, 2, 2),
526 &QTime::new(2, 2, 2, 2),
527 &ffi::QTimeZone::utc(),
528 );
529
530 assert!(qdatetime_a < qdatetime_b);
531 assert_eq!(qdatetime_a.cmp(&qdatetime_b), Ordering::Less);
532 assert_eq!(qdatetime_b.cmp(&qdatetime_a), Ordering::Greater);
533 assert_eq!(qdatetime_a.cmp(&qdatetime_a), Ordering::Equal);
534 }
535}
536
537#[cfg(test)]
538#[cfg(feature = "chrono")]
539mod test_chrono {
540 use super::*;
541
542 #[test]
543 fn qdatetime_from_chrono() {
544 let datetime_east = {
545 let timezone_east = chrono::FixedOffset::east_opt(60 * 60).unwrap();
546 let naivedatetime_east = chrono::NaiveDate::from_ymd_opt(2023, 1, 1)
547 .unwrap()
548 .and_hms_milli_opt(1, 2, 3, 4)
549 .unwrap();
550 chrono::DateTime::<chrono::FixedOffset>::from_naive_utc_and_offset(
551 naivedatetime_east,
552 timezone_east,
553 )
554 };
555
556 let qdatetime = QDateTime::from_date_and_time_time_zone(
557 &QDate::new(2023, 1, 1),
558 &QTime::new(1 + 1 , 2, 3, 4),
560 &ffi::QTimeZone::from_offset_seconds(60 * 60),
561 );
562 assert_eq!(QDateTime::try_from(datetime_east).unwrap(), qdatetime);
563 }
564
565 #[test]
566 fn qdatetime_to_chrono_fixed_offset() {
567 let datetime_east = {
568 let timezone_east = chrono::FixedOffset::east_opt(60 * 60).unwrap();
569 let naivedatetime_east = chrono::NaiveDate::from_ymd_opt(2023, 1, 1)
570 .unwrap()
571 .and_hms_milli_opt(1 - 1 , 2, 3, 4)
573 .unwrap();
574 chrono::DateTime::<chrono::FixedOffset>::from_naive_utc_and_offset(
575 naivedatetime_east,
576 timezone_east,
577 )
578 };
579
580 let qdatetime = QDateTime::from_date_and_time_time_zone(
581 &QDate::new(2023, 1, 1),
582 &QTime::new(1, 2, 3, 4),
583 &ffi::QTimeZone::from_offset_seconds(60 * 60),
584 );
585 assert_eq!(
586 chrono::DateTime::<chrono::FixedOffset>::try_from(qdatetime).unwrap(),
587 datetime_east
588 );
589 }
590
591 #[test]
592 fn qdatetime_to_chrono_utc() {
593 let datetime_utc = {
594 let naivedatetime_utc = chrono::NaiveDate::from_ymd_opt(2023, 1, 1)
595 .unwrap()
596 .and_hms_milli_opt(1, 2, 3, 4)
597 .unwrap();
598 chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(
599 naivedatetime_utc,
600 chrono::Utc,
601 )
602 };
603
604 let qdatetime = QDateTime::from_date_and_time_time_zone(
605 &QDate::new(2023, 1, 1),
606 &QTime::new(1, 2, 3, 4),
607 &ffi::QTimeZone::utc(),
608 );
609 assert_eq!(
610 chrono::DateTime::<chrono::Utc>::try_from(qdatetime).unwrap(),
611 datetime_utc
612 );
613 }
614
615 #[test]
616 fn qdatetime_to_chrono_utc_with_offset() {
617 let datetime_utc = {
618 let naivedatetime_utc = chrono::NaiveDate::from_ymd_opt(2023, 1, 1)
619 .unwrap()
620 .and_hms_milli_opt(0, 2, 3, 4)
621 .unwrap();
622 chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(
623 naivedatetime_utc,
624 chrono::Utc,
625 )
626 };
627
628 let qdatetime = QDateTime::from_date_and_time_time_zone(
629 &QDate::new(2023, 1, 1),
630 &QTime::new(1, 2, 3, 4),
631 &ffi::QTimeZone::from_offset_seconds(60 * 60),
633 );
634 assert_eq!(
635 chrono::DateTime::<chrono::Utc>::try_from(qdatetime).unwrap(),
636 datetime_utc
637 );
638 }
639}
640
641#[cfg(test)]
642#[cfg(feature = "time")]
643mod test_time {
644 use super::*;
645
646 #[test]
647 fn qdatetime_to_time_offsetdatetime() {
648 let time_offsetdatetime = time::Date::from_calendar_date(2023, time::Month::January, 1)
649 .unwrap()
650 .with_hms_milli(1, 2, 3, 4)
651 .unwrap()
652 .assume_offset(time::UtcOffset::from_whole_seconds(60 * 60).unwrap());
653
654 let qdatetime = QDateTime::from_date_and_time_time_zone(
655 &QDate::new(2023, 1, 1),
656 &QTime::new(1, 2, 3, 4),
657 &ffi::QTimeZone::from_offset_seconds(60 * 60),
658 );
659 assert_eq!(
660 time::OffsetDateTime::try_from(qdatetime).unwrap(),
661 time_offsetdatetime
662 );
663 }
664
665 #[test]
666 fn qdatetime_to_time_primitivedatetime() {
667 let time_offsetdatetime = time::Date::from_calendar_date(2023, time::Month::January, 1)
668 .unwrap()
669 .with_hms_milli(1, 2, 3, 4)
670 .unwrap();
671
672 let qdatetime = QDateTime::from_date_and_time_time_zone(
673 &QDate::new(2023, 1, 1),
674 &QTime::new(1, 2, 3, 4),
675 &ffi::QTimeZone::utc(),
676 );
677 assert_eq!(
678 time::PrimitiveDateTime::try_from(qdatetime).unwrap(),
679 time_offsetdatetime
680 );
681 }
682
683 #[test]
684 fn qdatetime_from_time_offsetdatetime() {
685 let time_offsetdatetime = time::Date::from_calendar_date(2023, time::Month::January, 1)
686 .unwrap()
687 .with_hms_milli(1, 2, 3, 4)
688 .unwrap()
689 .assume_offset(time::UtcOffset::from_whole_seconds(60 * 60).unwrap());
690
691 let qdatetime = QDateTime::from_date_and_time_time_zone(
692 &QDate::new(2023, 1, 1),
693 &QTime::new(1, 2, 3, 4),
694 &ffi::QTimeZone::from_offset_seconds(60 * 60),
695 );
696 assert_eq!(QDateTime::from(time_offsetdatetime), qdatetime);
697 }
698
699 #[test]
700 fn qdatetime_from_time_primitivedatetime() {
701 let time_offsetdatetime = time::Date::from_calendar_date(2023, time::Month::January, 1)
702 .unwrap()
703 .with_hms_milli(1, 2, 3, 4)
704 .unwrap();
705
706 let qdatetime = QDateTime::from_date_and_time_time_zone(
707 &QDate::new(2023, 1, 1),
708 &QTime::new(1, 2, 3, 4),
709 &ffi::QTimeZone::utc(),
710 );
711 assert_eq!(QDateTime::from(time_offsetdatetime), qdatetime);
712 }
713}