@@ -41,7 +41,6 @@ use std::fmt::Display;
41
41
42
42
use chrono:: FixedOffset ;
43
43
use winnow:: {
44
- ascii:: digit1,
45
44
combinator:: { alt, opt, peek, preceded} ,
46
45
error:: { ContextError , ErrMode , StrContext , StrContextValue } ,
47
46
seq,
@@ -178,18 +177,18 @@ pub fn iso(input: &mut &str) -> ModalResult<Time> {
178
177
///
179
178
/// The hours are restricted to 12 or lower in this format
180
179
fn am_pm_time ( input : & mut & str ) ->ModalResult < Time > {
181
- let ( h, m, s, meridiem) =seq ! (
180
+ let ( h, m, s, meridiem) =(
182
181
hour12,
183
182
opt ( preceded ( colon, minute) ) ,
184
183
opt ( preceded ( colon, second) ) ,
185
184
alt ( (
186
185
s ( "am" ) . value ( Meridiem :: Am ) ,
187
186
s ( "a.m." ) . value ( Meridiem :: Am ) ,
188
187
s ( "pm" ) . value ( Meridiem :: Pm ) ,
189
- s( "p.m." ) . value( Meridiem :: Pm )
188
+ s ( "p.m." ) . value ( Meridiem :: Pm ) ,
190
189
) ) ,
191
190
)
192
- . parse_next ( input) ?;
191
+ . parse_next ( input) ?;
193
192
194
193
if h ==0 {
195
194
let mut ctx_err =ContextError :: new ( ) ;
@@ -288,14 +287,7 @@ fn timezone_num(input: &mut &str) -> ModalResult<Offset> {
288
287
/// Parse a timezone offset with a colon separating hours and minutes
289
288
fn timezone_colon ( input : & mut & str ) ->ModalResult < ( u32 , u32 ) > {
290
289
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( ) ) ,
299
291
_: colon,
300
292
s( take_while( 1 ..=2 , AsChar :: is_dec_digit) ) . try_map( |x: & str | x. parse( ) ) ,
301
293
)
@@ -304,26 +296,21 @@ fn timezone_colon(input: &mut &str) -> ModalResult<(u32, u32)> {
304
296
305
297
/// Parse a timezone offset without colon
306
298
fn 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 ( ) {
322
309
0 =>( 0 , 0 ) ,
323
- 1 |2 =>( x . parse ( ) . ok ( ) ?, 0 ) ,
310
+ 1 |2 =>( s . parse ( ) . ok ( ) ?, 0 ) ,
324
311
// 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 ( ) ?) ,
327
314
_ =>return None ,
328
315
} )
329
316
} )
@@ -852,6 +839,8 @@ mod tests {
852
839
853
840
assert_eq ! ( "(0, 0)" , aux( & mut "0000" ) ) ;
854
841
assert_eq ! ( "(12, 34)" , aux( & mut "1234" ) ) ;
842
+ assert_eq ! ( "(12, 34)" , aux( & mut "00001234" ) ) ;
843
+ assert ! ( timezone_colonless( & mut "12345" ) . is_err( ) ) ;
855
844
}
856
845
857
846
#[ test]