Skip to content

Commit 240abf7

Browse files
authored
Merge pull request #101 from jfinkels/single-digit-tz-offset
Parse single digit timezone offsets
2 parents 00dc90d + 34f226f commit 240abf7

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

src/lib.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! * relative time to now, e.g. "+1 hour"
1010
//!
1111
use regex::Error as RegexError;
12+
use regex::Regex;
1213
use std::error::Error;
1314
use std::fmt::{self, Display};
1415

@@ -75,6 +76,7 @@ mod format {
7576
pub const YYYYMMDDHHMMS_T_SEP: &str = "%Y-%m-%dT%H:%M:%S";
7677
pub const UTC_OFFSET: &str = "UTC%#z";
7778
pub const ZULU_OFFSET: &str = "Z%#z";
79+
pub const NAKED_OFFSET: &str = "%#z";
7880
}
7981

8082
/// Parses a time string and returns a `DateTime` representing the
@@ -219,8 +221,21 @@ pub fn parse_datetime_at_date<S: AsRef<str> + Clone>(
219221
// offsets, so instead we replicate parse_date behaviour by getting
220222
// the current date with local, and create a date time string at midnight,
221223
// 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+
] {
224239
let f = format::YYYYMMDDHHMM.to_owned() + fmt;
225240
if let Ok(parsed) = DateTime::parse_from_str(&ts, &f) {
226241
return Ok(parsed);
@@ -356,6 +371,8 @@ mod tests {
356371
"Z+07:00",
357372
"Z+0700",
358373
"Z+07",
374+
"+07",
375+
"+7",
359376
];
360377

361378
let expected = format!("{}{}", Local::now().format("%Y%m%d"), "0000+0700");
@@ -377,13 +394,11 @@ mod tests {
377394

378395
#[test]
379396
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+
);
387402
}
388403
}
389404

0 commit comments

Comments
 (0)