@@ -252,7 +252,7 @@ pub(crate) mod function {
252
252
///
253
253
/// The goal is to only accept inputs that _unambiguously_ look like
254
254
/// git's raw date format.
255
- pub fn parse_raw ( input : & str ) -> Option < Time > {
255
+ fn parse_raw ( input : & str ) -> Option < Time > {
256
256
let mut split = input. split_whitespace ( ) ;
257
257
let seconds = split. next ( ) ?. parse :: < SecondsSinceUnixEpoch > ( ) . ok ( ) ?;
258
258
let offset_str = split. next ( ) ?;
@@ -279,7 +279,7 @@ pub(crate) mod function {
279
279
return None ;
280
280
}
281
281
let offset: i32 = sign * ( ( hours as i32 ) * 3600 + ( minutes as i32 ) * 60 ) ;
282
- Some ( Time { seconds, offset } )
282
+ Time { seconds, offset } . into ( )
283
283
}
284
284
285
285
/// This is just like `Zoned::strptime`, but it allows parsing datetimes
@@ -298,6 +298,75 @@ pub(crate) mod function {
298
298
static P : rfc2822:: DateTimeParser = rfc2822:: DateTimeParser :: new ( ) . relaxed_weekday ( true ) ;
299
299
P . parse_zoned ( input)
300
300
}
301
+
302
+ #[ cfg( test) ]
303
+ mod tests {
304
+ use super :: * ;
305
+
306
+ #[ test]
307
+ fn parse_raw_valid ( ) {
308
+ // These examples show how it's more loose than it has to be,
309
+ // merely as a side effect of the implementation.
310
+ for ( valid, expected_seconds, expected_offset) in [
311
+ ( "12345 +0000" , 12345 , 0 ) ,
312
+ ( "-1234567 +0000" , -1234567 , 0 ) ,
313
+ ( "+1234567 -000000" , 1234567 , 0 ) ,
314
+ ( " +0 -000000 " , 0 , 0 ) ,
315
+ ( "\t -0\t -0000\t " , 0 , 0 ) ,
316
+ ( "\n -0\r \n -0000\n " , 0 , 0 ) ,
317
+ ] {
318
+ assert_eq ! (
319
+ parse_raw( valid) ,
320
+ Some ( Time {
321
+ seconds: expected_seconds,
322
+ offset: expected_offset
323
+ } ) ,
324
+ "should succeed: '{valid}'"
325
+ ) ;
326
+ }
327
+ }
328
+
329
+ #[ test]
330
+ fn parse_raw_invalid ( ) {
331
+ for ( bad_date_str, message) in [
332
+ ( "123456 !0600" , "invalid sign - must be + or -" ) ,
333
+ ( "123456 0600" , "missing offset sign" ) ,
334
+ ( "123456 +060" , "positive offset too short" ) ,
335
+ ( "123456 -060" , "negative offset too short" ) ,
336
+ ( "123456 +06000" , "not enough offset seconds" ) ,
337
+ ( "123456 --060" , "duplicate offset sign with correct offset length" ) ,
338
+ ( "123456 -+060" , "multiple offset signs with correct offset length" ) ,
339
+ ( "123456 --0600" , "multiple offset signs, but incorrect offset length" ) ,
340
+ ( "123456 +-06000" , "multiple offset signs with correct offset length" ) ,
341
+ ( "123456 +-0600" , "multiple offset signs with incorrect offset length" ) ,
342
+ ( "123456 +-060" , "multiple offset signs with correct offset length" ) ,
343
+ ( "123456 +10030" , "invalid offset length with one 'second' field" ) ,
344
+ ( "123456 06000" , "invalid offset length, missing sign" ) ,
345
+ ( "123456 +0600 extra" , "extra field past offset" ) ,
346
+ ( "123456 +0600 2005" , "extra field past offset that looks like year" ) ,
347
+ ( "123456+0600" , "missing space between unix timestamp and offset" ) ,
348
+ (
349
+ "123456 + 600" ,
350
+ "extra spaces between sign and offset (which also is too short)" ,
351
+ ) ,
352
+ ( "123456 -1500" , "negative offset hours out of bounds" ) ,
353
+ ( "123456 +1500" , "positive offset hours out of bounds" ) ,
354
+ ( "123456 +6600" , "positive offset hours out of bounds" ) ,
355
+ ( "123456 +0660" , "invalid offset minutes" ) ,
356
+ ( "123456 +060010" , "positive offset seconds is allowed but only if zero" ) ,
357
+ ( "123456 -060010" , "negative offset seconds is allowed but only if zero" ) ,
358
+ ( "123456 +0075" , "positive offset minutes invalid" ) ,
359
+ ( "++123456 +0000" , "duplicate timestamp sign" ) ,
360
+ ( "--123456 +0000" , "duplicate timestamp sign" ) ,
361
+ ( "1234567 -+1+1+0" , "unsigned offset parsing rejects '+'" ) ,
362
+ ] {
363
+ assert ! (
364
+ parse_raw( bad_date_str) . is_none( ) ,
365
+ "should fail: '{bad_date_str}': {message}"
366
+ ) ;
367
+ }
368
+ }
369
+ }
301
370
}
302
371
303
372
mod relative {
0 commit comments