| //! # 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: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; |
| } |
| }; |
| |
| // 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 |
| |
| 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; |
| |
| // Not public yet. |
| 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; |
| |
| /// An alias for [`std::result::Result`] with a generic error from the time crate. |
| pub type Result<T> = core::result::Result<T, Error>; |
| |
| /// 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) |
| } |