#![doc(html_playground_url = "https://play.rust-lang.org")]
#![cfg_attr(__time_03_docs, feature(doc_auto_cfg, doc_notable_trait))]
#![cfg_attr(coverage_nightly, feature(no_coverage))]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
anonymous_parameters,
clippy::all,
clippy::alloc_instead_of_core,
clippy::explicit_auto_deref,
clippy::obfuscated_if_else,
clippy::std_instead_of_core,
clippy::undocumented_unsafe_blocks,
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_op_in_unsafe_fn,
unused_extern_crates,
rustdoc::broken_intra_doc_links,
rustdoc::private_intra_doc_links
)]
#![warn(
clippy::dbg_macro,
clippy::decimal_literal_representation,
clippy::get_unwrap,
clippy::missing_docs_in_private_items,
clippy::nursery,
clippy::print_stdout,
clippy::todo,
clippy::unimplemented,
clippy::uninlined_format_args,
clippy::unnested_or_patterns,
clippy::unwrap_in_result,
clippy::unwrap_used,
clippy::use_debug,
deprecated_in_future,
missing_copy_implementations,
missing_debug_implementations,
unused_qualifications,
variant_size_differences
)]
#![allow(
clippy::redundant_pub_crate, // suggests bad style
clippy::option_if_let_else, // suggests terrible code
clippy::unused_peekable, // temporary due to bug: remove when Rust 1.66 is released
clippy::std_instead_of_core, // temporary due to bug: remove when Rust 1.66 is released
)]
#![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))))]
#[allow(unused_extern_crates)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(unsound_local_offset)]
compile_error!(
"The `unsound_local_offset` flag was removed in time 0.3.18. If you need this functionality, \
see the `time::util::local_offset::set_soundness` function."
);
macro_rules! __impl_assign {
($sym:tt $op:ident $fn:ident $target:ty : $($(#[$attr:meta])* $t:ty),+) => {$(
#[allow(unused_qualifications)]
$(#[$attr])*
impl core::ops::$op<$t> for $target {
fn $fn(&mut self, rhs: $t) {
*self = *self $sym rhs;
}
}
)+};
}
macro_rules! impl_add_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
__impl_assign!(+ AddAssign add_assign $target : $($(#[$attr])* $t),+);
};
}
macro_rules! impl_sub_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
__impl_assign!(- SubAssign sub_assign $target : $($(#[$attr])* $t),+);
};
}
macro_rules! impl_mul_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
__impl_assign!(* MulAssign mul_assign $target : $($(#[$attr])* $t),+);
};
}
macro_rules! impl_div_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
__impl_assign!(/ DivAssign div_assign $target : $($(#[$attr])* $t),+);
};
}
macro_rules! div_floor {
($a:expr, $b:expr) => {{
let _a = $a;
let _b = $b;
let (_quotient, _remainder) = (_a / _b, _a % _b);
if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) {
_quotient - 1
} else {
_quotient
}
}};
}
macro_rules! cascade {
(@ordinal ordinal) => {};
(@year year) => {};
($from:ident in $min:literal.. $max:expr => $to:tt) => {
#[allow(unused_comparisons, unused_assignments)]
let min = $min;
let max = $max;
if $from >= max {
$from -= max - min;
$to += 1;
} else if $from < min {
$from += max - min;
$to -= 1;
}
};
($ordinal:ident => $year:ident) => {
cascade!(@ordinal $ordinal);
cascade!(@year $year);
#[allow(unused_assignments)]
if $ordinal > crate::util::days_in_year($year) as i16 {
$ordinal -= crate::util::days_in_year($year) as i16;
$year += 1;
} else if $ordinal < 1 {
$year -= 1;
$ordinal += crate::util::days_in_year($year) as i16;
}
};
}
macro_rules! ensure_value_in_range {
($value:ident in $start:expr => $end:expr) => {{
let _start = $start;
let _end = $end;
#[allow(trivial_numeric_casts, unused_comparisons)]
if $value < _start || $value > _end {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: _start as _,
maximum: _end as _,
value: $value as _,
conditional_range: false,
});
}
}};
($value:ident conditionally in $start:expr => $end:expr) => {{
let _start = $start;
let _end = $end;
#[allow(trivial_numeric_casts, unused_comparisons)]
if $value < _start || $value > _end {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: _start as _,
maximum: _end as _,
value: $value as _,
conditional_range: true,
});
}
}};
}
macro_rules! ensure_ranged {
($type:ident : $value:ident) => {
match $type::new($value) {
Some(val) => val,
None => {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $type::MIN.get() as _,
maximum: $type::MAX.get() as _,
value: $value as _,
conditional_range: false,
});
}
}
};
($type:ident : $value:ident $(as $as_type:ident)? * $factor:expr) => {
match ($value $(as $as_type)?).checked_mul($factor) {
Some(val) => match $type::new(val) {
Some(val) => val,
None => {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $type::MIN.get() as i64 / $factor as i64,
maximum: $type::MAX.get() as i64 / $factor as i64,
value: $value as _,
conditional_range: false,
});
}
},
None => {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $type::MIN.get() as i64 / $factor as i64,
maximum: $type::MAX.get() as i64 / $factor as i64,
value: $value as _,
conditional_range: false,
});
}
}
};
}
macro_rules! const_try {
($e:expr) => {
match $e {
Ok(value) => value,
Err(error) => return Err(error),
}
};
}
macro_rules! const_try_opt {
($e:expr) => {
match $e {
Some(value) => value,
None => return None,
}
};
}
macro_rules! expect_opt {
($e:expr, $message:literal) => {
match $e {
Some(value) => value,
None => crate::expect_failed($message),
}
};
}
macro_rules! bug {
() => { compile_error!("provide an error message to help fix a possible bug") };
($descr:literal $($rest:tt)?) => {
panic!(concat!("internal error: ", $descr) $($rest)?)
}
}
mod date;
mod date_time;
mod duration;
pub mod error;
pub mod ext;
#[cfg(any(feature = "formatting", feature = "parsing"))]
pub mod format_description;
#[cfg(feature = "formatting")]
pub mod formatting;
#[cfg(feature = "std")]
mod instant;
#[cfg(feature = "macros")]
pub mod macros;
mod month;
mod offset_date_time;
#[cfg(feature = "parsing")]
pub mod parsing;
mod primitive_date_time;
#[cfg(feature = "quickcheck")]
mod quickcheck;
#[cfg(feature = "rand")]
mod rand;
#[cfg(feature = "serde")]
#[allow(missing_copy_implementations, missing_debug_implementations)]
pub mod serde;
mod sys;
#[cfg(test)]
mod tests;
mod time;
mod utc_offset;
pub mod util;
mod weekday;
use time_core::convert;
pub use crate::date::Date;
use crate::date_time::DateTime;
pub use crate::duration::Duration;
pub use crate::error::Error;
#[cfg(feature = "std")]
pub use crate::instant::Instant;
pub use crate::month::Month;
pub use crate::offset_date_time::OffsetDateTime;
pub use crate::primitive_date_time::PrimitiveDateTime;
pub use crate::time::Time;
pub use crate::utc_offset::UtcOffset;
pub use crate::weekday::Weekday;
pub type Result<T> = core::result::Result<T, Error>;
#[inline(never)]
#[cold]
#[track_caller]
const fn expect_failed(message: &str) -> ! {
panic!("{}", message)
}