use std::{
fmt,
time::{Duration, SystemTime, UNIX_EPOCH},
}; use time::{format_description::well_known::Rfc3339, OffsetDateTime, UtcOffset};
/// A UTC timestamp used for serialization to and from the plist date type. /// /// Note that while this type implements `Serialize` and `Deserialize` it will behave strangely if /// used with serializers from outside this crate. #[derive(Clone, Copy, Eq, Hash, PartialEq)] pubstruct Date {
inner: SystemTime,
}
/// An error indicating that a string was not a valid XML plist date. #[derive(Debug)] #[non_exhaustive] pubstruct InvalidXmlDate;
pub(crate) struct InfiniteOrNanDate;
impl Date { /// The unix timestamp of the plist epoch. const PLIST_EPOCH_UNIX_TIMESTAMP: Duration = Duration::from_secs(978_307_200);
/// Converts an XML plist date string to a `Date`. pubfn from_xml_format(date: &str) -> Result<Self, InvalidXmlDate> { let offset: OffsetDateTime = OffsetDateTime::parse(date, &Rfc3339)
.map_err(|_| InvalidXmlDate)?
.to_offset(UtcOffset::UTC);
Ok(Date {
inner: offset.into(),
})
}
/// Converts the `Date` to an XML plist date string. pubfn to_xml_format(&self) -> String { let datetime: OffsetDateTime = self.inner.into();
datetime.format(&Rfc3339).unwrap()
}
pub(crate) fn from_seconds_since_plist_epoch(
timestamp: f64,
) -> Result<Date, InfiniteOrNanDate> { // `timestamp` is the number of seconds since the plist epoch of 1/1/2001 00:00:00. let plist_epoch = UNIX_EPOCH + Date::PLIST_EPOCH_UNIX_TIMESTAMP;
if !timestamp.is_finite() { return Err(InfiniteOrNanDate);
}
let is_negative = timestamp < 0.0; let timestamp = timestamp.abs(); let seconds = timestamp.floor() as u64; let subsec_nanos = (timestamp.fract() * 1e9) as u32;
let dur_since_plist_epoch = Duration::new(seconds, subsec_nanos);
let inner = if is_negative {
plist_epoch.checked_sub(dur_since_plist_epoch)
} else {
plist_epoch.checked_add(dur_since_plist_epoch)
};
impl fmt::Display for InvalidXmlDate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("String was not a valid XML plist date")
}
}
impl std::error::Error for InvalidXmlDate {}
#[cfg(feature = "serde")] pubmod serde_impls { use serde::{
de::{Deserialize, Deserializer, Error, Unexpected, Visitor},
ser::{Serialize, Serializer},
}; use std::fmt;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.