#![cfg_attr(__time_02_docs, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
anonymous_parameters,
clippy::all,
const_err,
illegal_floating_point_literal_pattern,
late_bound_lifetime_arguments,
path_statements,
patterns_in_fns_without_body,
rust_2018_idioms,
trivial_casts,
trivial_numeric_casts,
unreachable_pub,
unsafe_code,
unused_extern_crates
)]
#![warn(
clippy::dbg_macro,
clippy::decimal_literal_representation,
clippy::get_unwrap,
clippy::missing_docs_in_private_items,
clippy::nursery,
clippy::pedantic,
clippy::print_stdout,
clippy::todo,
clippy::unimplemented,
clippy::unwrap_used,
clippy::use_debug,
missing_copy_implementations,
missing_debug_implementations,
single_use_lifetimes,
unused_qualifications,
variant_size_differences
)]
#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::enum_glob_use,
clippy::inline_always,
clippy::map_err_ignore,
clippy::missing_errors_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::redundant_pub_crate,
clippy::suspicious_arithmetic_impl,
clippy::suspicious_op_assign_impl,
clippy::use_self,
clippy::wildcard_imports,
clippy::zero_prefixed_literal,
unstable_name_collisions
)]
#![cfg_attr(
test,
allow(
clippy::cognitive_complexity,
clippy::similar_names,
clippy::too_many_lines,
)
)]
#![doc(html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(test(attr(deny(warnings))))]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "panicking-api")]
#[cfg_attr(__time_02_docs, doc(cfg(feature = "panicking-api")))]
macro_rules! format_conditional {
($conditional:ident) => {{
#[cfg(not(feature = "std"))]
use alloc::format;
format!(concat!(stringify!($conditional), "={}"), $conditional)
}};
($first_conditional:ident, $($conditional:ident),*) => {{
#[cfg(not(feature = "std"))]
use alloc::{format, string::String};
let mut s = String::new();
s.push_str(&format_conditional!($first_conditional));
$(s.push_str(&format!(concat!(", ", stringify!($conditional), "={}"), $conditional));)*
s
}}
}
#[cfg(feature = "panicking-api")]
#[cfg_attr(__time_02_docs, doc(cfg(feature = "panicking-api")))]
macro_rules! assert_value_in_range {
($value:ident in $start:expr => $end:expr) => {{
#[allow(unused_imports)]
use standback::prelude::*;
if !($start..=$end).contains(&$value) {
panic!(
concat!(stringify!($value), " must be in the range {}..={} (was {})"),
$start,
$end,
$value,
);
}
}};
($value:ident in $start:expr => $end:expr, given $($conditional:ident),+ $(,)?) => {{
#[allow(unused_imports)]
use standback::prelude::*;
if !($start..=$end).contains(&$value) {
panic!(
concat!(stringify!($value), " must be in the range {}..={} given{} (was {})"),
$start,
$end,
&format_conditional!($($conditional),+),
$value,
);
}
}};
}
macro_rules! ensure_value_in_range {
($value:ident in $start:expr => $end:expr) => {{
#![allow(
trivial_numeric_casts,
unused_comparisons,
clippy::manual_range_contains
)]
if $value < $start || $value > $end {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $start as i64,
maximum: $end as i64,
value: $value as i64,
conditional_range: false,
#[cfg(not(__time_02_supports_non_exhaustive))]
__non_exhaustive: (),
});
}
}};
($value:ident conditionally in $start:expr => $end:expr) => {{
#![allow(
trivial_numeric_casts,
unused_comparisons,
clippy::manual_range_contains
)]
if $value < $start || $value > $end {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $start as i64,
maximum: $end as i64,
value: $value as i64,
conditional_range: true,
#[cfg(not(__time_02_supports_non_exhaustive))]
__non_exhaustive: (),
});
}
}};
}
macro_rules! const_try {
($e:expr) => {
match $e {
Ok(value) => value,
Err(error) => return Err(error),
}
};
}
mod date;
mod duration;
pub mod error;
pub mod ext;
mod format;
#[cfg(feature = "std")]
mod instant;
pub mod internals;
mod offset_date_time;
mod primitive_date_time;
#[cfg(feature = "rand")]
mod rand;
#[cfg(feature = "serde")]
#[allow(missing_copy_implementations, missing_debug_implementations)]
pub mod serde;
mod sign;
mod time_mod;
mod utc_offset;
pub mod util;
mod weekday;
pub use date::Date;
pub use duration::Duration;
pub use error::Error;
#[deprecated(
since = "0.2.23",
note = "Errors have been moved to the `error` module."
)]
pub use error::{
ComponentRange as ComponentRangeError, ConversionRange as ConversionRangeError,
IndeterminateOffset as IndeterminateOffsetError, Parse as ParseError,
};
#[deprecated(
since = "0.2.23",
note = "Extension traits have been moved to the `ext` module."
)]
pub use ext::{NumericalDuration, NumericalStdDuration, NumericalStdDurationShort};
pub(crate) use format::DeferredFormat;
pub use format::Format;
use format::ParseResult;
#[cfg(feature = "std")]
pub use instant::Instant;
#[deprecated(
since = "0.2.23",
note = "Macros have been moved to the `macros` module."
)]
pub use macros::{date, offset, time};
pub use offset_date_time::OffsetDateTime;
pub use primitive_date_time::PrimitiveDateTime;
#[allow(deprecated)]
pub use sign::Sign;
#[allow(unused_imports)]
use standback::prelude::*;
pub use time_mod::Time;
pub use utc_offset::UtcOffset;
#[deprecated(
since = "0.2.23",
note = "This function has been moved to the `util` module."
)]
pub use util::{days_in_year, is_leap_year, validate_format_string, weeks_in_year};
pub use weekday::Weekday;
pub type Result<T> = core::result::Result<T, Error>;
pub mod prelude {
#[cfg(not(__time_02_use_trait_as_underscore))]
pub use crate::ext::{NumericalDuration, NumericalStdDuration};
#[cfg(__time_02_use_trait_as_underscore)]
pub use crate::ext::{NumericalDuration as _, NumericalStdDuration as _};
pub use time_macros::{date, offset, time};
}
#[allow(clippy::missing_docs_in_private_items)]
mod private {
use super::*;
macro_rules! parsable {
($($type:ty),* $(,)?) => {
$(
impl Parsable for $type {
fn parse(s: impl AsRef<str>, format: impl AsRef<str>) -> ParseResult<Self> {
Self::parse(s, format)
}
}
)*
};
}
pub trait Parsable: Sized {
fn parse(s: impl AsRef<str>, format: impl AsRef<str>) -> ParseResult<Self>;
}
parsable![Time, Date, UtcOffset, PrimitiveDateTime, OffsetDateTime];
}
pub fn parse<T: private::Parsable>(s: impl AsRef<str>, format: impl AsRef<str>) -> ParseResult<T> {
private::Parsable::parse(s, format)
}
pub mod macros {
pub use time_macros::date;
pub use time_macros::offset;
pub use time_macros::time;
}
#[cfg(all(feature = "std", feature = "deprecated"))]
#[allow(clippy::missing_docs_in_private_items)]
#[deprecated(since = "0.2.0", note = "Use `Instant`")]
pub type PreciseTime = Instant;
#[cfg(all(feature = "std", feature = "deprecated"))]
#[allow(clippy::missing_docs_in_private_items)]
#[deprecated(since = "0.2.0", note = "Use `Instant`")]
pub type SteadyTime = Instant;
#[cfg(all(feature = "std", feature = "deprecated"))]
#[allow(clippy::missing_docs_in_private_items)]
#[deprecated(
since = "0.2.0",
note = "Use `OffsetDateTime::now() - OffsetDateTime::unix_epoch()` to get a `Duration` since \
a known epoch."
)]
pub fn precise_time_ns() -> u64 {
use standback::convert::TryInto;
use std::time::SystemTime;
(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH))
.expect("System clock was before 1970.")
.as_nanos()
.try_into()
.expect("This function will be removed long before this is an issue.")
}
#[cfg(all(feature = "std", feature = "deprecated"))]
#[allow(clippy::missing_docs_in_private_items)]
#[deprecated(
since = "0.2.0",
note = "Use `OffsetDateTime::now() - OffsetDateTime::unix_epoch()` to get a `Duration` since \
a known epoch."
)]
pub fn precise_time_s() -> f64 {
use std::time::SystemTime;
(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH))
.expect("System clock was before 1970.")
.as_secs_f64()
}