diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/core-foundation/src/date.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/core-foundation/src/date.rs')
-rw-r--r-- | vendor/core-foundation/src/date.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/vendor/core-foundation/src/date.rs b/vendor/core-foundation/src/date.rs new file mode 100644 index 000000000..57ee7211e --- /dev/null +++ b/vendor/core-foundation/src/date.rs @@ -0,0 +1,130 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Core Foundation date objects. + +pub use core_foundation_sys::date::*; +use core_foundation_sys::base::kCFAllocatorDefault; + +use base::TCFType; + +#[cfg(feature = "with-chrono")] +use chrono::NaiveDateTime; + + +declare_TCFType!{ + /// A date. + CFDate, CFDateRef +} +impl_TCFType!(CFDate, CFDateRef, CFDateGetTypeID); +impl_CFTypeDescription!(CFDate); +impl_CFComparison!(CFDate, CFDateCompare); + +impl CFDate { + #[inline] + pub fn new(time: CFAbsoluteTime) -> CFDate { + unsafe { + let date_ref = CFDateCreate(kCFAllocatorDefault, time); + TCFType::wrap_under_create_rule(date_ref) + } + } + + #[inline] + pub fn now() -> CFDate { + CFDate::new(unsafe { CFAbsoluteTimeGetCurrent() }) + } + + #[inline] + pub fn abs_time(&self) -> CFAbsoluteTime { + unsafe { + CFDateGetAbsoluteTime(self.0) + } + } + + #[cfg(feature = "with-chrono")] + pub fn naive_utc(&self) -> NaiveDateTime { + let ts = unsafe { + self.abs_time() + kCFAbsoluteTimeIntervalSince1970 + }; + let (secs, nanos) = if ts.is_sign_positive() { + (ts.trunc() as i64, ts.fract()) + } else { + // nanoseconds can't be negative in NaiveDateTime + (ts.trunc() as i64 - 1, 1.0 - ts.fract().abs()) + }; + NaiveDateTime::from_timestamp(secs, (nanos * 1e9).floor() as u32) + } + + #[cfg(feature = "with-chrono")] + pub fn from_naive_utc(time: NaiveDateTime) -> CFDate { + let secs = time.timestamp(); + let nanos = time.timestamp_subsec_nanos(); + let ts = unsafe { + secs as f64 + (nanos as f64 / 1e9) - kCFAbsoluteTimeIntervalSince1970 + }; + CFDate::new(ts) + } +} + +#[cfg(test)] +mod test { + use super::CFDate; + use std::cmp::Ordering; + + #[cfg(feature = "with-chrono")] + use chrono::NaiveDateTime; + + #[cfg(feature = "with-chrono")] + fn approx_eq(a: f64, b: f64) -> bool { + use std::f64; + + let same_sign = a.is_sign_positive() == b.is_sign_positive(); + let equal = ((a - b).abs() / f64::min(a.abs() + b.abs(), f64::MAX)) < f64::EPSILON; + (same_sign && equal) + } + + #[test] + fn date_comparison() { + let now = CFDate::now(); + let past = CFDate::new(now.abs_time() - 1.0); + assert_eq!(now.cmp(&past), Ordering::Greater); + assert_eq!(now.cmp(&now), Ordering::Equal); + assert_eq!(past.cmp(&now), Ordering::Less); + } + + #[test] + fn date_equality() { + let now = CFDate::now(); + let same_time = CFDate::new(now.abs_time()); + assert_eq!(now, same_time); + } + + #[test] + #[cfg(feature = "with-chrono")] + fn date_chrono_conversion_positive() { + let date = CFDate::now(); + let datetime = date.naive_utc(); + let converted = CFDate::from_naive_utc(datetime); + assert!(approx_eq(date.abs_time(), converted.abs_time())); + } + + #[test] + #[cfg(feature = "with-chrono")] + fn date_chrono_conversion_negative() { + use super::kCFAbsoluteTimeIntervalSince1970; + + let ts = unsafe { + kCFAbsoluteTimeIntervalSince1970 - 420.0 + }; + let date = CFDate::new(ts); + let datetime: NaiveDateTime = date.naive_utc(); + let converted = CFDate::from_naive_utc(datetime); + assert!(approx_eq(date.abs_time(), converted.abs_time())); + } +} |