1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
//! Utility functions.
pub use time_core::util::{days_in_year, is_leap_year, weeks_in_year};
use crate::Month;
/// Whether to adjust the date, and in which direction. Useful when implementing arithmetic.
pub(crate) enum DateAdjustment {
    /// The previous day should be used.
    Previous,
    /// The next day should be used.
    Next,
    /// The date should be used as-is.
    None,
}
/// Get the number of days in the month of a given year.
///
/// ```rust
/// # use time::{Month, util};
/// assert_eq!(util::days_in_year_month(2020, Month::February), 29);
/// ```
pub const fn days_in_year_month(year: i32, month: Month) -> u8 {
    use Month::*;
    match month {
        January | March | May | July | August | October | December => 31,
        April | June | September | November => 30,
        February if is_leap_year(year) => 29,
        February => 28,
    }
}
#[cfg(feature = "local-offset")]
/// Utility functions relating to the local UTC offset.
pub mod local_offset {
    use core::sync::atomic::{AtomicBool, Ordering};
    /// Whether obtaining the local UTC offset is required to be sound.
    static LOCAL_OFFSET_IS_SOUND: AtomicBool = AtomicBool::new(true);
    /// The soundness of obtaining the local UTC offset.
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub enum Soundness {
        /// Obtaining the local UTC offset is required to be sound. Undefined behavior will never
        /// occur. This is the default.
        Sound,
        /// Obtaining the local UTC offset is allowed to invoke undefined behavior. Setting this
        /// value is strongly discouraged. To do so, you must comply with the safety requirements
        /// of [`time::local_offset::set_soundness`](set_soundness).
        Unsound,
    }
    /// Set whether obtaining the local UTC offset is allowed to invoke undefined behavior.
    ///
    /// # Safety
    ///
    /// If this method is called with [`Soundness::Sound`], the call is always sound. If this method
    /// is called with [`Soundness::Unsound`], the following conditions apply.
    ///
    /// - If the operating system is not Unix-like, the call is sound.
    /// - If the process is single-threaded, the call is sound.
    /// - If the process is multi-threaded, no other thread may mutate the environment in any way at
    ///   the same time a call to a method that obtains the local UTC offset. This includes adding,
    ///   removing, or modifying an environment variable.
    ///
    /// Note that you must not only verify this safety condition for your code, but for **all** code
    /// that will be included in the final binary. Notably, it applies to both direct and transitive
    /// dependencies and to both Rust and non-Rust code. For this reason it is not possible to
    /// soundly pass [`Soundness::Unsound`] to this method if you are writing a library that may
    /// used by others.
    ///
    /// The following methods currently obtain the local UTC offset:
    ///
    /// - [`OffsetDateTime::now_local`](crate::OffsetDateTime::now_local)
    /// - [`UtcOffset::local_offset_at`](crate::UtcOffset::local_offset_at)
    /// - [`UtcOffset::current_local_offset`](crate::UtcOffset::current_local_offset)
    pub unsafe fn set_soundness(soundness: Soundness) {
        LOCAL_OFFSET_IS_SOUND.store(soundness == Soundness::Sound, Ordering::SeqCst);
    }
    /// Obtains the soundness of obtaining the local UTC offset. If it is [`Soundness::Unsound`],
    /// it is allowed to invoke undefined behavior when obtaining the local UTC offset.
    pub fn get_soundness() -> Soundness {
        match LOCAL_OFFSET_IS_SOUND.load(Ordering::SeqCst) {
            false => Soundness::Unsound,
            true => Soundness::Sound,
        }
    }
}