1
- use nom:: combinator:: map;
1
+ use nom:: branch:: alt;
2
+ use nom:: character:: complete:: { char, digit1} ;
3
+ use nom:: combinator:: all_consuming;
4
+ use nom:: multi:: fold_many0;
5
+ use nom:: sequence:: preceded;
6
+ use nom:: sequence:: tuple;
2
7
use nom:: { self , IResult } ;
3
8
4
9
pub ( crate ) fn parse_timestamp ( s : & str ) -> Option < i64 > {
5
10
let s = s. trim ( ) . to_lowercase ( ) ;
6
11
let s = s. as_str ( ) ;
7
12
8
- let res: IResult < & str , ( & str , char , & str ) > =
9
- nom:: combinator:: all_consuming ( nom:: sequence:: tuple ( (
10
- nom:: bytes:: complete:: tag ( "@" ) ,
11
- map (
12
- nom:: bytes:: complete:: take_while ( |c : char | c == '+' || c == '-' ) ,
13
- |st : & str | st. chars ( ) . last ( ) . unwrap_or ( '+' ) ,
13
+ let res: IResult < & str , ( char , & str ) > = all_consuming ( preceded (
14
+ char ( '@' ) ,
15
+ tuple ( (
16
+ // Note: gnu date allows multiple + and - and only considers the last one
17
+ fold_many0 (
18
+ // parse either + or -
19
+ alt ( ( char ( '+' ) , char ( '-' ) ) ) ,
20
+ // start with a +
21
+ || '+' ,
22
+ // whatever we get (+ or -), update the accumulator to that value
23
+ |_, c| c,
14
24
) ,
15
- nom:: character:: complete:: digit1,
16
- ) ) ) ( s) ;
25
+ digit1,
26
+ ) ) ,
27
+ ) ) ( s) ;
17
28
18
- if let Ok ( ( _, ( _, sign, number_str) ) ) = res {
19
- let number = format ! ( "{}{}" , sign, number_str) . parse ( ) ;
29
+ let ( _, ( sign, number_str) ) = res. ok ( ) ?;
20
30
21
- return match number {
22
- Err ( _ ) => None ,
23
- Ok ( val ) => Some ( val ) ,
24
- } ;
31
+ let mut number = number_str . parse :: < i64 > ( ) . ok ( ) ? ;
32
+
33
+ if sign == '-' {
34
+ number *= - 1 ;
25
35
}
26
36
27
- None
37
+ Some ( number )
28
38
}
29
39
30
40
#[ cfg( test) ]
@@ -41,7 +51,9 @@ mod tests {
41
51
assert_eq ! ( parse_timestamp( "@+4" ) , Some ( 4 ) ) ;
42
52
assert_eq ! ( parse_timestamp( "@0" ) , Some ( 0 ) ) ;
43
53
44
- // gnu date accepts this
54
+ // gnu date acceppts numbers signs and uses the last sign
55
+ assert_eq ! ( parse_timestamp( "@---+12" ) , Some ( 12 ) ) ;
56
+ assert_eq ! ( parse_timestamp( "@+++-12" ) , Some ( -12 ) ) ;
45
57
assert_eq ! ( parse_timestamp( "@+----+12" ) , Some ( 12 ) ) ;
46
58
assert_eq ! ( parse_timestamp( "@++++-123" ) , Some ( -123 ) ) ;
47
59
}
@@ -50,5 +62,6 @@ mod tests {
50
62
fn test_invalid_timestamp ( ) {
51
63
assert_eq ! ( parse_timestamp( "@" ) , None ) ;
52
64
assert_eq ! ( parse_timestamp( "@+--+" ) , None ) ;
65
+ assert_eq ! ( parse_timestamp( "@+1ab2" ) , None ) ;
53
66
}
54
67
}
0 commit comments