Browse Source

adds day of week parameter (i.e. cet2est 2pm tue)

tags/v1.1.0
Jonathan Strong 1 year ago
parent
commit
031d8ac91f
6 changed files with 128 additions and 23 deletions
  1. +2
    -2
      Cargo.toml
  2. +24
    -0
      justfile
  3. +28
    -5
      src/cet2est.rs
  4. +29
    -6
      src/est2cet.rs
  5. +24
    -4
      src/lib.rs
  6. +21
    -6
      src/main.rs

+ 2
- 2
Cargo.toml View File

@@ -1,6 +1,6 @@
[package]
name = "tzconvert"
version = "1.0.0"
version = "1.1.0"
edition = "2018"
authors = ["Jonathan Strong <jstrong@mmcxi.com>"]

@@ -26,4 +26,4 @@ chrono-tz = { version = "0.5", features = ["serde"] }
structopt = "0.3"
regex = "1.5"
lazy_static = "1.4"
colored = "2"

+ 24
- 0
justfile View File

@@ -13,4 +13,28 @@ debug-build:
cargo build --bin cet2est
cargo build --bin est2cet

send-release remote-machine: release-build
scp -C target/release/tzconvert {{remote-machine}}:~/.cargo/bin
scp -C target/release/cet2est {{remote-machine}}:~/.cargo/bin
scp -C target/release/est2cet {{remote-machine}}:~/.cargo/bin

cargo +args:
cargo {{args}}

run-examples: debug-build
./target/debug/tzconvert CET EST 2pm
./target/debug/tzconvert EST CET 1:30pm tue
./target/debug/tzconvert Africa/Timbuktu America/Jamaica 18:30 --date 2021-11-03
./target/debug/tzconvert Africa/Timbuktu America/Jamaica 18:30 sat --date 2021-11-03
./target/debug/cet2est 2pm
./target/debug/cet2est 1:30pm tue
./target/debug/cet2est 14:15 -d 2021-11-03
./target/debug/cet2est 14:15 tue -d 2021-11-03
./target/debug/est2cet 2pm
./target/debug/est2cet 1:30pm tue
./target/debug/est2cet 14:15 -d 2021-11-03
./target/debug/est2cet 14:15 tue -d 2021-11-03





+ 28
- 5
src/cet2est.rs View File

@@ -1,19 +1,42 @@
use structopt::StructOpt;
use chrono::prelude::*;

/// convert CET time to EST
///
/// examples:
///
/// - cet2est 2pm
///
/// - cet2est 1:30pm thu
///
/// - cet2est 14:15 -d 2021-11-03
///
#[derive(StructOpt, Debug)]
#[structopt(author = env!("CARGO_PKG_AUTHORS"))]
struct Opt {
/// time to convert
/// time to convert (%H:%M or %I[:%M]%p)
#[structopt(value_name = "TIME")]
time: String,

/// specify the date on which the time lies. defaults to today.
#[structopt(long, short)]
/// optional: specify day of week the time lies, relative to today.
///
/// this will always result in a DATE greater than or equal to
/// today (in FROM TIMEZONE).
///
/// example: if today is Thursday, Aug. 26, passing DAY OF WEEK "Friday"/"fri"
/// will result in a DATE of Friday, Aug. 27.
#[structopt(value_name = "DAY OF WEEK")]
day: Option<String>,

/// optional: specify date the time lies. defaults to today.
///
/// when DAY OF WEEK argument is also specified, DAY OF WEEK will be picked relative
/// to DATE (i.e. the next occuring instance of, on or following DATE).
#[structopt(long, short, value_name = "DATE")]
date: Option<NaiveDate>,
}

fn main() {
let Opt { time, date } = Opt::from_args();
tzconvert::convert("Europe/Brussels", "EST", &time, date);
let Opt { time, date, day } = Opt::from_args();
tzconvert::convert("Europe/Brussels", "America/New_York", &time, day, date);
}

+ 29
- 6
src/est2cet.rs View File

@@ -1,19 +1,42 @@
use structopt::StructOpt;
use chrono::prelude::*;

/// convert EST time to CET
///
/// examples:
///
/// - est2cet 2pm
///
/// - est2cet 1:30pm thu
///
/// - est2cet 14:15 -d 2021-11-03
///
#[derive(StructOpt, Debug)]
#[structopt(author = env!("CARGO_PKG_AUTHORS"))]
struct Opt {
/// time to convert
#[structopt(value_name = "HH:MM")]
/// time to convert (%H:%M or %I[:%M]%p)
#[structopt(value_name = "TIME")]
time: String,

/// specify the date on which the time lies. defaults to today.
#[structopt(long, short)]
/// optional: specify day of week the time lies, relative to today.
///
/// this will always result in a DATE greater than or equal to
/// today (in FROM TIMEZONE).
///
/// example: if today is Thursday, Aug. 26, passing DAY OF WEEK "Friday"/"fri"
/// will result in a DATE of Friday, Aug. 27.
#[structopt(value_name = "DAY OF WEEK")]
day: Option<String>,

/// optional: specify date the time lies. defaults to today.
///
/// when DAY OF WEEK argument is also specified, DAY OF WEEK will be picked relative
/// to DATE (i.e. the next occuring instance of, on or following DATE).
#[structopt(long, short, value_name = "DATE")]
date: Option<NaiveDate>,
}

