#![cfg_attr(not(any(test, feature = "std")), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![allow(unused_attributes)]
#![warn(absolute_paths_not_starting_with_crate)]
#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
#![warn(meta_variable_misuse)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(unreachable_pub)]
#![warn(unused_extern_crates)]
#![warn(unused_lifetimes)]
#![warn(unused_results)]
#[cfg_attr(
any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "redox",
),
path = "impl_rustix.rs"
)]
#[cfg_attr(
any(
target_os = "android",
target_os = "darwin",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "illumos",
target_os = "netbsd",
target_os = "solaris",
),
path = "impl_libc.rs"
)]
#[cfg_attr(target_os = "wasi", path = "impl_wasi.rs")]
#[cfg_attr(target_os = "windows", path = "impl_winapi.rs")]
#[cfg_attr(
all(target_arch = "wasm32", not(target_os = "wasi")),
path = "impl_web.rs"
)]
mod platform;
use core::convert::{TryFrom, TryInto};
use core::fmt;
use core::time::Duration;
#[cfg(feature = "std")]
use std::time::SystemTime;
use crate::platform::OsError;
pub const IMPLEMENTED: bool = platform::IMPLEMENTED;
pub const INFALLIBLE: bool = platform::INFALLIBLE;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UtcTime {
secs: i64,
nanos: u32,
}
impl UtcTime {
#[inline]
pub fn now() -> Result<Self> {
utcnow()
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub fn from_system_time(value: SystemTime) -> Option<Self> {
Self::from_duration(value.duration_since(SystemTime::UNIX_EPOCH).ok()?)
}
pub fn from_duration(value: Duration) -> Option<Self> {
let secs = value.as_secs().try_into().ok()?;
let nanos = value.subsec_nanos();
Some(Self { secs, nanos })
}
#[inline]
pub const fn as_secs(self) -> i64 {
self.secs
}
pub const fn as_millis(self) -> i128 {
(self.secs as i128 * 1_000) + (self.nanos as i128 / 1_000_000)
}
pub const fn as_micros(self) -> i128 {
(self.secs as i128 * 1_000_000) + (self.nanos as i128 / 1_000)
}
pub const fn as_nanos(self) -> i128 {
(self.secs as i128 * 1_000_000_000) + (self.nanos as i128)
}
pub const fn subsec_millis(self) -> u32 {
self.nanos / 1_000_000
}
pub const fn subsec_micros(self) -> u32 {
self.nanos / 1_000
}
#[inline]
pub const fn subsec_nanos(self) -> u32 {
self.nanos
}
#[inline]
pub fn into_duration(self) -> core::result::Result<Duration, ConvertionError> {
Ok(Duration::new(
self.secs.try_into().map_err(|_| ConvertionError)?,
self.nanos,
))
}
#[inline]
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub fn into_system_time(self) -> core::result::Result<SystemTime, ConvertionError> {
SystemTime::UNIX_EPOCH
.checked_add(self.try_into()?)
.ok_or(ConvertionError)
}
}
#[inline]
pub fn utcnow() -> Result<UtcTime> {
platform::utcnow()
}
impl TryFrom<UtcTime> for Duration {
type Error = ConvertionError;
#[inline]
fn try_from(value: UtcTime) -> Result<Self, ConvertionError> {
value.into_duration()
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl TryFrom<UtcTime> for SystemTime {
type Error = ConvertionError;
#[inline]
fn try_from(value: UtcTime) -> Result<Self, ConvertionError> {
value.into_system_time()
}
}
impl TryFrom<Duration> for UtcTime {
type Error = ConvertionError;
#[inline]
fn try_from(value: Duration) -> Result<Self, ConvertionError> {
Self::from_duration(value).ok_or(ConvertionError)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl TryFrom<SystemTime> for UtcTime {
type Error = ConvertionError;
#[inline]
fn try_from(value: SystemTime) -> Result<Self, ConvertionError> {
Self::from_system_time(value).ok_or(ConvertionError)
}
}
pub type Result<T, E = Error> = core::result::Result<T, E>;
#[derive(Debug, Clone, Copy)]
pub struct Error(OsError);
impl fmt::Display for Error {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl From<OsError> for Error {
#[inline]
fn from(err: OsError) -> Self {
Self(err)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for Error {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ConvertionError;
impl fmt::Display for ConvertionError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("cannot convert a negative UtcTime")
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for ConvertionError {}
#[cfg(test)]
#[test]
fn test_if_can_call() {
let _ = utcnow().unwrap();
}