1 //! This module and its contents are not subject to stability guarantees and
2 //! should not be relied upon.
3 //!
4 //! These methods either exist to reduce duplication in code elsewhere or are
5 //! public only for usage in macros. The reasoning for a method's existence is
6 //! generally documented alongside the method.
7 //!
8 //! Failure to ensure that parameters to the contained functions are in range
9 //! will likely result in invalid behavior.
10 
11 #![doc(hidden)]
12 #![allow(missing_debug_implementations, missing_copy_implementations)]
13 
14 use crate::{days_in_year, is_leap_year, Weekday};
15 use const_fn::const_fn;
16 
17 pub struct Time;
18 
19 impl Time {
20     /// Create a `Time` from its components.
from_hms_nanos_unchecked( hour: u8, minute: u8, second: u8, nanosecond: u32, ) -> crate::Time21     pub const fn from_hms_nanos_unchecked(
22         hour: u8,
23         minute: u8,
24         second: u8,
25         nanosecond: u32,
26     ) -> crate::Time {
27         crate::Time {
28             hour,
29             minute,
30             second,
31             nanosecond,
32         }
33     }
34 }
35 
36 pub struct Date;
37 
38 impl Date {
39     // macros
from_yo_unchecked(year: i32, ordinal: u16) -> crate::Date40     pub const fn from_yo_unchecked(year: i32, ordinal: u16) -> crate::Date {
41         crate::Date {
42             value: (year << 9) | ordinal as i32,
43         }
44     }
45 
46     // reduce duplication
from_ymd_unchecked(year: i32, month: u8, day: u8) -> crate::Date47     pub(crate) const fn from_ymd_unchecked(year: i32, month: u8, day: u8) -> crate::Date {
48         /// Cumulative days through the beginning of a month in both common and
49         /// leap years.
50         const DAYS_CUMULATIVE_COMMON_LEAP: [[u16; 12]; 2] = [
51             [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
52             [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335],
53         ];
54 
55         Date::from_yo_unchecked(
56             year,
57             DAYS_CUMULATIVE_COMMON_LEAP[is_leap_year(year) as usize][month as usize - 1]
58                 + day as u16,
59         )
60     }
61 
62     // reduce duplication
63     #[const_fn("1.46")]
from_iso_ywd_unchecked( year: i32, week: u8, weekday: Weekday, ) -> crate::Date64     pub(crate) const fn from_iso_ywd_unchecked(
65         year: i32,
66         week: u8,
67         weekday: Weekday,
68     ) -> crate::Date {
69         let (ordinal, overflow) = (week as u16 * 7 + weekday.iso_weekday_number() as u16)
70             .overflowing_sub(jan_weekday(year, 4) as u16 + 4);
71 
72         if overflow || ordinal == 0 {
73             return Self::from_yo_unchecked(year - 1, ordinal.wrapping_add(days_in_year(year - 1)));
74         }
75 
76         let days_in_cur_year = days_in_year(year);
77         if ordinal > days_in_cur_year {
78             Self::from_yo_unchecked(year + 1, ordinal - days_in_cur_year)
79         } else {
80             Self::from_yo_unchecked(year, ordinal)
81         }
82     }
83 }
84 
85 /// Obtain the ISO weekday number of a day in January.
86 #[const_fn("1.46")]
jan_weekday(year: i32, ordinal: i32) -> u887 pub(crate) const fn jan_weekday(year: i32, ordinal: i32) -> u8 {
88     let adj_year = year - 1;
89     let rem = (ordinal + adj_year + adj_year / 4 - adj_year / 100 + adj_year / 400 + 6) % 7;
90     if rem < 0 {
91         (rem + 7) as u8
92     } else {
93         rem as u8
94     }
95 }
96