summaryrefslogtreecommitdiffstats
path: root/sqv/src/sqv.rs
diff options
context:
space:
mode:
Diffstat (limited to 'sqv/src/sqv.rs')
-rw-r--r--sqv/src/sqv.rs78
1 files changed, 73 insertions, 5 deletions
diff --git a/sqv/src/sqv.rs b/sqv/src/sqv.rs
index 373bbd38..5543efb0 100644
--- a/sqv/src/sqv.rs
+++ b/sqv/src/sqv.rs
@@ -3,6 +3,7 @@
/// See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=872271 for
/// the motivation.
+use chrono::{DateTime, offset::Utc};
extern crate clap;
extern crate failure;
use failure::ResultExt;
@@ -50,11 +51,9 @@ fn real_main() -> Result<(), failure::Error> {
exit(2);
}
- use chrono::{DateTime, offset::Utc, NaiveDate};
let not_before: Option<std::time::SystemTime> =
if let Some(t) = matches.value_of("not-before") {
- Some(NaiveDate::parse_from_str(t, "%Y-%m-%d")
- .map(|n| DateTime::<Utc>::from_utc(n.and_hms(0, 0, 0), Utc))
+ Some(parse_iso8601(t, chrono::NaiveTime::from_hms(0, 0, 0))
.context(format!("Bad value passed to --not-before: {:?}", t))?
.into())
} else {
@@ -62,8 +61,7 @@ fn real_main() -> Result<(), failure::Error> {
};
let not_after: std::time::SystemTime =
if let Some(t) = matches.value_of("not-after") {
- Some(NaiveDate::parse_from_str(t, "%Y-%m-%d")
- .map(|n| DateTime::<Utc>::from_utc(n.and_hms(23, 59, 59), Utc))
+ Some(parse_iso8601(t, chrono::NaiveTime::from_hms(23, 59, 59))
.context(format!("Bad value passed to --not-after: {:?}", t))?
.into())
} else {
@@ -376,3 +374,73 @@ fn main() {
exit(2);
}
}
+
+/// Parses the given string depicting a ISO 8601 timestamp.
+fn parse_iso8601(s: &str, pad_date_with: chrono::NaiveTime)
+ -> failure::Fallible<DateTime<Utc>>
+{
+ for f in &[
+ "%Y-%m-%dT%H:%M:%S%#z",
+ "%Y-%m-%dT%H:%M:%S",
+ "%Y-%m-%dT%H:%M%#z",
+ "%Y-%m-%dT%H:%M",
+ "%Y-%m-%dT%H%#z",
+ "%Y-%m-%dT%H",
+ "%Y%m%dT%H%M%S%#z",
+ "%Y%m%dT%H%M%S",
+ "%Y%m%dT%H%M%#z",
+ "%Y%m%dT%H%M",
+ "%Y%m%dT%H%#z",
+ "%Y%m%dT%H",
+ ] {
+ if f.ends_with("%#z") {
+ if let Ok(d) = DateTime::parse_from_str(s, *f) {
+ return Ok(d.into());
+ }
+ } else {
+ if let Ok(d) = chrono::NaiveDateTime::parse_from_str(s, *f) {
+ return Ok(DateTime::from_utc(d, Utc));
+ }
+ }
+ }
+ for f in &[
+ "%Y-%m-%d",
+ "%Y-%m",
+ "%Y-%j",
+ "%Y%m%d",
+ "%Y%m",
+ "%Y%j",
+ "%Y",
+ ] {
+ if let Ok(d) = chrono::NaiveDate::parse_from_str(s, *f) {
+ return Ok(DateTime::from_utc(d.and_time(pad_date_with), Utc));
+ }
+ }
+ Err(failure::format_err!("Malformed ISO8601 timestamp: {}", s))
+}
+
+#[test]
+fn test_parse_iso8601() {
+ let z = chrono::NaiveTime::from_hms(0, 0, 0);
+ parse_iso8601("2017-03-04T13:25:35Z", z).unwrap();
+ parse_iso8601("2017-03-04T13:25:35+08:30", z).unwrap();
+ parse_iso8601("2017-03-04T13:25:35", z).unwrap();
+ parse_iso8601("2017-03-04T13:25Z", z).unwrap();
+ parse_iso8601("2017-03-04T13:25", z).unwrap();
+ // parse_iso8601("2017-03-04T13Z", z).unwrap(); // XXX: chrono doesn't like
+ // parse_iso8601("2017-03-04T13", z).unwrap(); // ditto
+ parse_iso8601("2017-03-04", z).unwrap();
+ // parse_iso8601("2017-03", z).unwrap(); // ditto
+ parse_iso8601("2017-031", z).unwrap();
+ parse_iso8601("20170304T132535Z", z).unwrap();
+ parse_iso8601("20170304T132535+0830", z).unwrap();
+ parse_iso8601("20170304T132535", z).unwrap();
+ parse_iso8601("20170304T1325Z", z).unwrap();
+ parse_iso8601("20170304T1325", z).unwrap();
+ // parse_iso8601("20170304T13Z", z).unwrap(); // ditto
+ // parse_iso8601("20170304T13", z).unwrap(); // ditto
+ parse_iso8601("20170304", z).unwrap();
+ // parse_iso8601("201703", z).unwrap(); // ditto
+ parse_iso8601("2017031", z).unwrap();
+ // parse_iso8601("2017", z).unwrap(); // ditto
+}