diff --git a/Cargo.lock b/Cargo.lock index c18c345..eabe0f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "atty" version = "0.2.14" @@ -34,6 +43,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + [[package]] name = "cassowary" version = "0.3.0" @@ -48,17 +63,42 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "time", + "wasm-bindgen", "winapi", ] +[[package]] +name = "chrono-tz" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c39203181991a7dd4343b8005bd804e7a9a37afb8ac070e43771e8c820bbde" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", + "serde", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f509c3a87b33437b05e2458750a0700e5bdd6956176773e6c7d6dd15a283a0c" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", +] + [[package]] name = "clap" version = "3.2.12" @@ -103,12 +143,19 @@ name = "clock-tui" version = "0.4.0" dependencies = [ "chrono", + "chrono-tz", "clap", "crossterm 0.24.0", "regex", "tui", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "crossterm" version = "0.23.2" @@ -171,6 +218,19 @@ dependencies = [ "libc", ] +[[package]] +name = "iana-time-zone" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "wasm-bindgen", + "winapi", +] + [[package]] name = "indexmap" version = "1.9.1" @@ -181,6 +241,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "js-sys" +version = "0.3.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.126" @@ -278,6 +347,54 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + +[[package]] +name = "phf" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +dependencies = [ + "siphasher", + "uncased", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -320,6 +437,21 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" + [[package]] name = "redox_syscall" version = "0.2.13" @@ -352,6 +484,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "serde" +version = "1.0.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" + [[package]] name = "signal-hook" version = "0.3.14" @@ -382,6 +520,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "smallvec" version = "1.9.0" @@ -444,6 +588,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-ident" version = "1.0.2" @@ -480,6 +633,60 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 99abb01..2397fac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ crossterm = "0.24" chrono = "0.4" clap = { version = "3.2.12", features = ["derive"] } regex = "1.6.0" +chrono-tz = { version = "0.6.3", features = ["serde"] } [[bin]] bench = false diff --git a/src/app.rs b/src/app.rs index 220f12d..d5a8aa6 100644 --- a/src/app.rs +++ b/src/app.rs @@ -5,6 +5,7 @@ use chrono::NaiveDate; use chrono::NaiveDateTime; use chrono::NaiveTime; use chrono::TimeZone; +use chrono_tz::Tz; use clap::Subcommand; use crossterm::event::KeyCode; use regex::Regex; @@ -25,6 +26,9 @@ pub(crate) mod modes; pub(crate) enum Mode { /// The clock mode displays the current time, the default mode. Clock { + /// Custome timezone, for example "America/New_York", use local timezone if not specificed + #[clap(short = 'z', long, value_parser=parse_timezone)] + timezone: Option, /// Do not show date #[clap(short = 'D', long, takes_value = false)] no_date: bool, @@ -127,12 +131,14 @@ impl App { no_date: false, millis: false, no_seconds: false, + timezone: None, }); match mode { Mode::Clock { no_date, no_seconds, millis, + timezone, } => { self.clock = Some(Clock { size: self.size, @@ -140,6 +146,7 @@ impl App { show_date: !no_date, show_millis: *millis, show_secs: !no_seconds, + timezone: *timezone, }); } Mode::Timer { @@ -302,3 +309,7 @@ fn parse_datetime(s: &str) -> Result, String> { Err("Invalid time format".to_string()) } + +fn parse_timezone(s: &str) -> Result { + s.parse() +} diff --git a/src/app/modes/clock.rs b/src/app/modes/clock.rs index e6837f0..fc17a9a 100644 --- a/src/app/modes/clock.rs +++ b/src/app/modes/clock.rs @@ -1,4 +1,5 @@ -use chrono::Local; +use chrono::{Local, Utc}; +use chrono_tz::Tz; use clock_tui::bricks_text::BricksText; use tui::{layout::Rect, style::Style, widgets::Widget}; @@ -10,24 +11,33 @@ pub(crate) struct Clock { pub show_date: bool, pub show_millis: bool, pub show_secs: bool, + pub timezone: Option, } impl Widget for &Clock { fn render(self, area: Rect, buf: &mut tui::buffer::Buffer) { - let now = Local::now(); - let time_str = if self.show_millis { - let mut str = now.format("%H:%M:%S%.3f").to_string(); - str.truncate(str.len() - 2); - str - } else if self.show_secs { - now.format("%H:%M:%S").to_string() + let now = if let Some(ref tz) = self.timezone { + Utc::now().with_timezone(tz).naive_local() } else { - now.format("%H:%M").to_string() + Local::now().naive_local() + }; + let mut time_str = now.format("%H:%M:%S%.3f").to_string(); + if self.show_millis { + time_str.truncate(time_str.len() - 2); + } else if self.show_secs { + time_str.truncate(time_str.len() - 4); + } else { + time_str.truncate(time_str.len() - 7); }; let time_str = time_str.as_str(); let text = BricksText::new(time_str, self.size, self.size, self.style); let header = if self.show_date { - Some(now.format("%Y-%m-%d %Z").to_string()) + let mut title = now.format("%Y-%m-%d").to_string(); + if let Some(tz) = self.timezone { + title.push(' '); + title.push_str(tz.name()); + } + Some(title) } else { None };