use core::{fmt::Display, str::FromStr};
use crate::{Calendar, CalendarTime, OffsetTime, Sigil, TimeZone};
use super::InvalidSigilError;
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct System;
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct SystemSigil;
pub type SystemTime = OffsetTime<SystemSigil>;
impl System {
pub fn now() -> SystemTime {
Self::now_impl()
}
#[cfg(feature = "std")]
fn now_impl() -> SystemTime {
let duration = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("Current time was before posix epoch");
let pseudo_nanos = i128::try_from(duration.as_nanos())
.expect("Overflow trying to retrieve the current time");
let extra_nanos = 0;
SystemTime::from_pseudo_nanos_since_posix_epoch(SystemSigil, pseudo_nanos, extra_nanos)
}
#[cfg(not(feature = "std"))]
fn now_impl() -> SystemTime {
panic!("Running on no-std with no known implementation of time-getting");
}
}
impl TimeZone for System {
type Sigil = SystemSigil;
}
impl Calendar for System {
type Time = SystemTime;
fn try_now(&self) -> crate::Result<Self::Time> {
Ok(Self::now())
}
fn now(&self) -> Self::Time {
Self::now()
}
fn write(&self, t: &crate::Time) -> crate::Result<Self::Time> {
let t = crate::providers::SYSTEM.write(t)?;
Ok(Self::Time::from_pseudo_nanos_since_posix_epoch(
SystemSigil,
t.as_pseudo_nanos_since_posix_epoch(),
t.extra_nanos(),
))
}
}
impl Sigil for SystemSigil {
fn read(&self, t: &OffsetTime<Self>) -> crate::Result<crate::TimeResult> {
OffsetTime::<crate::providers::SystemSigil>::from_pseudo_nanos_since_posix_epoch(
crate::providers::SYSTEM_SIGIL,
t.as_pseudo_nanos_since_posix_epoch(),
t.extra_nanos(),
)
.read()
}
}
impl Display for SystemSigil {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("Z")
}
}
impl FromStr for SystemSigil {
type Err = InvalidSigilError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Z" => Ok(SystemSigil),
" UTC" => Ok(SystemSigil),
_ => Err(InvalidSigilError),
}
}
}