@@ -138,7 +138,7 @@ where
138138
139139// Parse an item
140140pub fn parse_one ( input : & mut & str ) -> PResult < Item > {
141- // eprintln!("--- > parse_one {input}");
141+ eprintln ! ( "--- > parse_one {input}" ) ;
142142 let result = alt ( (
143143 combined:: parse. map ( Item :: DateTime ) ,
144144 date:: parse. map ( Item :: Date ) ,
@@ -151,7 +151,7 @@ pub fn parse_one(input: &mut &str) -> PResult<Item> {
151151 ) )
152152 . parse_next ( input) ?;
153153
154- // eprintln!("--- < parse_one {input} {result:?}");
154+ eprintln ! ( "--- < parse_one {input} {result:?}" ) ;
155155 Ok ( result)
156156}
157157
@@ -169,7 +169,6 @@ fn with_timezone_restore(
169169) -> Option < DateTime < FixedOffset > > {
170170 let offset: FixedOffset = chrono:: FixedOffset :: from ( offset) ;
171171 let copy = at;
172- //eprintln!("with_timezone {at} {offset}");
173172 let x = at
174173 . with_timezone ( & offset)
175174 . with_day ( copy. day ( ) ) ?
@@ -181,14 +180,11 @@ fn with_timezone_restore(
181180 Some ( x)
182181}
183182
184- pub ( crate ) fn at_date (
185- date : Vec < Item > ,
186- mut d : DateTime < FixedOffset > ,
187- ) -> Result < DateTime < FixedOffset > , ParseDateTimeError > {
188- d = d. with_hour ( 0 ) . unwrap_or ( d) ;
189- d = d. with_minute ( 0 ) . unwrap_or ( d) ;
190- d = d. with_second ( 0 ) . unwrap_or ( d) ;
191- d = d. with_nanosecond ( 0 ) . unwrap_or ( d) ;
183+ fn at_date_inner ( date : Vec < Item > , mut d : DateTime < FixedOffset > ) -> Option < DateTime < FixedOffset > > {
184+ d = d. with_hour ( 0 ) . unwrap ( ) ;
185+ d = d. with_minute ( 0 ) . unwrap ( ) ;
186+ d = d. with_second ( 0 ) . unwrap ( ) ;
187+ d = d. with_nanosecond ( 0 ) . unwrap ( ) ;
192188
193189 for item in date {
194190 match item {
@@ -199,13 +195,12 @@ pub(crate) fn at_date(
199195 . with_timezone ( & d. timezone ( ) )
200196 }
201197 Item :: Date ( date:: Date { day, month, year } ) => {
202- d = d. with_day ( day) . unwrap_or ( d) ;
203- d = d. with_month ( month) . unwrap_or ( d) ;
204- d = year
205- // converts i32 to u32 safely
206- . and_then ( |year : u32 | <u32 as TryInto < i32 > >:: try_into ( year) . ok ( ) )
207- . and_then ( |year| d. with_year ( year) )
208- . unwrap_or ( d) ;
198+ d = d. with_day ( day) ?;
199+ d = d. with_month ( month) ?;
200+ if let Some ( year) = year {
201+ let y = year as i32 ;
202+ d = d. with_year ( y) ?
203+ }
209204 }
210205 Item :: DateTime ( combined:: DateTime {
211206 date : date:: Date { day, month, year } ,
@@ -222,16 +217,14 @@ pub(crate) fn at_date(
222217 let offset: FixedOffset = chrono:: FixedOffset :: from ( offset) ;
223218 d = d. with_timezone ( & offset) ;
224219 }
225- d = d. with_day ( day) . unwrap_or ( d) ;
226- d = d. with_month ( month) . unwrap_or ( d) ;
227- d = year
228- // converts i32 to u32 safely
229- . and_then ( |year : u32 | <u32 as TryInto < i32 > >:: try_into ( year) . ok ( ) )
230- . and_then ( |year| d. with_year ( year) )
231- . unwrap_or ( d) ;
232- d = d. with_hour ( hour) . unwrap_or ( d) ;
233- d = d. with_minute ( minute) . unwrap_or ( d) ;
234- d = d. with_second ( second as u32 ) . unwrap_or ( d) ;
220+ d = d. with_day ( day) ?;
221+ d = d. with_month ( month) ?;
222+ d = d. with_hour ( hour) ?;
223+ d = d. with_minute ( minute) ?;
224+ d = d. with_second ( second as u32 ) ?;
225+ if let Some ( year) = year {
226+ d = d. with_year ( year as i32 ) ?
227+ }
235228 }
236229 Item :: Year ( year) => d = d. with_year ( year as i32 ) . unwrap_or ( d) ,
237230 Item :: Time ( time:: Time {
@@ -242,11 +235,11 @@ pub(crate) fn at_date(
242235 } ) => {
243236 if let Some ( offset) = offset {
244237 // timezone overflowed
245- d = with_timezone_restore ( offset, d) . ok_or ( ParseDateTimeError :: InvalidInput ) ?;
238+ d = with_timezone_restore ( offset, d) ?;
246239 }
247- d = d. with_hour ( hour) . unwrap_or ( d ) ;
248- d = d. with_minute ( minute) . unwrap_or ( d ) ;
249- d = d. with_second ( second as u32 ) . unwrap_or ( d ) ;
240+ d = d. with_hour ( hour) ? ;
241+ d = d. with_minute ( minute) ? ;
242+ d = d. with_second ( second as u32 ) ? ;
250243 }
251244 Item :: Weekday ( weekday:: Weekday {
252245 offset : _, // TODO: use the offset
@@ -269,9 +262,14 @@ pub(crate) fn at_date(
269262
270263 d = beginning_of_day
271264 }
272- Item :: Relative ( relative:: Relative :: Years ( x) ) => d = d. with_year ( x) . unwrap_or ( d) ,
265+ Item :: Relative ( relative:: Relative :: Years ( x) ) => {
266+ d = d. with_year ( d. year ( ) + x) ?;
267+ }
273268 Item :: Relative ( relative:: Relative :: Months ( x) ) => {
274- d = d. with_month ( x as u32 ) . unwrap_or ( d)
269+ d += d
270+ . date_naive ( )
271+ . checked_add_months ( chrono:: Months :: new ( x as u32 ) ) ?
272+ . signed_duration_since ( d. date_naive ( ) ) ;
275273 }
276274 Item :: Relative ( relative:: Relative :: Days ( x) ) => d += chrono:: Duration :: days ( x. into ( ) ) ,
277275 Item :: Relative ( relative:: Relative :: Hours ( x) ) => d += chrono:: Duration :: hours ( x. into ( ) ) ,
@@ -283,12 +281,19 @@ pub(crate) fn at_date(
283281 d += chrono:: Duration :: seconds ( x as i64 ) ;
284282 }
285283 Item :: TimeZone ( offset) => {
286- d = with_timezone_restore ( offset, d) . ok_or ( ParseDateTimeError :: InvalidInput ) ?;
284+ d = with_timezone_restore ( offset, d) ?;
287285 }
288286 }
289287 }
290288
291- Ok ( d)
289+ Some ( d)
290+ }
291+
292+ pub ( crate ) fn at_date (
293+ date : Vec < Item > ,
294+ d : DateTime < FixedOffset > ,
295+ ) -> Result < DateTime < FixedOffset > , ParseDateTimeError > {
296+ at_date_inner ( date, d) . ok_or ( ParseDateTimeError :: InvalidInput )
292297}
293298
294299pub ( crate ) fn at_local ( date : Vec < Item > ) -> Result < DateTime < FixedOffset > , ParseDateTimeError > {
0 commit comments