Browse Source

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

tags/v1.1.0
Jonathan Strong 2 years 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] [package]
name = "tzconvert" name = "tzconvert"
version = "1.0.0"
version = "1.1.0"
edition = "2018" edition = "2018"
authors = ["Jonathan Strong <jstrong@mmcxi.com>"] authors = ["Jonathan Strong <jstrong@mmcxi.com>"]


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

+ 24
- 0
justfile View File

@@ -13,4 +13,28 @@ debug-build:
cargo build --bin cet2est cargo build --bin cet2est
cargo build --bin est2cet 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 structopt::StructOpt;
use chrono::prelude::*; 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)] #[derive(StructOpt, Debug)]
#[structopt(author = env!("CARGO_PKG_AUTHORS"))] #[structopt(author = env!("CARGO_PKG_AUTHORS"))]
struct Opt { struct Opt {
/// time to convert
/// time to convert (%H:%M or %I[:%M]%p)
#[structopt(value_name = "TIME")] #[structopt(value_name = "TIME")]
time: String, 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>, date: Option<NaiveDate>,
} }


fn main() { 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 structopt::StructOpt;
use chrono::prelude::*; 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)] #[derive(StructOpt, Debug)]
#[structopt(author = env!("CARGO_PKG_AUTHORS"))] #[structopt(author = env!("CARGO_PKG_AUTHORS"))]
struct Opt { 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, 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>, date: Option<NaiveDate>,
} }


fn main() { 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::prelude::*;
use chrono_tz::Tz; use chrono_tz::Tz;
use colored::*;


lazy_static::lazy_static! { 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(); 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 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 from = convert_common_tz_abbrs(from);
let to = convert_common_tz_abbrs(to); 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), 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 src = dt.and_time(tm).unwrap();


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


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


println!(); println!();


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


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




+ 21
- 6
src/main.rs View File

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


/// timezone converter /// timezone converter
/// ///
/// Examples:
/// examples:
/// ///
/// - tzconvert CET EST 2pm /// - tzconvert CET EST 2pm
/// ///
/// - tzconvert EST CET 1:30pm thu
///
/// - tzconvert Africa/Timbuktu America/Jamaica 18:30 --date 2021-11-03 /// - tzconvert Africa/Timbuktu America/Jamaica 18:30 --date 2021-11-03
/// ///
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
@@ -18,16 +20,29 @@ struct Opt {
/// destination time zone /// destination time zone
#[structopt(value_name = "TO TIMEZONE")] #[structopt(value_name = "TO TIMEZONE")]
to: String, 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")] #[structopt(value_name = "TIME")]
time: String, 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>, date: Option<NaiveDate>,
} }


fn main() { 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