diff -Nru rust-humantime-1.3.0/benches/datetime_format.rs rust-humantime-2.0.0/benches/datetime_format.rs --- rust-humantime-1.3.0/benches/datetime_format.rs 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/benches/datetime_format.rs 2020-01-19 01:45:10.000000000 +0000 @@ -1,16 +1,14 @@ #![feature(test)] -extern crate chrono; -extern crate humantime; extern crate test; use std::io::Write; use std::time::{Duration, UNIX_EPOCH}; -use humantime::format_rfc3339; +use humantime::format_rfc3339; #[bench] fn rfc3339_humantime_seconds(b: &mut test::Bencher) { - let time = UNIX_EPOCH + Duration::new(1483228799, 0); + let time = UNIX_EPOCH + Duration::new(1_483_228_799, 0); let mut buf = Vec::with_capacity(100); b.iter(|| { buf.truncate(0); @@ -28,11 +26,11 @@ use chrono::format::Pad::*; let time = DateTime::::from_utc( - NaiveDateTime::from_timestamp(1483228799, 0), Utc); + NaiveDateTime::from_timestamp(1_483_228_799, 0), Utc); let mut buf = Vec::with_capacity(100); // formatting code from env_logger - const ITEMS: &'static [Item<'static>] = { + const ITEMS: &[Item<'static>] = { &[ Numeric(Year, Zero), Literal("-"), diff -Nru rust-humantime-1.3.0/benches/datetime_parse.rs rust-humantime-2.0.0/benches/datetime_parse.rs --- rust-humantime-1.3.0/benches/datetime_parse.rs 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/benches/datetime_parse.rs 2020-01-19 01:45:10.000000000 +0000 @@ -1,12 +1,9 @@ #![feature(test)] -extern crate chrono; -extern crate humantime; extern crate test; use chrono::{DateTime}; use humantime::parse_rfc3339; - #[bench] fn rfc3339_humantime_seconds(b: &mut test::Bencher) { b.iter(|| { diff -Nru rust-humantime-1.3.0/Cargo.toml rust-humantime-2.0.0/Cargo.toml --- rust-humantime-1.3.0/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ rust-humantime-2.0.0/Cargo.toml 2020-01-19 01:45:28.000000000 +0000 @@ -11,8 +11,9 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "humantime" -version = "1.3.0" +version = "2.0.0" authors = ["Paul Colomiets "] description = " A parser and formatter for std::time::{Duration, SystemTime}\n" homepage = "https://github.com/tailhook/humantime" @@ -25,13 +26,11 @@ [lib] name = "humantime" path = "src/lib.rs" -[dependencies.quick-error] -version = "1.0.0" [dev-dependencies.chrono] -version = "0.4.0" +version = "0.4" [dev-dependencies.rand] -version = "0.4.2" +version = "0.6" [dev-dependencies.time] -version = "0.1.39" +version = "0.1" diff -Nru rust-humantime-1.3.0/Cargo.toml.orig rust-humantime-2.0.0/Cargo.toml.orig --- rust-humantime-1.3.0/Cargo.toml.orig 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/Cargo.toml.orig 2020-01-19 01:45:10.000000000 +0000 @@ -8,18 +8,16 @@ keywords = ["time", "human", "human-friendly", "parser", "duration"] homepage = "https://github.com/tailhook/humantime" documentation = "https://docs.rs/humantime" -version = "1.3.0" +version = "2.0.0" +edition = "2018" authors = ["Paul Colomiets "] categories = ["date-and-time"] -[dependencies] -quick-error = "1.0.0" - [lib] name = "humantime" path = "src/lib.rs" [dev-dependencies] -time = "0.1.39" -chrono = "0.4.0" -rand = "0.4.2" +time = "0.1" +chrono = "0.4" +rand = "0.6" diff -Nru rust-humantime-1.3.0/.cargo_vcs_info.json rust-humantime-2.0.0/.cargo_vcs_info.json --- rust-humantime-1.3.0/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ rust-humantime-2.0.0/.cargo_vcs_info.json 2020-01-19 01:45:28.000000000 +0000 @@ -1,5 +1,5 @@ { "git": { - "sha1": "19350dd88c18adbe596b6d95b601753f8c28006f" + "sha1": "d478f8a7878edba8a609a287776e27fc16d7009b" } } diff -Nru rust-humantime-1.3.0/debian/cargo-checksum.json rust-humantime-2.0.0/debian/cargo-checksum.json --- rust-humantime-1.3.0/debian/cargo-checksum.json 2019-11-28 00:47:25.000000000 +0000 +++ rust-humantime-2.0.0/debian/cargo-checksum.json 2020-03-28 14:29:44.000000000 +0000 @@ -1 +1 @@ -{"package":"df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f","files":{}} +{"package":"b9b6c53306532d3c8e8087b44e6580e10db51a023cf9b433cea2ac38066b92da","files":{}} diff -Nru rust-humantime-1.3.0/debian/changelog rust-humantime-2.0.0/debian/changelog --- rust-humantime-1.3.0/debian/changelog 2019-11-28 00:47:25.000000000 +0000 +++ rust-humantime-2.0.0/debian/changelog 2020-03-28 14:29:44.000000000 +0000 @@ -1,3 +1,10 @@ +rust-humantime (2.0.0-1) unstable; urgency=medium + + * Team upload. + * Package humantime 2.0.0 from crates.io using debcargo 2.4.0 + + -- Sylvestre Ledru Sat, 28 Mar 2020 15:29:44 +0100 + rust-humantime (1.3.0-1) unstable; urgency=medium * Team upload. diff -Nru rust-humantime-1.3.0/debian/control rust-humantime-2.0.0/debian/control --- rust-humantime-1.3.0/debian/control 2019-11-28 00:47:25.000000000 +0000 +++ rust-humantime-2.0.0/debian/control 2020-03-28 14:29:44.000000000 +0000 @@ -5,8 +5,7 @@ dh-cargo (>= 18), cargo:native , rustc:native , - libstd-rust-dev , - librust-quick-error-1+default-dev + libstd-rust-dev Maintainer: Debian Rust Maintainers Uploaders: Wolfgang Silbermayr @@ -19,16 +18,15 @@ Architecture: any Multi-Arch: same Depends: - ${misc:Depends}, - librust-quick-error-1+default-dev + ${misc:Depends} Provides: librust-humantime+default-dev (= ${binary:Version}), - librust-humantime-1-dev (= ${binary:Version}), - librust-humantime-1+default-dev (= ${binary:Version}), - librust-humantime-1.3-dev (= ${binary:Version}), - librust-humantime-1.3+default-dev (= ${binary:Version}), - librust-humantime-1.3.0-dev (= ${binary:Version}), - librust-humantime-1.3.0+default-dev (= ${binary:Version}) + librust-humantime-2-dev (= ${binary:Version}), + librust-humantime-2+default-dev (= ${binary:Version}), + librust-humantime-2.0-dev (= ${binary:Version}), + librust-humantime-2.0+default-dev (= ${binary:Version}), + librust-humantime-2.0.0-dev (= ${binary:Version}), + librust-humantime-2.0.0+default-dev (= ${binary:Version}) Description: Parser and formatter for std::time::{Duration, SystemTime} - Rust source code This package contains the source for the Rust humantime crate, packaged by debcargo for use with cargo and dh-cargo. diff -Nru rust-humantime-1.3.0/debian/copyright.debcargo.hint rust-humantime-2.0.0/debian/copyright.debcargo.hint --- rust-humantime-1.3.0/debian/copyright.debcargo.hint 2019-11-28 00:47:25.000000000 +0000 +++ rust-humantime-2.0.0/debian/copyright.debcargo.hint 2020-03-28 14:29:44.000000000 +0000 @@ -23,8 +23,8 @@ Files: debian/* Copyright: - 2018-2019 Debian Rust Maintainers - 2018-2019 Wolfgang Silbermayr + 2018-2020 Debian Rust Maintainers + 2018-2020 Wolfgang Silbermayr License: MIT or Apache-2.0 License: Apache-2.0 diff -Nru rust-humantime-1.3.0/debian/tests/control rust-humantime-2.0.0/debian/tests/control --- rust-humantime-1.3.0/debian/tests/control 2019-11-28 00:47:25.000000000 +0000 +++ rust-humantime-2.0.0/debian/tests/control 2020-03-28 14:29:44.000000000 +0000 @@ -1,7 +1,7 @@ -Test-Command: /usr/share/cargo/bin/cargo-auto-test humantime 1.3.0 --all-targets --all-features -Depends: dh-cargo (>= 18), librust-chrono-0.4+default-dev, librust-rand-0.4+default-dev (>= 0.4.2-~~), librust-time-0.1+default-dev (>= 0.1.39-~~), @ +Test-Command: /usr/share/cargo/bin/cargo-auto-test humantime 2.0.0 --all-targets --all-features +Depends: dh-cargo (>= 18), librust-chrono-0.4+default-dev, librust-rand-0.6+default-dev, librust-time-0.1+default-dev, @ Restrictions: allow-stderr, skip-not-installable -Test-Command: /usr/share/cargo/bin/cargo-auto-test humantime 1.3.0 --all-targets --no-default-features -Depends: dh-cargo (>= 18), librust-chrono-0.4+default-dev, librust-rand-0.4+default-dev (>= 0.4.2-~~), librust-time-0.1+default-dev (>= 0.1.39-~~), librust-humantime-dev +Test-Command: /usr/share/cargo/bin/cargo-auto-test humantime 2.0.0 --all-targets --no-default-features +Depends: dh-cargo (>= 18), librust-chrono-0.4+default-dev, librust-rand-0.6+default-dev, librust-time-0.1+default-dev, librust-humantime-dev Restrictions: allow-stderr, skip-not-installable diff -Nru rust-humantime-1.3.0/src/date.rs rust-humantime-2.0.0/src/date.rs --- rust-humantime-1.3.0/src/date.rs 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/src/date.rs 2020-01-19 01:45:10.000000000 +0000 @@ -1,3 +1,4 @@ +use std::error::Error as StdError; use std::fmt; use std::str; use std::time::{SystemTime, Duration, UNIX_EPOCH}; @@ -26,26 +27,30 @@ all(target_arch="wasm32", not(target_os="emscripten")), ))] mod max { - pub const SECONDS: u64 = 253402300800-1; // last second of year 9999 + pub const SECONDS: u64 = 253_402_300_800-1; // last second of year 9999 #[allow(unused)] - pub const TIMESTAMP: &'static str = "9999-12-31T23:59:59Z"; + pub const TIMESTAMP: &str = "9999-12-31T23:59:59Z"; } -quick_error! { - /// Error parsing datetime (timestamp) - #[derive(Debug, PartialEq, Clone, Copy)] - pub enum Error { - /// Numeric component is out of range - OutOfRange { - display("numeric component is out of range") - } - /// Bad character where digit is expected - InvalidDigit { - display("bad character where digit is expected") - } - /// Other formatting errors - InvalidFormat { - display("timestamp format is invalid") +/// Error parsing datetime (timestamp) +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum Error { + /// Numeric component is out of range + OutOfRange, + /// Bad character where digit is expected + InvalidDigit, + /// Other formatting errors + InvalidFormat, +} + +impl StdError for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::OutOfRange => write!(f, "numeric component is out of range"), + Error::InvalidDigit => write!(f, "bad character where digit is expected"), + Error::InvalidFormat => write!(f, "timestamp format is invalid"), } } } @@ -85,7 +90,7 @@ if b[10] != b'T' || b[b.len()-1] != b'Z' { return Err(Error::InvalidFormat); } - return parse_rfc3339_weak(s); + parse_rfc3339_weak(s) } /// Parse RFC3339-like timestamp `2018-02-14 00:28:07` @@ -172,10 +177,8 @@ nanos += mult * (b[idx] - b'0') as u32; mult /= 10; } - } else { - if b.len() != 19 && (b.len() > 20 || b[19] != b'Z') { - return Err(Error::InvalidFormat); - } + } else if b.len() != 19 && (b.len() > 20 || b[19] != b'Z') { + return Err(Error::InvalidFormat); } let total_seconds = time + days * 86400; @@ -183,11 +186,11 @@ return Err(Error::OutOfRange); } - return Ok(UNIX_EPOCH + Duration::new(total_seconds, nanos)); + Ok(UNIX_EPOCH + Duration::new(total_seconds, nanos)) } fn is_leap_year(y: u64) -> bool { - y % 4 == 0 && (!(y % 100 == 0) || y % 400 == 0) + y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) } /// Format an RFC3339 timestamp `2018-02-14T00:28:07Z` @@ -198,7 +201,7 @@ /// /// The value is always UTC and ignores system timezone. pub fn format_rfc3339(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Smart); + Rfc3339Timestamp(system_time, Precision::Smart) } /// Format an RFC3339 timestamp `2018-02-14T00:28:07Z` @@ -207,7 +210,7 @@ /// /// The value is always UTC and ignores system timezone. pub fn format_rfc3339_seconds(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Seconds); + Rfc3339Timestamp(system_time, Precision::Seconds) } /// Format an RFC3339 timestamp `2018-02-14T00:28:07.000Z` @@ -216,7 +219,7 @@ /// /// The value is always UTC and ignores system timezone. pub fn format_rfc3339_millis(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Millis); + Rfc3339Timestamp(system_time, Precision::Millis) } /// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000Z` @@ -225,7 +228,7 @@ /// /// The value is always UTC and ignores system timezone. pub fn format_rfc3339_micros(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Micros); + Rfc3339Timestamp(system_time, Precision::Micros) } /// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000000Z` @@ -234,7 +237,7 @@ /// /// The value is always UTC and ignores system timezone. pub fn format_rfc3339_nanos(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Nanos); + Rfc3339Timestamp(system_time, Precision::Nanos) } impl fmt::Display for Rfc3339Timestamp { @@ -246,7 +249,7 @@ let secs_since_epoch = dur.as_secs(); let nanos = dur.subsec_nanos(); - if secs_since_epoch >= 253402300800 { // year 9999 + if secs_since_epoch >= 253_402_300_800 { // year 9999 return Err(fmt::Error); } @@ -353,18 +356,17 @@ }; // we know our chars are all ascii - f.write_str(unsafe { str::from_utf8_unchecked(&buf[..offset+1]) }) + f.write_str(str::from_utf8(&buf[..=offset]).expect("Conversion to utf8 failed")) } } #[cfg(test)] mod test { - extern crate time; - extern crate rand; - use std::str::from_utf8; - use self::rand::Rng; use std::time::{UNIX_EPOCH, SystemTime, Duration}; + + use rand::Rng; + use super::{parse_rfc3339, parse_rfc3339_weak, format_rfc3339}; use super::{format_rfc3339_millis, format_rfc3339_micros}; use super::{format_rfc3339_nanos}; @@ -374,7 +376,7 @@ let s = time::at_utc(time::Timespec { sec: sec as i64, nsec: 0 }) .rfc3339().to_string(); let time = UNIX_EPOCH + Duration::new(sec, 0); - return (s, time) + (s, time) } #[test] @@ -394,9 +396,9 @@ assert_eq!(parse_rfc3339("1970-01-01T00:00:01Z").unwrap(), UNIX_EPOCH + Duration::new(1, 0)); assert_eq!(parse_rfc3339("2018-02-13T23:08:32Z").unwrap(), - UNIX_EPOCH + Duration::new(1518563312, 0)); + UNIX_EPOCH + Duration::new(1_518_563_312, 0)); assert_eq!(parse_rfc3339("2012-01-01T00:00:00Z").unwrap(), - UNIX_EPOCH + Duration::new(1325376000, 0)); + UNIX_EPOCH + Duration::new(1_325_376_000, 0)); } #[test] @@ -408,10 +410,10 @@ format_rfc3339(UNIX_EPOCH + Duration::new(1, 0)).to_string(), "1970-01-01T00:00:01Z"); assert_eq!( - format_rfc3339(UNIX_EPOCH + Duration::new(1518563312, 0)).to_string(), + format_rfc3339(UNIX_EPOCH + Duration::new(1_518_563_312, 0)).to_string(), "2018-02-13T23:08:32Z"); assert_eq!( - format_rfc3339(UNIX_EPOCH + Duration::new(1325376000, 0)).to_string(), + format_rfc3339(UNIX_EPOCH + Duration::new(1_325_376_000, 0)).to_string(), "2012-01-01T00:00:00Z"); } @@ -423,7 +425,7 @@ "1970-01-01T00:00:00.000Z"); assert_eq!( format_rfc3339_millis(UNIX_EPOCH + - Duration::new(1518563312, 123_000_000)).to_string(), + Duration::new(1_518_563_312, 123_000_000)).to_string(), "2018-02-13T23:08:32.123Z"); } @@ -435,11 +437,11 @@ "1970-01-01T00:00:00.000000Z"); assert_eq!( format_rfc3339_micros(UNIX_EPOCH + - Duration::new(1518563312, 123_000_000)).to_string(), + Duration::new(1_518_563_312, 123_000_000)).to_string(), "2018-02-13T23:08:32.123000Z"); assert_eq!( format_rfc3339_micros(UNIX_EPOCH + - Duration::new(1518563312, 456_123_000)).to_string(), + Duration::new(1_518_563_312, 456_123_000)).to_string(), "2018-02-13T23:08:32.456123Z"); } @@ -451,11 +453,11 @@ "1970-01-01T00:00:00.000000000Z"); assert_eq!( format_rfc3339_nanos(UNIX_EPOCH + - Duration::new(1518563312, 123_000_000)).to_string(), + Duration::new(1_518_563_312, 123_000_000)).to_string(), "2018-02-13T23:08:32.123000000Z"); assert_eq!( format_rfc3339_nanos(UNIX_EPOCH + - Duration::new(1518563312, 789_456_123)).to_string(), + Duration::new(1_518_563_312, 789_456_123)).to_string(), "2018-02-13T23:08:32.789456123Z"); } @@ -469,13 +471,13 @@ #[test] fn leap_second() { assert_eq!(parse_rfc3339("2016-12-31T23:59:60Z").unwrap(), - UNIX_EPOCH + Duration::new(1483228799, 0)); + UNIX_EPOCH + Duration::new(1_483_228_799, 0)); } #[test] fn first_731_days() { let year_start = 0; // 1970 - for day in 0.. (365 * 2 + 1) { // scan leap year and non-leap year + for day in 0..= 365 * 2 { // scan leap year and non-leap year let (s, time) = from_sec(year_start + day * 86400); assert_eq!(parse_rfc3339(&s).unwrap(), time); assert_eq!(format_rfc3339(time).to_string(), s); @@ -484,8 +486,8 @@ #[test] fn the_731_consecutive_days() { - let year_start = 1325376000; // 2012 - for day in 0.. (365 * 2 + 1) { // scan leap year and non-leap year + let year_start = 1_325_376_000; // 2012 + for day in 0..= 365 * 2 { // scan leap year and non-leap year let (s, time) = from_sec(year_start + day * 86400); assert_eq!(parse_rfc3339(&s).unwrap(), time); assert_eq!(format_rfc3339(time).to_string(), s); @@ -494,7 +496,7 @@ #[test] fn all_86400_seconds() { - let day_start = 1325376000; + let day_start = 1_325_376_000; for second in 0..86400 { // scan leap year and non-leap year let (s, time) = from_sec(day_start + second); assert_eq!(parse_rfc3339(&s).unwrap(), time); @@ -516,7 +518,7 @@ #[test] fn random_wide_range() { - for _ in 0..100000 { + for _ in 0..100_000 { let sec = rand::thread_rng().gen_range(0, max::SECONDS); let (s, time) = from_sec(sec); assert_eq!(parse_rfc3339(&s).unwrap(), time); @@ -527,8 +529,8 @@ #[test] fn milliseconds() { assert_eq!(parse_rfc3339("1970-01-01T00:00:00.123Z").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000000)); - assert_eq!(format_rfc3339(UNIX_EPOCH + Duration::new(0, 123000000)) + UNIX_EPOCH + Duration::new(0, 123_000_000)); + assert_eq!(format_rfc3339(UNIX_EPOCH + Duration::new(0, 123_000_000)) .to_string(), "1970-01-01T00:00:00.123000000Z"); } @@ -596,15 +598,15 @@ parse_rfc3339("1970-01-01 00:00:00").unwrap_err(); assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000)); + UNIX_EPOCH + Duration::new(0, 123_000)); parse_rfc3339("1970-01-01 00:00:00.000123").unwrap_err(); assert_eq!(parse_rfc3339_weak("1970-01-01T00:00:00.000123").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000)); + UNIX_EPOCH + Duration::new(0, 123_000)); parse_rfc3339("1970-01-01T00:00:00.000123").unwrap_err(); assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123Z").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000)); + UNIX_EPOCH + Duration::new(0, 123_000)); parse_rfc3339("1970-01-01 00:00:00.000123Z").unwrap_err(); assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00Z").unwrap(), diff -Nru rust-humantime-1.3.0/src/duration.rs rust-humantime-2.0.0/src/duration.rs --- rust-humantime-1.3.0/src/duration.rs 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/src/duration.rs 2020-01-19 01:45:10.000000000 +0000 @@ -1,60 +1,79 @@ +use std::error::Error as StdError; use std::fmt; use std::str::Chars; use std::time::Duration; -use std::error::Error as StdError; -quick_error! { - /// Error parsing human-friendly duration - #[derive(Debug, PartialEq, Clone, Copy)] - pub enum Error { - /// Invalid character during parsing - /// - /// More specifically anything that is not alphanumeric is prohibited - /// - /// The field is an byte offset of the character in the string. - InvalidCharacter(offset: usize) { - display("invalid character at {}", offset) - description("invalid character") - } - /// Non-numeric value where number is expected - /// - /// This usually means that either time unit is broken into words, - /// e.g. `m sec` instead of `msec`, or just number is omitted, - /// for example `2 hours min` instead of `2 hours 1 min` - /// - /// The field is an byte offset of the errorneous character - /// in the string. - NumberExpected(offset: usize) { - display("expected number at {}", offset) - description("expected number") - } - /// Unit in the number is not one of allowed units - /// - /// See documentation of `parse_duration` for the list of supported - /// time units. - /// - /// The two fields are start and end (exclusive) of the slice from - /// the original string, containing errorneous value - UnknownUnit(start: usize, end: usize) { - display("unknown unit at {}-{}", start, end) - description("unknown unit") - } - /// The numeric value is too large - /// - /// Usually this means value is too large to be useful. If user writes - /// data in subsecond units, then the maximum is about 3k years. When - /// using seconds, or larger units, the limit is even larger. - NumberOverflow { - display(self_) -> ("{}", self_.description()) - description("number is too large") - } - /// The value was an empty string (or consists only whitespace) - Empty { - display(self_) -> ("{}", self_.description()) - description("value was empty") +/// Error parsing human-friendly duration +#[derive(Debug, PartialEq, Clone)] +pub enum Error { + /// Invalid character during parsing + /// + /// More specifically anything that is not alphanumeric is prohibited + /// + /// The field is an byte offset of the character in the string. + InvalidCharacter(usize), + /// Non-numeric value where number is expected + /// + /// This usually means that either time unit is broken into words, + /// e.g. `m sec` instead of `msec`, or just number is omitted, + /// for example `2 hours min` instead of `2 hours 1 min` + /// + /// The field is an byte offset of the errorneous character + /// in the string. + NumberExpected(usize), + /// Unit in the number is not one of allowed units + /// + /// See documentation of `parse_duration` for the list of supported + /// time units. + /// + /// The two fields are start and end (exclusive) of the slice from + /// the original string, containing errorneous value + UnknownUnit { + /// Start of the invalid unit inside the original string + start: usize, + /// End of the invalid unit inside the original string + end: usize, + /// The unit verbatim + unit: String, + /// A number associated with the unit + value: u64, + }, + /// The numeric value is too large + /// + /// Usually this means value is too large to be useful. If user writes + /// data in subsecond units, then the maximum is about 3k years. When + /// using seconds, or larger units, the limit is even larger. + NumberOverflow, + /// The value was an empty string (or consists only whitespace) + Empty, +} + +impl StdError for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::InvalidCharacter(offset) => write!(f, "invalid character at {}", offset), + Error::NumberExpected(offset) => write!(f, "expected number at {}", offset), + Error::UnknownUnit { unit, value, .. } if &unit == &"" => { + write!(f, + "time unit needed, for example {0}sec or {0}ms", + value, + ) + } + Error::UnknownUnit { unit, .. } => { + write!( + f, + "unknown time unit {:?}, \ + supported units: ns, us, ms, sec, min, hours, days, \ + weeks, months, years (and few variations)", + unit + ) + } + Error::NumberOverflow => write!(f, "number is too large"), + Error::Empty => write!(f, "value was empty"), } } - } /// A wrapper type that allows you to Display a Duration @@ -90,7 +109,7 @@ let off = self.off(); for c in self.iter.by_ref() { match c { - '0'...'9' => { + '0'..='9' => { return Ok(Some(c as u64 - '0' as u64)); } c if c.is_whitespace() => continue, @@ -99,48 +118,54 @@ } } } - return Ok(None); + Ok(None) } fn parse_unit(&mut self, n: u64, start: usize, end: usize) -> Result<(), Error> { let (mut sec, nsec) = match &self.src[start..end] { "nanos" | "nsec" | "ns" => (0u64, n), - "usec" | "us" => (0u64, try!(n.mul(1000))), - "millis" | "msec" | "ms" => (0u64, try!(n.mul(1000_000))), + "usec" | "us" => (0u64, n.mul(1000)?), + "millis" | "msec" | "ms" => (0u64, n.mul(1_000_000)?), "seconds" | "second" | "secs" | "sec" | "s" => (n, 0), "minutes" | "minute" | "min" | "mins" | "m" - => (try!(n.mul(60)), 0), - "hours" | "hour" | "hr" | "hrs" | "h" => (try!(n.mul(3600)), 0), - "days" | "day" | "d" => (try!(n.mul(86400)), 0), - "weeks" | "week" | "w" => (try!(n.mul(86400*7)), 0), - "months" | "month" | "M" => (try!(n.mul(2630016)), 0), // 30.44d - "years" | "year" | "y" => (try!(n.mul(31557600)), 0), // 365.25d - _ => return Err(Error::UnknownUnit(start, end)), + => (n.mul(60)?, 0), + "hours" | "hour" | "hr" | "hrs" | "h" => (n.mul(3600)?, 0), + "days" | "day" | "d" => (n.mul(86400)?, 0), + "weeks" | "week" | "w" => (n.mul(86400*7)?, 0), + "months" | "month" | "M" => (n.mul(2_630_016)?, 0), // 30.44d + "years" | "year" | "y" => (n.mul(31_557_600)?, 0), // 365.25d + _ => { + return Err(Error::UnknownUnit { + start, end, + unit: self.src[start..end].to_string(), + value: n, + }); + } }; - let mut nsec = try!(self.current.1.add(nsec)); - if nsec > 1000_000_000 { - sec = try!(sec.add(nsec / 1000_000_000)); - nsec %= 1000_000_000; + let mut nsec = self.current.1.add(nsec)?; + if nsec > 1_000_000_000 { + sec = sec.add(nsec / 1_000_000_000)?; + nsec %= 1_000_000_000; } - sec = try!(self.current.0.add(sec)); + sec = self.current.0.add(sec)?; self.current = (sec, nsec); Ok(()) } fn parse(mut self) -> Result { - let mut n = try!(try!(self.parse_first_char()).ok_or(Error::Empty)); + let mut n = self.parse_first_char()?.ok_or(Error::Empty)?; 'outer: loop { let mut off = self.off(); while let Some(c) = self.iter.next() { match c { - '0'...'9' => { - n = try!(n.checked_mul(10) + '0'..='9' => { + n = n.checked_mul(10) .and_then(|x| x.checked_add(c as u64 - '0' as u64)) - .ok_or(Error::NumberOverflow)); + .ok_or(Error::NumberOverflow)?; } c if c.is_whitespace() => {} - 'a'...'z' | 'A'...'Z' => { + 'a'..='z' | 'A'..='Z' => { break; } _ => { @@ -153,21 +178,21 @@ let mut off = self.off(); while let Some(c) = self.iter.next() { match c { - '0'...'9' => { - try!(self.parse_unit(n, start, off)); + '0'..='9' => { + self.parse_unit(n, start, off)?; n = c as u64 - '0' as u64; continue 'outer; } c if c.is_whitespace() => break, - 'a'...'z' | 'A'...'Z' => {} + 'a'..='z' | 'A'..='Z' => {} _ => { return Err(Error::InvalidCharacter(off)); } } off = self.off(); } - try!(self.parse_unit(n, start, off)); - n = match try!(self.parse_first_char()) { + self.parse_unit(n, start, off)?; + n = match self.parse_first_char()? { Some(n) => n, None => return Ok( Duration::new(self.current.0, self.current.1 as u32)), @@ -270,10 +295,10 @@ return Ok(()); } - let years = secs / 31557600; // 365.25d - let ydays = secs % 31557600; - let months = ydays / 2630016; // 30.44d - let mdays = ydays % 2630016; + let years = secs / 31_557_600; // 365.25d + let ydays = secs % 31_557_600; + let months = ydays / 2_630_016; // 30.44d + let mdays = ydays % 2_630_016; let days = mdays / 86400; let day_secs = mdays % 86400; let hours = day_secs / 3600; @@ -300,23 +325,24 @@ #[cfg(test)] mod test { - extern crate rand; - use std::time::Duration; - use self::rand::Rng; + + use rand::Rng; + use super::{parse_duration, format_duration}; use super::Error; #[test] + #[allow(clippy::cognitive_complexity)] fn test_units() { assert_eq!(parse_duration("17nsec"), Ok(Duration::new(0, 17))); assert_eq!(parse_duration("17nanos"), Ok(Duration::new(0, 17))); assert_eq!(parse_duration("33ns"), Ok(Duration::new(0, 33))); assert_eq!(parse_duration("3usec"), Ok(Duration::new(0, 3000))); assert_eq!(parse_duration("78us"), Ok(Duration::new(0, 78000))); - assert_eq!(parse_duration("31msec"), Ok(Duration::new(0, 31000000))); - assert_eq!(parse_duration("31millis"), Ok(Duration::new(0, 31000000))); - assert_eq!(parse_duration("6ms"), Ok(Duration::new(0, 6000000))); + assert_eq!(parse_duration("31msec"), Ok(Duration::new(0, 31_000_000))); + assert_eq!(parse_duration("31millis"), Ok(Duration::new(0, 31_000_000))); + assert_eq!(parse_duration("6ms"), Ok(Duration::new(0, 6_000_000))); assert_eq!(parse_duration("3000s"), Ok(Duration::new(3000, 0))); assert_eq!(parse_duration("300sec"), Ok(Duration::new(300, 0))); assert_eq!(parse_duration("300secs"), Ok(Duration::new(300, 0))); @@ -333,17 +359,17 @@ assert_eq!(parse_duration("1hour"), Ok(Duration::new(3600, 0))); assert_eq!(parse_duration("24hours"), Ok(Duration::new(86400, 0))); assert_eq!(parse_duration("1day"), Ok(Duration::new(86400, 0))); - assert_eq!(parse_duration("2days"), Ok(Duration::new(172800, 0))); - assert_eq!(parse_duration("365d"), Ok(Duration::new(31536000, 0))); - assert_eq!(parse_duration("1week"), Ok(Duration::new(604800, 0))); - assert_eq!(parse_duration("7weeks"), Ok(Duration::new(4233600, 0))); - assert_eq!(parse_duration("52w"), Ok(Duration::new(31449600, 0))); - assert_eq!(parse_duration("1month"), Ok(Duration::new(2630016, 0))); - assert_eq!(parse_duration("3months"), Ok(Duration::new(3*2630016, 0))); - assert_eq!(parse_duration("12M"), Ok(Duration::new(31560192, 0))); - assert_eq!(parse_duration("1year"), Ok(Duration::new(31557600, 0))); - assert_eq!(parse_duration("7years"), Ok(Duration::new(7*31557600, 0))); - assert_eq!(parse_duration("17y"), Ok(Duration::new(536479200, 0))); + assert_eq!(parse_duration("2days"), Ok(Duration::new(172_800, 0))); + assert_eq!(parse_duration("365d"), Ok(Duration::new(31_536_000, 0))); + assert_eq!(parse_duration("1week"), Ok(Duration::new(604_800, 0))); + assert_eq!(parse_duration("7weeks"), Ok(Duration::new(4_233_600, 0))); + assert_eq!(parse_duration("52w"), Ok(Duration::new(31_449_600, 0))); + assert_eq!(parse_duration("1month"), Ok(Duration::new(2_630_016, 0))); + assert_eq!(parse_duration("3months"), Ok(Duration::new(3*2_630_016, 0))); + assert_eq!(parse_duration("12M"), Ok(Duration::new(31_560_192, 0))); + assert_eq!(parse_duration("1year"), Ok(Duration::new(31_557_600, 0))); + assert_eq!(parse_duration("7years"), Ok(Duration::new(7*31_557_600, 0))); + assert_eq!(parse_duration("17y"), Ok(Duration::new(536_479_200, 0))); } #[test] @@ -364,7 +390,7 @@ #[test] fn random_second() { for _ in 0..10000 { - let sec = rand::thread_rng().gen_range(0, 253370764800); + let sec = rand::thread_rng().gen_range(0, 253_370_764_800); let d = Duration::new(sec, 0); assert_eq!(d, parse_duration(&format_duration(d).to_string()).unwrap()); @@ -374,7 +400,7 @@ #[test] fn random_any() { for _ in 0..10000 { - let sec = rand::thread_rng().gen_range(0, 253370764800); + let sec = rand::thread_rng().gen_range(0, 253_370_764_800); let nanos = rand::thread_rng().gen_range(0, 1_000_000_000); let d = Duration::new(sec, nanos); assert_eq!(d, @@ -408,4 +434,16 @@ assert_eq!(parse_duration("10000000000000y"), Err(Error::NumberOverflow)); } + + #[test] + fn test_nice_error_message() { + assert_eq!(parse_duration("123").unwrap_err().to_string(), + "time unit needed, for example 123sec or 123ms"); + assert_eq!(parse_duration("10 months 1").unwrap_err().to_string(), + "time unit needed, for example 1sec or 1ms"); + assert_eq!(parse_duration("10nights").unwrap_err().to_string(), + "unknown time unit \"nights\", supported units: \ + ns, us, ms, sec, min, hours, days, weeks, months, \ + years (and few variations)"); + } } diff -Nru rust-humantime-1.3.0/src/lib.rs rust-humantime-2.0.0/src/lib.rs --- rust-humantime-1.3.0/src/lib.rs 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/src/lib.rs 2020-01-19 01:45:10.000000000 +0000 @@ -10,24 +10,25 @@ //! Timestamp parsing/formatting is super-fast because format is basically //! fixed. //! -//! See [serde-humantime] for serde integration. +//! See [humantime-serde] for serde integration (previous crate [serde-humantime] looks unmaintained). //! //! [serde-humantime]: https://docs.rs/serde-humantime/0.1.1/serde_humantime/ +//! [humantime-serde]: https://docs.rs/humantime-serde + +#![forbid(unsafe_code)] #![warn(missing_debug_implementations)] #![warn(missing_docs)] -#[macro_use] extern crate quick_error; - mod duration; mod wrapper; mod date; -pub use duration::{parse_duration, Error as DurationError}; -pub use duration::{format_duration, FormattedDuration}; -pub use wrapper::{Duration, Timestamp}; -pub use date::{parse_rfc3339, parse_rfc3339_weak, Error as TimestampError}; -pub use date::{ +pub use self::duration::{parse_duration, Error as DurationError}; +pub use self::duration::{format_duration, FormattedDuration}; +pub use self::wrapper::{Duration, Timestamp}; +pub use self::date::{parse_rfc3339, parse_rfc3339_weak, Error as TimestampError}; +pub use self::date::{ format_rfc3339, format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds, }; -pub use date::{Rfc3339Timestamp}; +pub use self::date::{Rfc3339Timestamp}; diff -Nru rust-humantime-1.3.0/src/wrapper.rs rust-humantime-2.0.0/src/wrapper.rs --- rust-humantime-1.3.0/src/wrapper.rs 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/src/wrapper.rs 2020-01-19 01:45:10.000000000 +0000 @@ -3,8 +3,8 @@ use std::fmt; use std::time::{Duration as StdDuration, SystemTime}; -use duration::{self, parse_duration, format_duration}; -use date::{self, parse_rfc3339_weak, format_rfc3339}; +use crate::duration::{self, parse_duration, format_duration}; +use crate::date::{self, parse_rfc3339_weak, format_rfc3339}; /// A wrapper for duration that has `FromStr` implementation /// diff -Nru rust-humantime-1.3.0/.travis.yml rust-humantime-2.0.0/.travis.yml --- rust-humantime-1.3.0/.travis.yml 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/.travis.yml 2020-01-19 01:45:10.000000000 +0000 @@ -11,7 +11,7 @@ jobs: include: - os: linux - rust: 1.18.0 + rust: 1.31.0 - os: linux rust: stable - os: linux diff -Nru rust-humantime-1.3.0/vagga.yaml rust-humantime-2.0.0/vagga.yaml --- rust-humantime-1.3.0/vagga.yaml 2019-09-09 20:50:33.000000000 +0000 +++ rust-humantime-2.0.0/vagga.yaml 2020-01-19 01:45:10.000000000 +0000 @@ -49,7 +49,7 @@ - !Install [ca-certificates, build-essential, vim] - !TarInstall - url: "https://static.rust-lang.org/dist/rust-1.24.0-x86_64-unknown-linux-gnu.tar.gz" + url: "https://static.rust-lang.org/dist/rust-1.31.0-x86_64-unknown-linux-gnu.tar.gz" script: "./install.sh --prefix=/usr \ --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo" - &bulk !Tar @@ -70,7 +70,7 @@ - !Install [ca-certificates, build-essential, vim] - !TarInstall - url: "https://static.rust-lang.org/dist/rust-1.24.0-i686-unknown-linux-gnu.tar.gz" + url: "https://static.rust-lang.org/dist/rust-1.31.0-i686-unknown-linux-gnu.tar.gz" script: "./install.sh --prefix=/usr \ --components=rustc,rust-std-i686-unknown-linux-gnu,cargo"