//! # Feature flags //! //! This crate exposes a number of features. These can be enabled or disabled as shown //! [in Cargo's documentation](https://doc.rust-lang.org/cargo/reference/features.html). Features //! are _disabled_ by default unless otherwise noted. //! //! Reliance on a given feature is always indicated alongside the item definition. //! //! - `std` (_enabled by default, implicitly enables `alloc`_) //! //! This enables a number of features that depend on the standard library. //! //! - `alloc` (_enabled by default via `std`_) //! //! Enables a number of features that require the ability to dynamically allocate memory. //! //! - `macros` //! //! Enables macros that provide compile-time verification of values and intuitive syntax. //! //! - `formatting` (_implicitly enables `std`_) //! //! Enables formatting of most structs. //! //! - `parsing` //! //! Enables parsing of most structs. //! //! - `local-offset` (_implicitly enables `std`_) //! //! This feature enables a number of methods that allow obtaining the system's UTC offset. //! //! - `large-dates` //! //! By default, only years within the ±9999 range (inclusive) are supported. If you need support //! for years outside this range, consider enabling this feature; the supported range will be //! increased to ±999,999. //! //! Note that enabling this feature has some costs, as it means forgoing some optimizations. //! Ambiguities may be introduced when parsing that would not otherwise exist. //! //! - `serde` //! //! Enables [serde](https://docs.rs/serde) support for all types except [`Instant`]. //! //! - `serde-human-readable` (_implicitly enables `serde`, `formatting`, and `parsing`_) //! //! Allows serde representations to use a human-readable format. This is determined by the //! serializer, not the user. If this feature is not enabled or if the serializer requests a //! non-human-readable format, a format optimized for binary representation will be used. //! //! Libraries should never enable this feature, as the decision of what format to use should be up //! to the user. //! //! - `serde-well-known` (_implicitly enables `serde-human-readable`_) //! //! _This feature flag is deprecated and will be removed in a future breaking release. Use the //! `serde-human-readable` feature instead._ //! //! Enables support for serializing and deserializing well-known formats using serde's //! [`#[with]` attribute](https://serde.rs/field-attrs.html#with). //! //! - `rand` //! //! Enables [rand](https://docs.rs/rand) support for all types. //! //! - `quickcheck` (_implicitly enables `alloc`_) //! //! Enables [quickcheck](https://docs.rs/quickcheck) support for all types except [`Instant`]. //! //! - `wasm-bindgen` //! //! Enables [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) support for converting //! [JavaScript dates](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Date.html), as //! well as obtaining the UTC offset from JavaScript. #![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; // TODO(jhpratt) remove this after a while #[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." ); // region: macros /// Helper macro for easily implementing `OpAssign`. 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; } } )+}; } /// Implement `AddAssign` for the provided types. macro_rules! impl_add_assign { ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { __impl_assign!(+ AddAssign add_assign $target : $($(#[$attr])* $t),+); }; } /// Implement `SubAssign` for the provided types. macro_rules! impl_sub_assign { ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { __impl_assign!(- SubAssign sub_assign $target : $($(#[$attr])* $t),+); }; } /// Implement `MulAssign` for the provided types. macro_rules! impl_mul_assign { ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { __impl_assign!(* MulAssign mul_assign $target : $($(#[$attr])* $t),+); }; } /// Implement `DivAssign` for the provided types. macro_rules! impl_div_assign { ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { __impl_assign!(/ DivAssign div_assign $target : $($(#[$attr])* $t),+); }; } /// Division of integers, rounding the resulting value towards negative infinity. 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 } }}; } /// Cascade an out-of-bounds value. macro_rules! cascade { (@ordinal ordinal) => {}; (@year year) => {}; // Cascade an out-of-bounds value from "from" to "to". ($from:ident in $min:literal.. $max:literal => $to:tt) => { #[allow(unused_comparisons, unused_assignments)] if $from >= $max { $from -= $max - $min; $to += 1; } else if $from < $min { $from += $max - $min; $to -= 1; } }; // Special case the ordinal-to-year cascade, as it has different behavior. ($ordinal:ident => $year:ident) => { // We need to actually capture the idents. Without this, macro hygiene causes errors. 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; } }; } /// Returns `Err(error::ComponentRange)` if the value is not in range. 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, }); } }}; } /// Try to unwrap an expression, returning if not possible. /// /// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is /// usable in `const` contexts. macro_rules! const_try { ($e:expr) => { match $e { Ok(value) => value, Err(error) => return Err(error), } }; } /// Try to unwrap an expression, returning if not possible. /// /// This is similar to the `?` operator, but is usable in `const` contexts. macro_rules! const_try_opt { ($e:expr) => { match $e { Some(value) => value, None => return None, } }; } /// Try to unwrap an expression, panicking if not possible. /// /// This is similar to `$e.expect($message)`, but is usable in `const` contexts. macro_rules! expect_opt { ($e:expr, $message:literal) => { match $e { Some(value) => value, None => crate::expect_failed($message), } }; } /// `unreachable!()`, but better. 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)?) } } // endregion macros #[macro_use] mod shim; 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; 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; /// An alias for [`std::result::Result`] with a generic error from the time crate. pub type Result = core::result::Result; /// This is a separate function to reduce the code size of `expect_opt!`. #[inline(never)] #[cold] #[track_caller] const fn expect_failed(message: &str) -> ! { panic!("{}", message) }