9
9
//! * relative time to now, e.g. "+1 hour"
10
10
//!
11
11
use regex:: Error as RegexError ;
12
+ use regex:: Regex ;
12
13
use std:: error:: Error ;
13
14
use std:: fmt:: { self , Display } ;
14
15
@@ -75,6 +76,7 @@ mod format {
75
76
pub const YYYYMMDDHHMMS_T_SEP : & str = "%Y-%m-%dT%H:%M:%S" ;
76
77
pub const UTC_OFFSET : & str = "UTC%#z" ;
77
78
pub const ZULU_OFFSET : & str = "Z%#z" ;
79
+ pub const NAKED_OFFSET : & str = "%#z" ;
78
80
}
79
81
80
82
/// Parses a time string and returns a `DateTime` representing the
@@ -219,8 +221,21 @@ pub fn parse_datetime_at_date<S: AsRef<str> + Clone>(
219
221
// offsets, so instead we replicate parse_date behaviour by getting
220
222
// the current date with local, and create a date time string at midnight,
221
223
// before trying offset suffixes
222
- let ts = format ! ( "{}" , date. format( "%Y%m%d" ) ) + "0000" + s. as_ref ( ) ;
223
- for fmt in [ format:: UTC_OFFSET , format:: ZULU_OFFSET ] {
224
+ //
225
+ // HACK: if the string ends with a single digit preceded by a + or -
226
+ // sign, then insert a 0 between the sign and the digit to make it
227
+ // possible for `chrono` to parse it.
228
+ let pattern = Regex :: new ( r"([\+-])(\d)$" ) . unwrap ( ) ;
229
+ let ts = format ! (
230
+ "{}0000{}" ,
231
+ date. format( "%Y%m%d" ) ,
232
+ pattern. replace( s. as_ref( ) , "${1}0${2}" )
233
+ ) ;
234
+ for fmt in [
235
+ format:: UTC_OFFSET ,
236
+ format:: ZULU_OFFSET ,
237
+ format:: NAKED_OFFSET ,
238
+ ] {
224
239
let f = format:: YYYYMMDDHHMM . to_owned ( ) + fmt;
225
240
if let Ok ( parsed) = DateTime :: parse_from_str ( & ts, & f) {
226
241
return Ok ( parsed) ;
@@ -356,6 +371,8 @@ mod tests {
356
371
"Z+07:00" ,
357
372
"Z+0700" ,
358
373
"Z+07" ,
374
+ "+07" ,
375
+ "+7" ,
359
376
] ;
360
377
361
378
let expected = format ! ( "{}{}" , Local :: now( ) . format( "%Y%m%d" ) , "0000+0700" ) ;
@@ -377,13 +394,11 @@ mod tests {
377
394
378
395
#[ test]
379
396
fn invalid_offset_format ( ) {
380
- let invalid_offsets = vec ! [ "+0700" , "UTC+2" , "Z-1" , "UTC+01005" ] ;
381
- for offset in invalid_offsets {
382
- assert_eq ! (
383
- parse_datetime( offset) ,
384
- Err ( ParseDateTimeError :: InvalidInput )
385
- ) ;
386
- }
397
+ let offset = "UTC+01005" ;
398
+ assert_eq ! (
399
+ parse_datetime( offset) ,
400
+ Err ( ParseDateTimeError :: InvalidInput )
401
+ ) ;
387
402
}
388
403
}
389
404
0 commit comments