You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.6KB

  1. #![allow(unused)]
  2. use std::str::FromStr;
  3. use chrono::{DateTime, Utc, NaiveDateTime};
  4. const ONE_SECOND: u64 = 1_000_000_000_u64;
  5. fn nanos(utc: DateTime<Utc>) -> u64 {
  6. (utc.timestamp() as u64) * 1_000_000_000_u64 + (utc.timestamp_subsec_nanos() as u64)
  7. }
  8. fn get_time() -> (i64, i32) {
  9. let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 };
  10. unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, &mut tv); }
  11. (tv.tv_sec as i64, tv.tv_nsec as i32)
  12. }
  13. fn timespec_to_utc(sec: i64, nsec: i32) -> DateTime<Utc> {
  14. let naive = NaiveDateTime::from_timestamp(sec, nsec as u32);
  15. DateTime::from_utc(naive, Utc)
  16. }
  17. fn timespec_to_nanos(sec: i64, nsec: i32) -> u64 {
  18. (sec as u64) * ONE_SECOND + (nsec as u64)
  19. }
  20. fn nanos_to_timespec(nanos: u64) -> (i64, i32) {
  21. ((nanos / ONE_SECOND) as i64, (nanos % ONE_SECOND) as i32)
  22. }
  23. fn main() {
  24. let args: clap::ArgMatches = clap::App::new("utcnow")
  25. .author("Jonathan Strong <jonathan.strong@gmail.com>")
  26. .version(clap::crate_version!())
  27. .about("\ncurrent time in utc with non-cryptic interface.\n\n\
  28. for your own safety and well-being, local time functionality is not provided.\n\n\
  29. default output format is rfc3339 with trailing 'Z', e.g. '1999-12-31T23:59:59.999999999Z'")
  30. .help_message("help")
  31. .version_message("version")
  32. .arg(clap::Arg::with_name("unix")
  33. .help("display elapsed nanoseconds since 1970-01-01T00:00:00Z")
  34. .long("unix")
  35. .short("u")
  36. .required(false)
  37. .takes_value(false))
  38. .arg(clap::Arg::with_name("rfc2822")
  39. .help("display in rfc2822 format")
  40. .long("rfc2822")
  41. .short("r")
  42. .required(false)
  43. .takes_value(false))
  44. .arg(clap::Arg::with_name("seconds")
  45. .help("display unix timestamp in seconds, instead of default nanoseconds")
  46. .long("seconds")
  47. .short("s")
  48. .requires("unix")
  49. .conflicts_with_all(&["rfc2822", "timespec"])
  50. .required(false)
  51. .takes_value(false))
  52. .arg(clap::Arg::with_name("timespec")
  53. .help("display as <sec>,<nsec>")
  54. .long("timespec")
  55. .short("t")
  56. .required(false)
  57. .takes_value(false))
  58. .arg(clap::Arg::with_name("null")
  59. .short("0")
  60. .long("null")
  61. .help("terminate displayed time with null character instead of newline")
  62. .takes_value(false)
  63. .required(false))
  64. .arg(clap::Arg::with_name("unix-to-utc")
  65. .long("unix-to-utc")
  66. .help("convert integer unix timestamp (nanoseconds precision) to iso datetime")
  67. .takes_value(true)
  68. .required(false)
  69. .conflicts_with_all(&["unix", "seconds"]))
  70. .get_matches();
  71. let (sec, nsec): (i64, i32) =
  72. if let Some(ts_str) = args.value_of("unix-to-utc") { // either parse --unix-to-utc input
  73. match u64::from_str(ts_str) {
  74. Ok(nanos) => nanos_to_timespec(nanos),
  75. Err(e) => {
  76. eprintln!("failed to parse timestamp (expected integer): {}", e);
  77. std::process::exit(1);
  78. }
  79. }
  80. } else { // or else get current time
  81. get_time()
  82. };
  83. let endline = if args.is_present("null") { "\u{0}" } else { "\n" }; // pick endline - \n unless -0
  84. if args.is_present("timespec") { // display timespec
  85. print!("{},{}{}", sec, nsec, endline);
  86. } else if args.is_present("unix") { // display unix
  87. if args.is_present("seconds") { // unix seconds
  88. print!("{}{}", sec, endline);
  89. } else { // unix nanos
  90. print!("{}{}", timespec_to_nanos(sec, nsec), endline);
  91. }
  92. } else if args.is_present("rfc2822") { // display rfc2822
  93. print!("{}{}", timespec_to_utc(sec, nsec).to_rfc2822(), endline);
  94. } else { // display rfc3339
  95. // Debug view is iso format / rfc3339 that we want
  96. // Display has spaces - no go
  97. // to_rfc3339 uses +00:00 instead of Z, which I don't like
  98. print!("{:?}{}", timespec_to_utc(sec, nsec), endline);
  99. }
  100. }