@@ -41,7 +41,6 @@ use std::fmt::Display;
4141
4242use chrono:: FixedOffset ;
4343use winnow:: {
44- ascii:: digit1,
4544 combinator:: { alt, opt, peek, preceded} ,
4645 error:: { ContextError , ErrMode , StrContext , StrContextValue } ,
4746 seq,
@@ -178,18 +177,18 @@ pub fn iso(input: &mut &str) -> ModalResult<Time> {
178177///
179178/// The hours are restricted to 12 or lower in this format
180179fn am_pm_time ( input : & mut & str ) -> ModalResult < Time > {
181- let ( h, m, s, meridiem) = seq ! (
180+ let ( h, m, s, meridiem) = (
182181 hour12,
183182 opt ( preceded ( colon, minute) ) ,
184183 opt ( preceded ( colon, second) ) ,
185184 alt ( (
186185 s ( "am" ) . value ( Meridiem :: Am ) ,
187186 s ( "a.m." ) . value ( Meridiem :: Am ) ,
188187 s ( "pm" ) . value ( Meridiem :: Pm ) ,
189- s( "p.m." ) . value( Meridiem :: Pm )
188+ s ( "p.m." ) . value ( Meridiem :: Pm ) ,
190189 ) ) ,
191190 )
192- . parse_next ( input) ?;
191+ . parse_next ( input) ?;
193192
194193 if h == 0 {
195194 let mut ctx_err = ContextError :: new ( ) ;
@@ -288,14 +287,7 @@ fn timezone_num(input: &mut &str) -> ModalResult<Offset> {
288287/// Parse a timezone offset with a colon separating hours and minutes
289288fn timezone_colon ( input : & mut & str ) -> ModalResult < ( u32 , u32 ) > {
290289 seq ! (
291- s( take_while( 1 ..=2 , AsChar :: is_dec_digit) ) . try_map( |x: & str | {
292- // parse will fail on empty input
293- if x. is_empty( ) {
294- Ok ( 0 )
295- } else {
296- x. parse( )
297- }
298- } ) ,
290+ s( take_while( 1 ..=2 , AsChar :: is_dec_digit) ) . try_map( |x: & str | x. parse( ) ) ,
299291 _: colon,
300292 s( take_while( 1 ..=2 , AsChar :: is_dec_digit) ) . try_map( |x: & str | x. parse( ) ) ,
301293 )
@@ -304,26 +296,21 @@ fn timezone_colon(input: &mut &str) -> ModalResult<(u32, u32)> {
304296
305297/// Parse a timezone offset without colon
306298fn timezone_colonless ( input : & mut & str ) -> ModalResult < ( u32 , u32 ) > {
307- if let Ok ( x) = peek ( s ( digit1 :: < & str , ContextError > ) ) . parse_next ( input) {
308- if x. len ( ) > 4 {
309- let mut ctx_err = ContextError :: new ( ) ;
310- ctx_err. push ( StrContext :: Expected ( StrContextValue :: Description (
311- "timezone offset cannot be more than 4 digits" ,
312- ) ) ) ;
313- return Err ( ErrMode :: Cut ( ctx_err) ) ;
314- }
315- }
316-
317- // TODO: GNU date supports number strings with leading zeroes, e.g.,
318- // `UTC+000001100` is valid.
319- s ( take_while ( 0 ..=4 , AsChar :: is_dec_digit) )
320- . verify_map ( |x : & str | {
321- Some ( match x. len ( ) {
299+ s ( take_while ( 0 .., AsChar :: is_dec_digit) )
300+ . verify_map ( |s : & str | {
301+ // GNU date supports number strings with leading zeroes, e.g.,
302+ // `UTC+000001100` is valid.
303+ let s = if s. len ( ) > 4 {
304+ s. trim_start_matches ( '0' )
305+ } else {
306+ s
307+ } ;
308+ Some ( match s. len ( ) {
322309 0 => ( 0 , 0 ) ,
323- 1 | 2 => ( x . parse ( ) . ok ( ) ?, 0 ) ,
310+ 1 | 2 => ( s . parse ( ) . ok ( ) ?, 0 ) ,
324311 // The minutes are the last two characters here, for some reason.
325- 3 => ( x [ ..1 ] . parse ( ) . ok ( ) ?, x [ 1 ..] . parse ( ) . ok ( ) ?) ,
326- 4 => ( x [ ..2 ] . parse ( ) . ok ( ) ?, x [ 2 ..] . parse ( ) . ok ( ) ?) ,
312+ 3 => ( s [ ..1 ] . parse ( ) . ok ( ) ?, s [ 1 ..] . parse ( ) . ok ( ) ?) ,
313+ 4 => ( s [ ..2 ] . parse ( ) . ok ( ) ?, s [ 2 ..] . parse ( ) . ok ( ) ?) ,
327314 _ => return None ,
328315 } )
329316 } )
@@ -852,6 +839,8 @@ mod tests {
852839
853840 assert_eq ! ( "(0, 0)" , aux( & mut "0000" ) ) ;
854841 assert_eq ! ( "(12, 34)" , aux( & mut "1234" ) ) ;
842+ assert_eq ! ( "(12, 34)" , aux( & mut "00001234" ) ) ;
843+ assert ! ( timezone_colonless( & mut "12345" ) . is_err( ) ) ;
855844 }
856845
857846 #[ test]
0 commit comments