1//! # Feature flags
2//!
3//! This crate exposes a number of features. These can be enabled or disabled as shown
4//! [in Cargo's documentation](https://doc.rust-lang.org/cargo/reference/features.html). Features
5//! are _disabled_ by default unless otherwise noted.
6//!
7//! Reliance on a given feature is always indicated alongside the item definition.
8//!
9//! - `std` (_enabled by default, implicitly enables `alloc`_)
10//!
11//! This enables a number of features that depend on the standard library.
12//!
13//! - `alloc` (_enabled by default via `std`_)
14//!
15//! Enables a number of features that require the ability to dynamically allocate memory.
16//!
17//! - `macros`
18//!
19//! Enables macros that provide compile-time verification of values and intuitive syntax.
20//!
21//! - `formatting` (_implicitly enables `std`_)
22//!
23//! Enables formatting of most structs.
24//!
25//! - `parsing`
26//!
27//! Enables parsing of most structs.
28//!
29//! - `local-offset` (_implicitly enables `std`_)
30//!
31//! This feature enables a number of methods that allow obtaining the system's UTC offset.
32//!
33//! - `large-dates`
34//!
35//! By default, only years within the ±9999 range (inclusive) are supported. If you need support
36//! for years outside this range, consider enabling this feature; the supported range will be
37//! increased to ±999,999.
38//!
39//! Note that enabling this feature has some costs, as it means forgoing some optimizations.
40//! Ambiguities may be introduced when parsing that would not otherwise exist.
41//!
42//! - `serde`
43//!
44//! Enables [serde](https://docs.rs/serde) support for all types except [`Instant`].
45//!
46//! - `serde-human-readable` (_implicitly enables `serde`, `formatting`, and `parsing`_)
47//!
48//! Allows serde representations to use a human-readable format. This is determined by the
49//! serializer, not the user. If this feature is not enabled or if the serializer requests a
50//! non-human-readable format, a format optimized for binary representation will be used.
51//!
52//! Libraries should never enable this feature, as the decision of what format to use should be up
53//! to the user.
54//!
55//! - `serde-well-known` (_implicitly enables `serde-human-readable`_)
56//!
57//! _This feature flag is deprecated and will be removed in a future breaking release. Use the
58//! `serde-human-readable` feature instead._
59//!
60//! Enables support for serializing and deserializing well-known formats using serde's
61//! [`#[with]` attribute](https://serde.rs/field-attrs.html#with).
62//!
63//! - `rand`
64//!
65//! Enables [rand](https://docs.rs/rand) support for all types.
66//!
67//! - `quickcheck` (_implicitly enables `alloc`_)
68//!
69//! Enables [quickcheck](https://docs.rs/quickcheck) support for all types except [`Instant`].
70//!
71//! - `wasm-bindgen`
72//!
73//! Enables [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) support for converting
74//! [JavaScript dates](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Date.html), as
75//! well as obtaining the UTC offset from JavaScript.
76
77#![doc(html_playground_url = "https://play.rust-lang.org")]
78#![cfg_attr(__time_03_docs, feature(doc_auto_cfg, doc_notable_trait))]
79#![cfg_attr(coverage_nightly, feature(no_coverage))]
80#![cfg_attr(not(feature = "std"), no_std)]
81#![deny(
82 anonymous_parameters,
83 clippy::all,
84 clippy::alloc_instead_of_core,
85 clippy::explicit_auto_deref,
86 clippy::obfuscated_if_else,
87 clippy::std_instead_of_core,
88 clippy::undocumented_unsafe_blocks,
89 illegal_floating_point_literal_pattern,
90 late_bound_lifetime_arguments,
91 path_statements,
92 patterns_in_fns_without_body,
93 rust_2018_idioms,
94 trivial_casts,
95 trivial_numeric_casts,
96 unreachable_pub,
97 unsafe_op_in_unsafe_fn,
98 unused_extern_crates,
99 rustdoc::broken_intra_doc_links,
100 rustdoc::private_intra_doc_links
101)]
102#![warn(
103 clippy::dbg_macro,
104 clippy::decimal_literal_representation,
105 clippy::get_unwrap,
106 clippy::missing_docs_in_private_items,
107 clippy::nursery,
108 clippy::print_stdout,
109 clippy::todo,
110 clippy::unimplemented,
111 clippy::uninlined_format_args,
112 clippy::unnested_or_patterns,
113 clippy::unwrap_in_result,
114 clippy::unwrap_used,
115 clippy::use_debug,
116 deprecated_in_future,
117 missing_copy_implementations,
118 missing_debug_implementations,
119 unused_qualifications,
120 variant_size_differences
121)]
122#![allow(
123 clippy::redundant_pub_crate, // suggests bad style
124 clippy::option_if_let_else, // suggests terrible code
125 clippy::unused_peekable, // temporary due to bug: remove when Rust 1.66 is released
126 clippy::std_instead_of_core, // temporary due to bug: remove when Rust 1.66 is released
127)]
128#![doc(html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857")]
129#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/55999857")]
130#![doc(test(attr(deny(warnings))))]
131
132#[allow(unused_extern_crates)]
133#[cfg(feature = "alloc")]
134extern crate alloc;
135
136// TODO(jhpratt) remove this after a while
137#[cfg(unsound_local_offset)]
138compile_error!(
139 "The `unsound_local_offset` flag was removed in time 0.3.18. If you need this functionality, \
140 see the `time::util::local_offset::set_soundness` function."
141);
142
143// region: macros
144/// Helper macro for easily implementing `OpAssign`.
145macro_rules! __impl_assign {
146 ($sym:tt $op:ident $fn:ident $target:ty : $($(#[$attr:meta])* $t:ty),+) => {$(
147 #[allow(unused_qualifications)]
148 $(#[$attr])*
149 impl core::ops::$op<$t> for $target {
150 fn $fn(&mut self, rhs: $t) {
151 *self = *self $sym rhs;
152 }
153 }
154 )+};
155}
156
157/// Implement `AddAssign` for the provided types.
158macro_rules! impl_add_assign {
159 ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
160 __impl_assign!(+ AddAssign add_assign $target : $($(#[$attr])* $t),+);
161 };
162}
163
164/// Implement `SubAssign` for the provided types.
165macro_rules! impl_sub_assign {
166 ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
167 __impl_assign!(- SubAssign sub_assign $target : $($(#[$attr])* $t),+);
168 };
169}
170
171/// Implement `MulAssign` for the provided types.
172macro_rules! impl_mul_assign {
173 ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
174 __impl_assign!(* MulAssign mul_assign $target : $($(#[$attr])* $t),+);
175 };
176}
177
178/// Implement `DivAssign` for the provided types.
179macro_rules! impl_div_assign {
180 ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
181 __impl_assign!(/ DivAssign div_assign $target : $($(#[$attr])* $t),+);
182 };
183}
184
185/// Division of integers, rounding the resulting value towards negative infinity.
186macro_rules! div_floor {
187 ($a:expr, $b:expr) => {{
188 let _a = $a;
189 let _b = $b;
190
191 let (_quotient, _remainder) = (_a / _b, _a % _b);
192
193 if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) {
194 _quotient - 1
195 } else {
196 _quotient
197 }
198 }};
199}
200
201/// Cascade an out-of-bounds value.
202macro_rules! cascade {
203 (@ordinal ordinal) => {};
204 (@year year) => {};
205
206 // Cascade an out-of-bounds value from "from" to "to".
207 ($from:ident in $min:literal.. $max:expr => $to:tt) => {
208 #[allow(unused_comparisons, unused_assignments)]
209 let min = $min;
210 let max = $max;
211 if $from >= max {
212 $from -= max - min;
213 $to += 1;
214 } else if $from < min {
215 $from += max - min;
216 $to -= 1;
217 }
218 };
219
220 // Special case the ordinal-to-year cascade, as it has different behavior.
221 ($ordinal:ident => $year:ident) => {
222 // We need to actually capture the idents. Without this, macro hygiene causes errors.
223 cascade!(@ordinal $ordinal);
224 cascade!(@year $year);
225 #[allow(unused_assignments)]
226 if $ordinal > crate::util::days_in_year($year) as i16 {
227 $ordinal -= crate::util::days_in_year($year) as i16;
228 $year += 1;
229 } else if $ordinal < 1 {
230 $year -= 1;
231 $ordinal += crate::util::days_in_year($year) as i16;
232 }
233 };
234}
235
236/// Returns `Err(error::ComponentRange)` if the value is not in range.
237macro_rules! ensure_value_in_range {
238 ($value:ident in $start:expr => $end:expr) => {{
239 let _start = $start;
240 let _end = $end;
241 #[allow(trivial_numeric_casts, unused_comparisons)]
242 if $value < _start || $value > _end {
243 return Err(crate::error::ComponentRange {
244 name: stringify!($value),
245 minimum: _start as _,
246 maximum: _end as _,
247 value: $value as _,
248 conditional_range: false,
249 });
250 }
251 }};
252
253 ($value:ident conditionally in $start:expr => $end:expr) => {{
254 let _start = $start;
255 let _end = $end;
256 #[allow(trivial_numeric_casts, unused_comparisons)]
257 if $value < _start || $value > _end {
258 return Err(crate::error::ComponentRange {
259 name: stringify!($value),
260 minimum: _start as _,
261 maximum: _end as _,
262 value: $value as _,
263 conditional_range: true,
264 });
265 }
266 }};
267}
268
269/// Try to unwrap an expression, returning if not possible.
270///
271/// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is
272/// usable in `const` contexts.
273macro_rules! const_try {
274 ($e:expr) => {
275 match $e {
276 Ok(value) => value,
277 Err(error) => return Err(error),
278 }
279 };
280}
281
282/// Try to unwrap an expression, returning if not possible.
283///
284/// This is similar to the `?` operator, but is usable in `const` contexts.
285macro_rules! const_try_opt {
286 ($e:expr) => {
287 match $e {
288 Some(value) => value,
289 None => return None,
290 }
291 };
292}
293
294/// Try to unwrap an expression, panicking if not possible.
295///
296/// This is similar to `$e.expect($message)`, but is usable in `const` contexts.
297macro_rules! expect_opt {
298 ($e:expr, $message:literal) => {
299 match $e {
300 Some(value) => value,
301 None => crate::expect_failed($message),
302 }
303 };
304}
305
306/// `unreachable!()`, but better.
307macro_rules! bug {
308 () => { compile_error!("provide an error message to help fix a possible bug") };
309 ($descr:literal $($rest:tt)?) => {
310 panic!(concat!("internal error: ", $descr) $($rest)?)
311 }
312}
313// endregion macros
314
315mod date;
316mod date_time;
317mod duration;
318pub mod error;
319pub mod ext;
320#[cfg(any(feature = "formatting", feature = "parsing"))]
321pub mod format_description;
322#[cfg(feature = "formatting")]
323pub mod formatting;
324#[cfg(feature = "std")]
325mod instant;
326#[cfg(feature = "macros")]
327pub mod macros;
328mod month;
329mod offset_date_time;
330#[cfg(feature = "parsing")]
331pub mod parsing;
332mod primitive_date_time;
333#[cfg(feature = "quickcheck")]
334mod quickcheck;
335#[cfg(feature = "rand")]
336mod rand;
337#[cfg(feature = "serde")]
338#[allow(missing_copy_implementations, missing_debug_implementations)]
339pub mod serde;
340mod sys;
341#[cfg(test)]
342mod tests;
343mod time;
344mod utc_offset;
345pub mod util;
346mod weekday;
347
348// Not public yet.
349use time_core::convert;
350
351pub use crate::date::Date;
352use crate::date_time::DateTime;
353pub use crate::duration::Duration;
354pub use crate::error::Error;
355#[cfg(feature = "std")]
356pub use crate::instant::Instant;
357pub use crate::month::Month;
358pub use crate::offset_date_time::OffsetDateTime;
359pub use crate::primitive_date_time::PrimitiveDateTime;
360pub use crate::time::Time;
361pub use crate::utc_offset::UtcOffset;
362pub use crate::weekday::Weekday;
363
364/// An alias for [`std::result::Result`] with a generic error from the time crate.
365pub type Result<T> = core::result::Result<T, Error>;
366
367/// This is a separate function to reduce the code size of `expect_opt!`.
368#[inline(never)]
369#[cold]
370#[track_caller]
371const fn expect_failed(message: &str) -> ! {
372 panic!("{}", message)
373}
374