support customized timezone for clock

This commit is contained in:
race604 2022-09-02 14:07:37 +08:00
parent 3f357f3fd2
commit dafcdd91ff
4 changed files with 242 additions and 13 deletions

213
Cargo.lock generated
View file

@ -11,6 +11,15 @@ dependencies = [
"memchr", "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]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -34,6 +43,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]] [[package]]
name = "cassowary" name = "cassowary"
version = "0.3.0" version = "0.3.0"
@ -48,17 +63,42 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.19" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
dependencies = [ dependencies = [
"libc", "iana-time-zone",
"js-sys",
"num-integer", "num-integer",
"num-traits", "num-traits",
"time", "time",
"wasm-bindgen",
"winapi", "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]] [[package]]
name = "clap" name = "clap"
version = "3.2.12" version = "3.2.12"
@ -103,12 +143,19 @@ name = "clock-tui"
version = "0.4.0" version = "0.4.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"chrono-tz",
"clap", "clap",
"crossterm 0.24.0", "crossterm 0.24.0",
"regex", "regex",
"tui", "tui",
] ]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]] [[package]]
name = "crossterm" name = "crossterm"
version = "0.23.2" version = "0.23.2"
@ -171,6 +218,19 @@ dependencies = [
"libc", "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]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.1" version = "1.9.1"
@ -181,6 +241,15 @@ dependencies = [
"hashbrown", "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]] [[package]]
name = "libc" name = "libc"
version = "0.2.126" version = "0.2.126"
@ -278,6 +347,54 @@ dependencies = [
"windows-sys", "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]] [[package]]
name = "proc-macro-error" name = "proc-macro-error"
version = "1.0.4" version = "1.0.4"
@ -320,6 +437,21 @@ dependencies = [
"proc-macro2", "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]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.13" version = "0.2.13"
@ -352,6 +484,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
[[package]] [[package]]
name = "signal-hook" name = "signal-hook"
version = "0.3.14" version = "0.3.14"
@ -382,6 +520,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.9.0" version = "1.9.0"
@ -444,6 +588,15 @@ dependencies = [
"unicode-width", "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]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.2" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 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]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View file

@ -17,6 +17,7 @@ crossterm = "0.24"
chrono = "0.4" chrono = "0.4"
clap = { version = "3.2.12", features = ["derive"] } clap = { version = "3.2.12", features = ["derive"] }
regex = "1.6.0" regex = "1.6.0"
chrono-tz = { version = "0.6.3", features = ["serde"] }
[[bin]] [[bin]]
bench = false bench = false

View file

@ -5,6 +5,7 @@ use chrono::NaiveDate;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use chrono::NaiveTime; use chrono::NaiveTime;
use chrono::TimeZone; use chrono::TimeZone;
use chrono_tz::Tz;
use clap::Subcommand; use clap::Subcommand;
use crossterm::event::KeyCode; use crossterm::event::KeyCode;
use regex::Regex; use regex::Regex;
@ -25,6 +26,9 @@ pub(crate) mod modes;
pub(crate) enum Mode { pub(crate) enum Mode {
/// The clock mode displays the current time, the default mode. /// The clock mode displays the current time, the default mode.
Clock { Clock {
/// Custome timezone, for example "America/New_York", use local timezone if not specificed
#[clap(short = 'z', long, value_parser=parse_timezone)]
timezone: Option<Tz>,
/// Do not show date /// Do not show date
#[clap(short = 'D', long, takes_value = false)] #[clap(short = 'D', long, takes_value = false)]
no_date: bool, no_date: bool,
@ -127,12 +131,14 @@ impl App {
no_date: false, no_date: false,
millis: false, millis: false,
no_seconds: false, no_seconds: false,
timezone: None,
}); });
match mode { match mode {
Mode::Clock { Mode::Clock {
no_date, no_date,
no_seconds, no_seconds,
millis, millis,
timezone,
} => { } => {
self.clock = Some(Clock { self.clock = Some(Clock {
size: self.size, size: self.size,
@ -140,6 +146,7 @@ impl App {
show_date: !no_date, show_date: !no_date,
show_millis: *millis, show_millis: *millis,
show_secs: !no_seconds, show_secs: !no_seconds,
timezone: *timezone,
}); });
} }
Mode::Timer { Mode::Timer {
@ -302,3 +309,7 @@ fn parse_datetime(s: &str) -> Result<DateTime<Local>, String> {
Err("Invalid time format".to_string()) Err("Invalid time format".to_string())
} }
fn parse_timezone(s: &str) -> Result<Tz, String> {
s.parse()
}

View file

@ -1,4 +1,5 @@
use chrono::Local; use chrono::{Local, Utc};
use chrono_tz::Tz;
use clock_tui::bricks_text::BricksText; use clock_tui::bricks_text::BricksText;
use tui::{layout::Rect, style::Style, widgets::Widget}; use tui::{layout::Rect, style::Style, widgets::Widget};
@ -10,24 +11,33 @@ pub(crate) struct Clock {
pub show_date: bool, pub show_date: bool,
pub show_millis: bool, pub show_millis: bool,
pub show_secs: bool, pub show_secs: bool,
pub timezone: Option<Tz>,
} }
impl Widget for &Clock { impl Widget for &Clock {
fn render(self, area: Rect, buf: &mut tui::buffer::Buffer) { fn render(self, area: Rect, buf: &mut tui::buffer::Buffer) {
let now = Local::now(); let now = if let Some(ref tz) = self.timezone {
let time_str = if self.show_millis { Utc::now().with_timezone(tz).naive_local()
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()
} else { } 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 time_str = time_str.as_str();
let text = BricksText::new(time_str, self.size, self.size, self.style); let text = BricksText::new(time_str, self.size, self.size, self.style);
let header = if self.show_date { 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 { } else {
None None
}; };