diff --git a/Cargo.toml b/Cargo.toml index 4e36fe6..fba836e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "utcnow" -version = "1.0.0" +version = "1.1.0" authors = ["Jonathan Strong "] edition = "2018" diff --git a/src/main.rs b/src/main.rs index 23ae768..394519a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ #![allow(unused)] - +use std::str::FromStr; use chrono::{DateTime, Utc, NaiveDateTime}; +const ONE_SECOND: u64 = 1_000_000_000_u64; + fn nanos(utc: DateTime) -> u64 { (utc.timestamp() as u64) * 1_000_000_000_u64 + (utc.timestamp_subsec_nanos() as u64) } @@ -18,7 +20,11 @@ fn timespec_to_utc(sec: i64, nsec: i32) -> DateTime { } fn timespec_to_nanos(sec: i64, nsec: i32) -> u64 { - (sec as u64) * 1_000_000_000_u64 + (nsec as u64) + (sec as u64) * ONE_SECOND + (nsec as u64) +} + +fn nanos_to_timespec(nanos: u64) -> (i64, i32) { + ((nanos / ONE_SECOND) as i64, (nanos % ONE_SECOND) as i32) } fn main() { @@ -47,6 +53,7 @@ fn main() { .long("seconds") .short("s") .requires("unix") + .conflicts_with_all(&["rfc2822", "timespec"]) .required(false) .takes_value(false)) .arg(clap::Arg::with_name("timespec") @@ -55,26 +62,62 @@ fn main() { .short("t") .required(false) .takes_value(false)) + .arg(clap::Arg::with_name("null") + .short("0") + .long("null") + .help("terminate displayed time with null character instead of newline") + .takes_value(false) + .required(false)) + .arg(clap::Arg::with_name("unix-to-utc") + .long("unix-to-utc") + .help("convert integer unix timestamp (nanoseconds precision) to iso datetime") + .takes_value(true) + .required(false) + .conflicts_with_all(&["unix", "seconds"])) .get_matches(); - let (sec, nsec) = get_time(); + + let (sec, nsec): (i64, i32) = + + if let Some(ts_str) = args.value_of("unix-to-utc") { // either parse --unix-to-utc input + match u64::from_str(ts_str) { + Ok(nanos) => nanos_to_timespec(nanos), + + Err(e) => { + eprintln!("failed to parse timestamp (expected integer): {}", e); + std::process::exit(1); + } + } + } else { // or else get current time + get_time() + }; + - if args.is_present("timespec") { - println!("{},{}", sec, nsec); - } else if args.is_present("unix") { - if args.is_present("seconds") { - println!("{}", sec); - } else { - println!("{}", timespec_to_nanos(sec, nsec)); + let endline = if args.is_present("null") { "\u{0}" } else { "\n" }; // pick endline - \n unless -0 + + + if args.is_present("timespec") { // display timespec + print!("{},{}{}", sec, nsec, endline); + + + } else if args.is_present("unix") { // display unix + + if args.is_present("seconds") { // unix seconds + print!("{}{}", sec, endline); + + } else { // unix nanos + print!("{}{}", timespec_to_nanos(sec, nsec), endline); } - } else if args.is_present("rfc2822") { - println!("{}", timespec_to_utc(sec, nsec).to_rfc2822()); - } else { + } else if args.is_present("rfc2822") { // display rfc2822 + print!("{}{}", timespec_to_utc(sec, nsec).to_rfc2822(), endline); + + + } else { // display rfc3339 // Debug view is iso format / rfc3339 that we want // Display has spaces - no go // to_rfc3339 uses +00:00 instead of Z, which I don't like - println!("{:?}", timespec_to_utc(sec, nsec)); + print!("{:?}{}", timespec_to_utc(sec, nsec), endline); } }