@@ -140,6 +140,8 @@ pub struct Parsed {
140140 #[ doc( hidden) ]
141141 pub isoyear_mod_100 : Option < i32 > ,
142142 #[ doc( hidden) ]
143+ pub quarter : Option < u32 > ,
144+ #[ doc( hidden) ]
143145 pub month : Option < u32 > ,
144146 #[ doc( hidden) ]
145147 pub week_from_sun : Option < u32 > ,
@@ -304,6 +306,23 @@ impl Parsed {
304306 set_if_consistent ( & mut self . isoyear_mod_100 , value as i32 )
305307 }
306308
309+ /// Set the [`quarter`](Parsed::quarter) field to the given value.
310+ ///
311+ /// Quarter 1 starts in January.
312+ ///
313+ /// # Errors
314+ ///
315+ /// Returns `OUT_OF_RANGE` if `value` is not in the range 1-4.
316+ ///
317+ /// Returns `IMPOSSIBLE` if this field was already set to a different value.
318+ #[ inline]
319+ pub fn set_quarter ( & mut self , value : i64 ) -> ParseResult < ( ) > {
320+ if !( 1 ..=4 ) . contains ( & value) {
321+ return Err ( OUT_OF_RANGE ) ;
322+ }
323+ set_if_consistent ( & mut self . quarter , value as u32 )
324+ }
325+
307326 /// Set the [`month`](Parsed::month) field to the given value.
308327 ///
309328 /// # Errors
@@ -698,7 +717,13 @@ impl Parsed {
698717 ( _, _, _) => return Err ( NOT_ENOUGH ) ,
699718 } ;
700719
701- if verified { Ok ( parsed_date) } else { Err ( IMPOSSIBLE ) }
720+ // verify the quarter if we have a good parsed date so far
721+ let verify_quarter = |date : NaiveDate | {
722+ let quarter = date. quarter ( ) ;
723+ self . quarter . unwrap_or ( quarter) == quarter
724+ } ;
725+
726+ if verified && verify_quarter ( parsed_date) { Ok ( parsed_date) } else { Err ( IMPOSSIBLE ) }
702727 }
703728
704729 /// Returns a parsed naive time out of given fields.
@@ -1013,6 +1038,14 @@ impl Parsed {
10131038 self . isoyear_mod_100
10141039 }
10151040
1041+ /// Get the `quarter` field if set.
1042+ ///
1043+ /// See also [`set_quarter()`](Parsed::set_quarter).
1044+ #[ inline]
1045+ pub fn quarter ( & self ) -> Option < u32 > {
1046+ self . quarter
1047+ }
1048+
10161049 /// Get the `month` field if set.
10171050 ///
10181051 /// See also [`set_month()`](Parsed::set_month).
@@ -1267,6 +1300,11 @@ mod tests {
12671300 assert ! ( Parsed :: new( ) . set_isoyear_mod_100( 99 ) . is_ok( ) ) ;
12681301 assert_eq ! ( Parsed :: new( ) . set_isoyear_mod_100( 100 ) , Err ( OUT_OF_RANGE ) ) ;
12691302
1303+ assert_eq ! ( Parsed :: new( ) . set_quarter( 0 ) , Err ( OUT_OF_RANGE ) ) ;
1304+ assert ! ( Parsed :: new( ) . set_quarter( 1 ) . is_ok( ) ) ;
1305+ assert ! ( Parsed :: new( ) . set_quarter( 4 ) . is_ok( ) ) ;
1306+ assert_eq ! ( Parsed :: new( ) . set_quarter( 5 ) , Err ( OUT_OF_RANGE ) ) ;
1307+
12701308 assert_eq ! ( Parsed :: new( ) . set_month( 0 ) , Err ( OUT_OF_RANGE ) ) ;
12711309 assert ! ( Parsed :: new( ) . set_month( 1 ) . is_ok( ) ) ;
12721310 assert ! ( Parsed :: new( ) . set_month( 12 ) . is_ok( ) ) ;
@@ -1425,6 +1463,17 @@ mod tests {
14251463 assert_eq ! ( parse!( year: -1 , year_div_100: 0 , month: 1 , day: 1 ) , Err ( IMPOSSIBLE ) ) ;
14261464 assert_eq ! ( parse!( year: -1 , year_mod_100: 99 , month: 1 , day: 1 ) , Err ( IMPOSSIBLE ) ) ;
14271465
1466+ // quarters
1467+ assert_eq ! ( parse!( year: 2000 , quarter: 1 ) , Err ( NOT_ENOUGH ) ) ;
1468+ assert_eq ! ( parse!( year: 2000 , quarter: 1 , month: 1 , day: 1 ) , ymd( 2000 , 1 , 1 ) ) ;
1469+ assert_eq ! ( parse!( year: 2000 , quarter: 2 , month: 4 , day: 1 ) , ymd( 2000 , 4 , 1 ) ) ;
1470+ assert_eq ! ( parse!( year: 2000 , quarter: 3 , month: 7 , day: 1 ) , ymd( 2000 , 7 , 1 ) ) ;
1471+ assert_eq ! ( parse!( year: 2000 , quarter: 4 , month: 10 , day: 1 ) , ymd( 2000 , 10 , 1 ) ) ;
1472+
1473+ // quarter: conflicting inputs
1474+ assert_eq ! ( parse!( year: 2000 , quarter: 2 , month: 3 , day: 31 ) , Err ( IMPOSSIBLE ) ) ;
1475+ assert_eq ! ( parse!( year: 2000 , quarter: 4 , month: 3 , day: 31 ) , Err ( IMPOSSIBLE ) ) ;
1476+
14281477 // weekdates
14291478 assert_eq ! ( parse!( year: 2000 , week_from_mon: 0 ) , Err ( NOT_ENOUGH ) ) ;
14301479 assert_eq ! ( parse!( year: 2000 , week_from_sun: 0 ) , Err ( NOT_ENOUGH ) ) ;
0 commit comments