1 //! Utility functions.
2 
3 use crate::{format::try_parse_fmt_string, internals};
4 #[cfg(not(feature = "std"))]
5 use alloc::string::String;
6 use const_fn::const_fn;
7 
8 /// Checks if a user-provided formatting string is valid. If it isn't, a
9 /// description of the error is returned.
validate_format_string(s: impl AsRef<str>) -> Result<(), String>10 pub fn validate_format_string(s: impl AsRef<str>) -> Result<(), String> {
11     try_parse_fmt_string(s.as_ref()).map(|_| ())
12 }
13 
14 /// The number of days in a month in both common and leap years.
15 const DAYS_IN_MONTH_COMMON_LEAP: [[u16; 12]; 2] = [
16     [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
17     [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
18 ];
19 
20 /// Get the number of days in the month of a given year.
days_in_year_month(year: i32, month: u8) -> u821 pub(crate) const fn days_in_year_month(year: i32, month: u8) -> u8 {
22     DAYS_IN_MONTH_COMMON_LEAP[is_leap_year(year) as usize][month as usize - 1] as u8
23 }
24 
25 /// Returns if the provided year is a leap year in the proleptic Gregorian
26 /// calendar. Uses [astronomical year numbering](https://en.wikipedia.org/wiki/Astronomical_year_numbering).
27 ///
28 /// ```rust
29 /// # use time::is_leap_year;
30 /// assert!(!is_leap_year(1900));
31 /// assert!(is_leap_year(2000));
32 /// assert!(is_leap_year(2004));
33 /// assert!(!is_leap_year(2005));
34 /// assert!(!is_leap_year(2100));
35 /// ```
is_leap_year(year: i32) -> bool36 pub const fn is_leap_year(year: i32) -> bool {
37     (year % 4 == 0) & ((year % 100 != 0) | (year % 400 == 0))
38 }
39 
40 /// Get the number of calendar days in a given year.
41 ///
42 /// The returned value will always be either 365 or 366.
43 ///
44 /// ```rust
45 /// # use time::days_in_year;
46 /// assert_eq!(days_in_year(1900), 365);
47 /// assert_eq!(days_in_year(2000), 366);
48 /// assert_eq!(days_in_year(2004), 366);
49 /// assert_eq!(days_in_year(2005), 365);
50 /// assert_eq!(days_in_year(2100), 365);
51 /// ```
days_in_year(year: i32) -> u1652 pub const fn days_in_year(year: i32) -> u16 {
53     365 + is_leap_year(year) as u16
54 }
55 
56 /// Get the number of weeks in the ISO year.
57 ///
58 /// The returned value will always be either 52 or 53.
59 ///
60 /// ```rust
61 /// # use time::weeks_in_year;
62 /// assert_eq!(weeks_in_year(2019), 52);
63 /// assert_eq!(weeks_in_year(2020), 53);
64 /// ```
65 ///
66 /// This function is `const fn` when using rustc >= 1.46.
67 #[const_fn("1.46")]
weeks_in_year(year: i32) -> u868 pub const fn weeks_in_year(year: i32) -> u8 {
69     let weekday = internals::Date::from_yo_unchecked(year, 1).iso_weekday_number();
70 
71     if weekday == 4 || weekday == 3 && is_leap_year(year) {
72         53
73     } else {
74         52
75     }
76 }
77