fn main() {
let Opt { time, date } = Opt::from_args();
tzconvert::convert("EST", "Europe/Brussels", &time, date);
let Opt { time, date, day } = Opt::from_args();
tzconvert::convert("America/New_York", "Europe/Brussels", &time, day, date);
}

+ 24
- 4
src/lib.rs View File

@@ -1,5 +1,7 @@
use std::str::FromStr;
use chrono::prelude::*;
use chrono_tz::Tz;
use colored::*;

lazy_static::lazy_static! {
static ref HOUR_AMPM: regex::Regex = regex::Regex::new(r#"(?P<hr>\d{1,2})\s?(?P<ampm>(am|pm|AM|PM))"#).unwrap();
@@ -40,7 +42,7 @@ fn convert_common_tz_abbrs(tz: &str) -> &str {
tz
}

pub fn convert(from: &str, to: &str, time: &str, date: Option<NaiveDate>) {
pub fn convert(from: &str, to: &str, time: &str, day: Option<String>, date: Option<NaiveDate>) {
let from = convert_common_tz_abbrs(from);
let to = convert_common_tz_abbrs(to);

@@ -61,6 +63,23 @@ pub fn convert(from: &str, to: &str, time: &str, date: Option<NaiveDate>) {
None => Utc::today().with_timezone(&fromtz),
};

let dt = match day {
Some(day_str) => {
let target_day_of_week: Weekday = Weekday::from_str(&day_str)
.map_err(|e| {
eprintln!("failed to parse day (input = '{}')", day_str);
e
}).unwrap();
let mut cur = dt;
while cur.weekday() != target_day_of_week {
cur = cur.succ();
}
cur
}

None => dt,
};

let src = dt.and_time(tm).unwrap();

let dst = src.with_timezone(&totz);
@@ -71,7 +90,7 @@ pub fn convert(from: &str, to: &str, time: &str, date: Option<NaiveDate>) {

let indent = " ";
println!();
println!("{} {} ... {} ... {}",
println!("{}{} ... {} ... {}",
indent,
pad_spaces(fromtz_str, n_spaces),
src.format("%a, %b %e"),
@@ -80,13 +99,14 @@ pub fn convert(from: &str, to: &str, time: &str, date: Option<NaiveDate>) {

println!();

println!("{} {} ... {} ... {}",
let dst_line = format!("{}{} ... {} ... {}",
indent,
pad_spaces(totz_str, n_spaces),
dst.format("%a, %b %e"),
dst.format("%l:%M%P"),
dst.format("%l:%M%P").to_string(),
);

println!("{}", dst_line.bold());
println!();
}



+ 21
- 6
src/main.rs View File

@@ -3,10 +3,12 @@ use chrono::prelude::*;

/// timezone converter
///
/// Examples:
/// examples:
///
/// - tzconvert CET EST 2pm
///
/// - tzconvert EST CET 1:30pm thu
///
/// - tzconvert Africa/Timbuktu America/Jamaica 18:30 --date 2021-11-03
///
#[derive(StructOpt, Debug)]
@@ -18,16 +20,29 @@ struct Opt {
/// destination time zone
#[structopt(value_name = "TO TIMEZONE")]
to: String,
/// time to convert (HH:MM or HH[:MM]am/HH[:MM]pm)
/// time to convert (%H:%M or %I[:%M]%p)
#[structopt(value_name = "TIME")]
time: String,

/// specify the date on which the time lies; defaults to today
#[structopt(long, short)]
/// optional: specify day of week the time lies, relative to today.
///
/// this will always result in a DATE greater than or equal to
/// today (in FROM TIMEZONE).
///
/// example: if today is Thursday, Aug. 26, passing DAY OF WEEK "Friday"/"fri"
/// will result in a DATE of Friday, Aug. 27.
#[structopt(value_name = "DAY OF WEEK")]
day: Option<String>,

/// optional: specify date the time lies. defaults to today.
///
/// when DAY OF WEEK argument is also specified, DAY OF WEEK will be picked relative
/// to DATE (i.e. the next occuring instance of, on or following DATE).
#[structopt(long, short, value_name = "DATE")]
date: Option<NaiveDate>,
}

fn main() {
let Opt { from, to, time, date } = Opt::from_args();
tzconvert::convert(&from, &to, &time, date);
let Opt { from, to, time, date, day } = Opt::from_args();
tzconvert::convert(&from, &to, &time, day, date);
}

Loading…
Cancel
Save