@@ -6,6 +6,8 @@ use core::time::Duration as StdDuration;
6
6
#[ cfg( feature = "formatting" ) ]
7
7
use std:: io;
8
8
9
+ use deranged:: RangedI32 ;
10
+
9
11
use crate :: convert:: * ;
10
12
#[ cfg( feature = "formatting" ) ]
11
13
use crate :: formatting:: Formattable ;
@@ -14,6 +16,8 @@ use crate::parsing::Parsable;
14
16
use crate :: util:: { days_in_year, days_in_year_month, is_leap_year, weeks_in_year} ;
15
17
use crate :: { error, Duration , Month , PrimitiveDateTime , Time , Weekday } ;
16
18
19
+ type Year = RangedI32 < MIN_YEAR , MAX_YEAR > ;
20
+
17
21
/// The minimum valid year.
18
22
pub ( crate ) const MIN_YEAR : i32 = if cfg ! ( feature = "large-dates" ) {
19
23
-999_999
@@ -91,8 +95,20 @@ impl Date {
91
95
[ 0 , 31 , 60 , 91 , 121 , 152 , 182 , 213 , 244 , 274 , 305 , 335 ] ,
92
96
] ;
93
97
94
- ensure_value_in_range ! ( year in MIN_YEAR => MAX_YEAR ) ;
95
- ensure_value_in_range ! ( day conditionally in 1 => days_in_year_month( year, month) ) ;
98
+ ensure_ranged ! ( Year : year) ;
99
+ match day {
100
+ 1 ..=28 => { }
101
+ 29 ..=31 if day <= days_in_year_month ( year, month) => { }
102
+ _ => {
103
+ return Err ( crate :: error:: ComponentRange {
104
+ name : "day" ,
105
+ minimum : 1 ,
106
+ maximum : days_in_year_month ( year, month) as _ ,
107
+ value : day as _ ,
108
+ conditional_range : true ,
109
+ } ) ;
110
+ }
111
+ }
96
112
97
113
Ok ( Self :: __from_ordinal_date_unchecked (
98
114
year,
@@ -114,8 +130,21 @@ impl Date {
114
130
/// assert!(Date::from_ordinal_date(2019, 366).is_err()); // 2019 isn't a leap year.
115
131
/// ```
116
132
pub const fn from_ordinal_date ( year : i32 , ordinal : u16 ) -> Result < Self , error:: ComponentRange > {
117
- ensure_value_in_range ! ( year in MIN_YEAR => MAX_YEAR ) ;
118
- ensure_value_in_range ! ( ordinal conditionally in 1 => days_in_year( year) ) ;
133
+ ensure_ranged ! ( Year : year) ;
134
+ match ordinal {
135
+ 1 ..=365 => { }
136
+ 366 if is_leap_year ( year) => { }
137
+ _ => {
138
+ return Err ( crate :: error:: ComponentRange {
139
+ name : "ordinal" ,
140
+ minimum : 1 ,
141
+ maximum : days_in_year ( year) as _ ,
142
+ value : ordinal as _ ,
143
+ conditional_range : true ,
144
+ } ) ;
145
+ }
146
+ }
147
+
119
148
Ok ( Self :: __from_ordinal_date_unchecked ( year, ordinal) )
120
149
}
121
150
@@ -137,8 +166,20 @@ impl Date {
137
166
week : u8 ,
138
167
weekday : Weekday ,
139
168
) -> Result < Self , error:: ComponentRange > {
140
- ensure_value_in_range ! ( year in MIN_YEAR => MAX_YEAR ) ;
141
- ensure_value_in_range ! ( week conditionally in 1 => weeks_in_year( year) ) ;
169
+ ensure_ranged ! ( Year : year) ;
170
+ match week {
171
+ 1 ..=52 => { }
172
+ 53 if week <= weeks_in_year ( year) => { }
173
+ _ => {
174
+ return Err ( crate :: error:: ComponentRange {
175
+ name : "week" ,
176
+ minimum : 1 ,
177
+ maximum : weeks_in_year ( year) as _ ,
178
+ value : week as _ ,
179
+ conditional_range : true ,
180
+ } ) ;
181
+ }
182
+ }
142
183
143
184
let adj_year = year - 1 ;
144
185
let raw = 365 * adj_year + div_floor ! ( adj_year, 4 ) - div_floor ! ( adj_year, 100 )
@@ -181,9 +222,8 @@ impl Date {
181
222
/// ```
182
223
#[ doc( alias = "from_julian_date" ) ]
183
224
pub const fn from_julian_day ( julian_day : i32 ) -> Result < Self , error:: ComponentRange > {
184
- ensure_value_in_range ! (
185
- julian_day in Self :: MIN . to_julian_day( ) => Self :: MAX . to_julian_day( )
186
- ) ;
225
+ type JulianDay = RangedI32 < { Date :: MIN . to_julian_day ( ) } , { Date :: MAX . to_julian_day ( ) } > ;
226
+ ensure_ranged ! ( JulianDay : julian_day) ;
187
227
Ok ( Self :: from_julian_day_unchecked ( julian_day) )
188
228
}
189
229
@@ -899,7 +939,7 @@ impl Date {
899
939
/// ```
900
940
#[ must_use = "This method does not mutate the original `Date`." ]
901
941
pub const fn replace_year ( self , year : i32 ) -> Result < Self , error:: ComponentRange > {
902
- ensure_value_in_range ! ( year in MIN_YEAR => MAX_YEAR ) ;
942
+ ensure_ranged ! ( Year : year ) ;
903
943
904
944
let ordinal = self . ordinal ( ) ;
905
945
@@ -961,11 +1001,18 @@ impl Date {
961
1001
/// ```
962
1002
#[ must_use = "This method does not mutate the original `Date`." ]
963
1003
pub const fn replace_day ( self , day : u8 ) -> Result < Self , error:: ComponentRange > {
964
- // Days 1-28 are present in every month, so we can skip checking.
965
- if day == 0 || day >= 29 {
966
- ensure_value_in_range ! (
967
- day conditionally in 1 => days_in_year_month( self . year( ) , self . month( ) )
968
- ) ;
1004
+ match day {
1005
+ 1 ..=28 => { }
1006
+ 29 ..=31 if day <= days_in_year_month ( self . year ( ) , self . month ( ) ) => { }
1007
+ _ => {
1008
+ return Err ( crate :: error:: ComponentRange {
1009
+ name : "day" ,
1010
+ minimum : 1 ,
1011
+ maximum : days_in_year_month ( self . year ( ) , self . month ( ) ) as _ ,
1012
+ value : day as _ ,
1013
+ conditional_range : true ,
1014
+ } ) ;
1015
+ }
969
1016
}
970
1017
971
1018
Ok ( Self :: __from_ordinal_date_unchecked (
0 commit comments