From 0c223ebad262e70fc31d777dd214ff20ae67ab1a Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Wed, 2 Oct 2024 19:42:16 -0300 Subject: [PATCH 1/9] feat(cdk): hub list should include release date --- crates/fluvio-hub-util/src/cmd/list.rs | 67 +++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/crates/fluvio-hub-util/src/cmd/list.rs b/crates/fluvio-hub-util/src/cmd/list.rs index 7e3f9d3c8c..7c30aa013a 100644 --- a/crates/fluvio-hub-util/src/cmd/list.rs +++ b/crates/fluvio-hub-util/src/cmd/list.rs @@ -1,6 +1,8 @@ use std::sync::Arc; use std::fmt::Debug; +use chrono::DateTime; +use chrono::Utc; use clap::Parser; use anyhow::Result; @@ -19,6 +21,10 @@ pub struct ConnectorHubListOpts { #[arg(long, hide = true)] system: bool, + /// Show exact time instead of relative time for `Release` column + #[arg(long, default_value = "false")] + exact_time: bool, + #[arg(long, hide_short_help = true)] remote: Option, } @@ -26,7 +32,7 @@ pub struct ConnectorHubListOpts { impl ConnectorHubListOpts { pub async fn process(self, out: Arc) -> Result<()> { let pl = get_pkg_list(HUB_API_CONN_LIST, &self.remote, self.system).await?; - output::tableformat(out, pl.packages, self.output.format)?; + output::tableformat(out, pl.packages, self.output.format, self.exact_time)?; Ok(()) } } @@ -45,10 +51,16 @@ mod output { use fluvio_extension_common::Terminal; use fluvio_extension_common::output::TableOutputHandler; use fluvio_extension_common::t_println; - use crate::PackageMeta; + + use crate::{PackageMeta, PackageMetaExt}; + + use super::format_duration; #[derive(Serialize)] - struct ListConnectors(Vec); + struct ListConnectors { + pkgs: Vec, + exact_time: bool, + } // ----------------------------------- // Format Output @@ -59,11 +71,15 @@ mod output { out: std::sync::Arc, list_pkgs: Vec, output_type: OutputType, + exact_time: bool, ) -> Result<()> { debug!("connectors: {:#?}", list_pkgs); if !list_pkgs.is_empty() { - let connectors = ListConnectors(list_pkgs); + let connectors = ListConnectors { + pkgs: list_pkgs, + exact_time, + }; out.render_list(&connectors, output_type)?; Ok(()) } else { @@ -78,7 +94,7 @@ mod output { impl TableOutputHandler for ListConnectors { /// table header implementation fn header(&self) -> Row { - Row::from(["CONNECTOR", "Visibility"]) + Row::from(["Connector", "Visibility", "Released"]) } /// return errors in string format @@ -88,15 +104,54 @@ mod output { /// table content implementation fn content(&self) -> Vec { - self.0 + self.pkgs .iter() .map(|e| { Row::from([ Cell::new(e.pkg_name()).set_alignment(CellAlignment::Left), Cell::new(&e.visibility).set_alignment(CellAlignment::Left), + Cell::new( + e.published_at() + .map(|date| format_duration(date, self.exact_time)) + .unwrap_or(String::from("N/A")), + ), ]) }) .collect() } } } + +fn format_duration(date: DateTime, exact: bool) -> String { + let duration = Utc::now().signed_duration_since(date); + + if exact { + return date.format("%Y-%m-%d %H:%M:%S %Z").to_string(); + } + + if duration.num_weeks() >= 1 { + return date.format("%Y/%m/%d").to_string(); + } + + if duration.num_days() >= 2 { + return format!("{} days ago", duration.num_days()); + } + + if duration.num_days() == 1 { + return String::from("Yesterday"); + } + + if duration.num_hours() >= 1 { + return format!("{} hours ago", duration.num_hours()); + } + + if duration.num_minutes() >= 1 { + return format!("{} minutes ago", duration.num_minutes()); + } + + if duration.num_minutes() < 1 { + return String::from("Just now"); + } + + date.format("%Y/%m/%d").to_string() +} From eb6b665c56b7809337696bdb6f1ebe937dec520f Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Thu, 3 Oct 2024 11:49:00 -0300 Subject: [PATCH 2/9] chore: centralize format algorithm in extension common --- Cargo.lock | 1 + .../src/client/hub/smartmodule/list.rs | 34 +++++++++++--- crates/fluvio-extension-common/Cargo.toml | 1 + .../fluvio-extension-common/src/common/mod.rs | 2 + .../src/common/time.rs | 35 ++++++++++++++ crates/fluvio-hub-util/src/cmd/list.rs | 47 ++----------------- 6 files changed, 72 insertions(+), 48 deletions(-) create mode 100644 crates/fluvio-extension-common/src/common/time.rs diff --git a/Cargo.lock b/Cargo.lock index 857e7e87ed..87538156e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2769,6 +2769,7 @@ version = "0.14.2" dependencies = [ "anyhow", "async-trait", + "chrono", "clap", "comfy-table", "fluvio", diff --git a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs index 7e8fc14c08..515fb50edc 100644 --- a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs +++ b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs @@ -16,6 +16,10 @@ pub struct SmartModuleHubListOpts { #[clap(flatten)] output: OutputFormat, + /// Show exact time instead of relative time for `Released` column + #[arg(long, default_value = "false")] + exact_time: bool, + #[arg(long, hide = true)] system: bool, @@ -26,7 +30,12 @@ pub struct SmartModuleHubListOpts { impl SmartModuleHubListOpts { pub async fn process(self, out: Arc) -> Result<()> { let pl = get_pkg_list(HUB_API_LIST_META, &self.remote, self.system).await?; - output::smartmodules_response_to_output(out, pl.packages, self.output.format)?; + output::smartmodules_response_to_output( + out, + pl.packages, + self.output.format, + self.exact_time, + )?; Ok(()) } } @@ -40,6 +49,7 @@ mod output { //! Format SmartModules response based on output type use comfy_table::{Cell, Row}; use comfy_table::CellAlignment; + use fluvio_extension_common::time::format_duration; use tracing::debug; use serde::Serialize; use anyhow::Result; @@ -48,10 +58,13 @@ mod output { use fluvio_extension_common::Terminal; use fluvio_extension_common::output::TableOutputHandler; use fluvio_extension_common::t_println; - use fluvio_hub_util::PackageMeta; + use fluvio_hub_util::{PackageMeta, PackageMetaExt}; #[derive(Serialize)] - struct ListSmartModules(Vec); + struct ListSmartModules { + pkgs: Vec, + exact_time: bool, + } // ----------------------------------- // Format Output @@ -62,11 +75,15 @@ mod output { out: std::sync::Arc, list_smartmodules: Vec, output_type: OutputType, + exact_time: bool, ) -> Result<()> { debug!("smartmodules: {:#?}", list_smartmodules); if !list_smartmodules.is_empty() { - let smartmodules = ListSmartModules(list_smartmodules); + let smartmodules = ListSmartModules { + pkgs: list_smartmodules, + exact_time, + }; out.render_list(&smartmodules, output_type)?; Ok(()) } else { @@ -81,7 +98,7 @@ mod output { impl TableOutputHandler for ListSmartModules { /// table header implementation fn header(&self) -> Row { - Row::from(["SMARTMODULE", "Visibility"]) + Row::from(["SmartModule", "Visibility", "Released"]) } /// return errors in string format @@ -91,12 +108,17 @@ mod output { /// table content implementation fn content(&self) -> Vec { - self.0 + self.pkgs .iter() .map(|e| { Row::from([ Cell::new(e.pkg_name()).set_alignment(CellAlignment::Left), Cell::new(&e.visibility).set_alignment(CellAlignment::Left), + Cell::new( + e.published_at() + .map(|date| format_duration(date, self.exact_time)) + .unwrap_or(String::from("N/A")), + ), ]) }) .collect() diff --git a/crates/fluvio-extension-common/Cargo.toml b/crates/fluvio-extension-common/Cargo.toml index 9a95568d93..4167558927 100644 --- a/crates/fluvio-extension-common/Cargo.toml +++ b/crates/fluvio-extension-common/Cargo.toml @@ -18,6 +18,7 @@ installation = ["fluvio"] [dependencies] anyhow = { workspace = true } async-trait = { workspace = true } +chrono = { workspace = true } clap = { workspace = true, features = ["std", "derive", "help", "usage", "error-context"], default-features = false } comfy-table = { workspace = true } serde = { workspace = true, features = ['derive'] } diff --git a/crates/fluvio-extension-common/src/common/mod.rs b/crates/fluvio-extension-common/src/common/mod.rs index 24c7ca3ddf..9c10be1245 100644 --- a/crates/fluvio-extension-common/src/common/mod.rs +++ b/crates/fluvio-extension-common/src/common/mod.rs @@ -3,6 +3,8 @@ use clap::Parser; mod hex_dump; pub use self::hex_dump::*; +pub mod time; + use crate::output::OutputType; #[derive(Debug, Parser, Default, Clone)] diff --git a/crates/fluvio-extension-common/src/common/time.rs b/crates/fluvio-extension-common/src/common/time.rs new file mode 100644 index 0000000000..76ee004471 --- /dev/null +++ b/crates/fluvio-extension-common/src/common/time.rs @@ -0,0 +1,35 @@ +use chrono::{DateTime, Utc}; + +pub fn format_duration(date: DateTime, exact: bool) -> String { + let duration = Utc::now().signed_duration_since(date); + + if exact { + return date.format("%Y-%m-%d %H:%M:%S %Z").to_string(); + } + + if duration.num_weeks() >= 1 { + return date.format("%Y/%m/%d").to_string(); + } + + if duration.num_days() >= 2 { + return format!("{} days ago", duration.num_days()); + } + + if duration.num_days() == 1 { + return String::from("Yesterday"); + } + + if duration.num_hours() >= 1 { + return format!("{} hours ago", duration.num_hours()); + } + + if duration.num_minutes() >= 1 { + return format!("{} minutes ago", duration.num_minutes()); + } + + if duration.num_minutes() < 1 { + return String::from("Just now"); + } + + date.format("%Y/%m/%d").to_string() +} diff --git a/crates/fluvio-hub-util/src/cmd/list.rs b/crates/fluvio-hub-util/src/cmd/list.rs index 7c30aa013a..3ff831344f 100644 --- a/crates/fluvio-hub-util/src/cmd/list.rs +++ b/crates/fluvio-hub-util/src/cmd/list.rs @@ -1,8 +1,6 @@ use std::sync::Arc; use std::fmt::Debug; -use chrono::DateTime; -use chrono::Utc; use clap::Parser; use anyhow::Result; @@ -18,15 +16,15 @@ pub struct ConnectorHubListOpts { #[clap(flatten)] output: OutputFormat, - #[arg(long, hide = true)] - system: bool, - - /// Show exact time instead of relative time for `Release` column + /// Show exact time instead of relative time for `Released` column #[arg(long, default_value = "false")] exact_time: bool, #[arg(long, hide_short_help = true)] remote: Option, + + #[arg(long, hide = true)] + system: bool, } impl ConnectorHubListOpts { @@ -48,14 +46,13 @@ mod output { use anyhow::Result; use fluvio_extension_common::output::OutputType; + use fluvio_extension_common::time::format_duration; use fluvio_extension_common::Terminal; use fluvio_extension_common::output::TableOutputHandler; use fluvio_extension_common::t_println; use crate::{PackageMeta, PackageMetaExt}; - use super::format_duration; - #[derive(Serialize)] struct ListConnectors { pkgs: Vec, @@ -121,37 +118,3 @@ mod output { } } } - -fn format_duration(date: DateTime, exact: bool) -> String { - let duration = Utc::now().signed_duration_since(date); - - if exact { - return date.format("%Y-%m-%d %H:%M:%S %Z").to_string(); - } - - if duration.num_weeks() >= 1 { - return date.format("%Y/%m/%d").to_string(); - } - - if duration.num_days() >= 2 { - return format!("{} days ago", duration.num_days()); - } - - if duration.num_days() == 1 { - return String::from("Yesterday"); - } - - if duration.num_hours() >= 1 { - return format!("{} hours ago", duration.num_hours()); - } - - if duration.num_minutes() >= 1 { - return format!("{} minutes ago", duration.num_minutes()); - } - - if duration.num_minutes() < 1 { - return String::from("Just now"); - } - - date.format("%Y/%m/%d").to_string() -} From 231efc91f651adb6b52378bb0cd5d6e995f74181 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Thu, 3 Oct 2024 12:56:57 -0300 Subject: [PATCH 3/9] chore: tests for time rendering --- crates/fluvio-extension-common/Cargo.toml | 2 +- .../src/common/time.rs | 85 +++++++++++++++++-- 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/crates/fluvio-extension-common/Cargo.toml b/crates/fluvio-extension-common/Cargo.toml index 4167558927..a59dc889d1 100644 --- a/crates/fluvio-extension-common/Cargo.toml +++ b/crates/fluvio-extension-common/Cargo.toml @@ -18,7 +18,7 @@ installation = ["fluvio"] [dependencies] anyhow = { workspace = true } async-trait = { workspace = true } -chrono = { workspace = true } +chrono = { workspace = true, features = ["clock"] } clap = { workspace = true, features = ["std", "derive", "help", "usage", "error-context"], default-features = false } comfy-table = { workspace = true } serde = { workspace = true, features = ['derive'] } diff --git a/crates/fluvio-extension-common/src/common/time.rs b/crates/fluvio-extension-common/src/common/time.rs index 76ee004471..2d86bd96c4 100644 --- a/crates/fluvio-extension-common/src/common/time.rs +++ b/crates/fluvio-extension-common/src/common/time.rs @@ -1,14 +1,17 @@ use chrono::{DateTime, Utc}; +const SIMPLE_DATE_FORMAT: &str = "%Y/%m/%d"; +const EXACT_FORMAT: &str = "%Y-%m-%d %H:%M:%S %Z"; + pub fn format_duration(date: DateTime, exact: bool) -> String { let duration = Utc::now().signed_duration_since(date); if exact { - return date.format("%Y-%m-%d %H:%M:%S %Z").to_string(); + return date.format(EXACT_FORMAT).to_string(); } if duration.num_weeks() >= 1 { - return date.format("%Y/%m/%d").to_string(); + return date.format(SIMPLE_DATE_FORMAT).to_string(); } if duration.num_days() >= 2 { @@ -19,11 +22,11 @@ pub fn format_duration(date: DateTime, exact: bool) -> String { return String::from("Yesterday"); } - if duration.num_hours() >= 1 { + if duration.num_hours() >= 1 && duration.num_hours() < 24 { return format!("{} hours ago", duration.num_hours()); } - if duration.num_minutes() >= 1 { + if duration.num_minutes() >= 1 && duration.num_minutes() < 59 { return format!("{} minutes ago", duration.num_minutes()); } @@ -31,5 +34,77 @@ pub fn format_duration(date: DateTime, exact: bool) -> String { return String::from("Just now"); } - date.format("%Y/%m/%d").to_string() + date.format(SIMPLE_DATE_FORMAT).to_string() +} + +#[cfg(test)] +mod tests { + use chrono::{Days, Timelike, Utc}; + + use crate::time::{EXACT_FORMAT, SIMPLE_DATE_FORMAT}; + + use super::format_duration; + + #[test] + fn determines_exact_date() { + let date = Utc::now(); + let formatted = format_duration(date, true); + + assert_eq!(formatted, date.format(EXACT_FORMAT).to_string()); + } + + #[test] + fn simple_date_format_for_exceeding_a_week() { + let date = Utc::now() + .checked_sub_days(Days::new(7)) + .expect("failed to sub days"); + let formatted = format_duration(date, false); + + assert_eq!(formatted, date.format(SIMPLE_DATE_FORMAT).to_string()); + } + + #[test] + fn renders_days_passed() { + let date = Utc::now() + .checked_sub_days(Days::new(2)) + .expect("failed to sub days"); + let formatted = format_duration(date, false); + + assert_eq!(formatted, "2 days ago"); + } + + #[test] + fn renders_yesterday() { + let date = Utc::now() + .checked_sub_days(Days::new(1)) + .expect("failed to sub days"); + let formatted = format_duration(date, false); + + assert_eq!(formatted, "Yesterday"); + } + + #[test] + fn renders_hours() { + let next_hour = Utc::now().hour() - 8; + let date = Utc::now().with_hour(next_hour).expect("failed to set hour"); + let formatted = format_duration(date, false); + + assert_eq!(formatted, "8 hours ago"); + } + + #[test] + fn renders_minutes() { + let next_min = Utc::now().minute() - 30; + let date = Utc::now().with_minute(next_min).expect("failed to set min"); + let formatted = format_duration(date, false); + + assert_eq!(formatted, "30 minutes ago"); + } + + #[test] + fn renders_just_now() { + let formatted = format_duration(Utc::now(), false); + + assert_eq!(formatted, "Just now"); + } } From 69c0de335037d17a1172500ca5219c856b999f47 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Thu, 3 Oct 2024 13:04:15 -0300 Subject: [PATCH 4/9] chore: bump fluvio-extension-common --- crates/fluvio-extension-common/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fluvio-extension-common/Cargo.toml b/crates/fluvio-extension-common/Cargo.toml index a59dc889d1..2c05a6769d 100644 --- a/crates/fluvio-extension-common/Cargo.toml +++ b/crates/fluvio-extension-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fluvio-extension-common" -version = "0.14.2" +version = "0.14.3" edition = "2021" authors = ["Fluvio Contributors "] description = "Fluvio extension common" From 2ecee7a5148aa3733853f23ce2cb19196fac4e8a Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Thu, 3 Oct 2024 17:17:20 -0300 Subject: [PATCH 5/9] fix: use static date for tests --- Cargo.lock | 2 +- .../src/client/hub/smartmodule/list.rs | 7 +- .../src/common/time.rs | 111 +++++++++++------- crates/fluvio-hub-util/src/cmd/list.rs | 7 +- 4 files changed, 82 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87538156e7..af29c37625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2765,7 +2765,7 @@ dependencies = [ [[package]] name = "fluvio-extension-common" -version = "0.14.2" +version = "0.14.3" dependencies = [ "anyhow", "async-trait", diff --git a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs index 515fb50edc..b1dc00cf28 100644 --- a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs +++ b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs @@ -49,12 +49,12 @@ mod output { //! Format SmartModules response based on output type use comfy_table::{Cell, Row}; use comfy_table::CellAlignment; - use fluvio_extension_common::time::format_duration; use tracing::debug; use serde::Serialize; use anyhow::Result; use fluvio_extension_common::output::OutputType; + use fluvio_extension_common::time::TimeElapsedFormatter; use fluvio_extension_common::Terminal; use fluvio_extension_common::output::TableOutputHandler; use fluvio_extension_common::t_println; @@ -116,7 +116,10 @@ mod output { Cell::new(&e.visibility).set_alignment(CellAlignment::Left), Cell::new( e.published_at() - .map(|date| format_duration(date, self.exact_time)) + .map(|date| { + TimeElapsedFormatter::default() + .time_since_str(date, self.exact_time) + }) .unwrap_or(String::from("N/A")), ), ]) diff --git a/crates/fluvio-extension-common/src/common/time.rs b/crates/fluvio-extension-common/src/common/time.rs index 2d86bd96c4..3de5809f5e 100644 --- a/crates/fluvio-extension-common/src/common/time.rs +++ b/crates/fluvio-extension-common/src/common/time.rs @@ -3,107 +3,138 @@ use chrono::{DateTime, Utc}; const SIMPLE_DATE_FORMAT: &str = "%Y/%m/%d"; const EXACT_FORMAT: &str = "%Y-%m-%d %H:%M:%S %Z"; -pub fn format_duration(date: DateTime, exact: bool) -> String { - let duration = Utc::now().signed_duration_since(date); +pub struct TimeElapsedFormatter { + bot: DateTime, +} - if exact { - return date.format(EXACT_FORMAT).to_string(); +impl Default for TimeElapsedFormatter { + fn default() -> Self { + Self { bot: Utc::now() } } +} - if duration.num_weeks() >= 1 { - return date.format(SIMPLE_DATE_FORMAT).to_string(); +impl TimeElapsedFormatter { + pub fn new(bot: DateTime) -> Self { + Self { bot } } - if duration.num_days() >= 2 { - return format!("{} days ago", duration.num_days()); - } + pub fn time_since_str(&self, date: DateTime, exact: bool) -> String { + let duration = self.bot.signed_duration_since(date); - if duration.num_days() == 1 { - return String::from("Yesterday"); - } + if exact { + return date.format(EXACT_FORMAT).to_string(); + } - if duration.num_hours() >= 1 && duration.num_hours() < 24 { - return format!("{} hours ago", duration.num_hours()); - } + if duration.num_weeks() >= 1 { + return date.format(SIMPLE_DATE_FORMAT).to_string(); + } - if duration.num_minutes() >= 1 && duration.num_minutes() < 59 { - return format!("{} minutes ago", duration.num_minutes()); - } + if duration.num_days() >= 2 { + return format!("{} days ago", duration.num_days()); + } - if duration.num_minutes() < 1 { - return String::from("Just now"); - } + if duration.num_days() == 1 { + return String::from("Yesterday"); + } - date.format(SIMPLE_DATE_FORMAT).to_string() + if duration.num_hours() >= 1 && duration.num_hours() < 24 { + return format!("{} hours ago", duration.num_hours()); + } + + if duration.num_minutes() >= 1 && duration.num_minutes() < 59 { + return format!("{} minutes ago", duration.num_minutes()); + } + + if duration.num_minutes() < 1 { + return String::from("Just now"); + } + + date.format(SIMPLE_DATE_FORMAT).to_string() + } } #[cfg(test)] mod tests { - use chrono::{Days, Timelike, Utc}; + use chrono::{DateTime, Days, TimeZone, Timelike, Utc}; - use crate::time::{EXACT_FORMAT, SIMPLE_DATE_FORMAT}; + use crate::time::{TimeElapsedFormatter, EXACT_FORMAT, SIMPLE_DATE_FORMAT}; - use super::format_duration; + fn december_17_1989_10_30_00() -> DateTime { + Utc.with_ymd_and_hms(1989, 12, 17, 10, 30, 0) + .unwrap() + .to_utc() + } + + fn make_fixed_time_elapsed_fmtr() -> TimeElapsedFormatter { + TimeElapsedFormatter::new(december_17_1989_10_30_00()) + } #[test] fn determines_exact_date() { - let date = Utc::now(); - let formatted = format_duration(date, true); + let next_min = december_17_1989_10_30_00().minute() - 30; + let date = december_17_1989_10_30_00() + .with_minute(next_min) + .expect("failed to set min"); + let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, true); assert_eq!(formatted, date.format(EXACT_FORMAT).to_string()); } #[test] fn simple_date_format_for_exceeding_a_week() { - let date = Utc::now() + let date = december_17_1989_10_30_00() .checked_sub_days(Days::new(7)) .expect("failed to sub days"); - let formatted = format_duration(date, false); + let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, false); assert_eq!(formatted, date.format(SIMPLE_DATE_FORMAT).to_string()); } #[test] fn renders_days_passed() { - let date = Utc::now() + let date = december_17_1989_10_30_00() .checked_sub_days(Days::new(2)) .expect("failed to sub days"); - let formatted = format_duration(date, false); + let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, false); assert_eq!(formatted, "2 days ago"); } #[test] fn renders_yesterday() { - let date = Utc::now() + let date = december_17_1989_10_30_00() .checked_sub_days(Days::new(1)) .expect("failed to sub days"); - let formatted = format_duration(date, false); + let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, false); assert_eq!(formatted, "Yesterday"); } #[test] fn renders_hours() { - let next_hour = Utc::now().hour() - 8; - let date = Utc::now().with_hour(next_hour).expect("failed to set hour"); - let formatted = format_duration(date, false); + let next_hour = december_17_1989_10_30_00().hour() - 8; + let date = december_17_1989_10_30_00() + .with_hour(next_hour) + .expect("failed to set hour"); + let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, false); assert_eq!(formatted, "8 hours ago"); } #[test] fn renders_minutes() { - let next_min = Utc::now().minute() - 30; - let date = Utc::now().with_minute(next_min).expect("failed to set min"); - let formatted = format_duration(date, false); + let next_min = december_17_1989_10_30_00().minute() - 30; + let date = december_17_1989_10_30_00() + .with_minute(next_min) + .expect("failed to set min"); + let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, false); assert_eq!(formatted, "30 minutes ago"); } #[test] fn renders_just_now() { - let formatted = format_duration(Utc::now(), false); + let formatted = TimeElapsedFormatter::default().time_since_str(Utc::now(), false); assert_eq!(formatted, "Just now"); } diff --git a/crates/fluvio-hub-util/src/cmd/list.rs b/crates/fluvio-hub-util/src/cmd/list.rs index 3ff831344f..363a676576 100644 --- a/crates/fluvio-hub-util/src/cmd/list.rs +++ b/crates/fluvio-hub-util/src/cmd/list.rs @@ -46,7 +46,7 @@ mod output { use anyhow::Result; use fluvio_extension_common::output::OutputType; - use fluvio_extension_common::time::format_duration; + use fluvio_extension_common::time::TimeElapsedFormatter; use fluvio_extension_common::Terminal; use fluvio_extension_common::output::TableOutputHandler; use fluvio_extension_common::t_println; @@ -109,7 +109,10 @@ mod output { Cell::new(&e.visibility).set_alignment(CellAlignment::Left), Cell::new( e.published_at() - .map(|date| format_duration(date, self.exact_time)) + .map(|date| { + TimeElapsedFormatter::default() + .time_since_str(date, self.exact_time) + }) .unwrap_or(String::from("N/A")), ), ]) From ba6348ad15e02909fbd3aa381f87f2df0ce26413 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Thu, 3 Oct 2024 21:41:01 -0300 Subject: [PATCH 6/9] feat: use `Published` instead of `Released` --- crates/fluvio-cli/src/client/hub/smartmodule/list.rs | 2 +- crates/fluvio-hub-util/src/cmd/list.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs index b1dc00cf28..f385a5c56d 100644 --- a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs +++ b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs @@ -98,7 +98,7 @@ mod output { impl TableOutputHandler for ListSmartModules { /// table header implementation fn header(&self) -> Row { - Row::from(["SmartModule", "Visibility", "Released"]) + Row::from(["SmartModule", "Visibility", "Published"]) } /// return errors in string format diff --git a/crates/fluvio-hub-util/src/cmd/list.rs b/crates/fluvio-hub-util/src/cmd/list.rs index 363a676576..de169543bd 100644 --- a/crates/fluvio-hub-util/src/cmd/list.rs +++ b/crates/fluvio-hub-util/src/cmd/list.rs @@ -91,7 +91,7 @@ mod output { impl TableOutputHandler for ListConnectors { /// table header implementation fn header(&self) -> Row { - Row::from(["Connector", "Visibility", "Released"]) + Row::from(["Connector", "Visibility", "Published"]) } /// return errors in string format From d6e8987e7e528b3fb4d604fafb53b6d669ba7077 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Thu, 3 Oct 2024 21:44:09 -0300 Subject: [PATCH 7/9] fix: update docs in cli --- crates/fluvio-cli/src/client/hub/smartmodule/list.rs | 2 +- crates/fluvio-hub-util/src/cmd/list.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs index f385a5c56d..5fdb05e0fa 100644 --- a/crates/fluvio-cli/src/client/hub/smartmodule/list.rs +++ b/crates/fluvio-cli/src/client/hub/smartmodule/list.rs @@ -16,7 +16,7 @@ pub struct SmartModuleHubListOpts { #[clap(flatten)] output: OutputFormat, - /// Show exact time instead of relative time for `Released` column + /// Show exact time instead of relative time for `Published` column #[arg(long, default_value = "false")] exact_time: bool, diff --git a/crates/fluvio-hub-util/src/cmd/list.rs b/crates/fluvio-hub-util/src/cmd/list.rs index de169543bd..d06c2e96e1 100644 --- a/crates/fluvio-hub-util/src/cmd/list.rs +++ b/crates/fluvio-hub-util/src/cmd/list.rs @@ -16,7 +16,7 @@ pub struct ConnectorHubListOpts { #[clap(flatten)] output: OutputFormat, - /// Show exact time instead of relative time for `Released` column + /// Show exact time instead of relative time for `Published` column #[arg(long, default_value = "false")] exact_time: bool, From 0a4d54ac3df22a05cc769e0504f477f0d3e3a2a3 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Thu, 3 Oct 2024 21:46:29 -0300 Subject: [PATCH 8/9] fix: update tests to use str --- crates/fluvio-extension-common/src/common/time.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fluvio-extension-common/src/common/time.rs b/crates/fluvio-extension-common/src/common/time.rs index 3de5809f5e..2938405964 100644 --- a/crates/fluvio-extension-common/src/common/time.rs +++ b/crates/fluvio-extension-common/src/common/time.rs @@ -57,7 +57,7 @@ impl TimeElapsedFormatter { mod tests { use chrono::{DateTime, Days, TimeZone, Timelike, Utc}; - use crate::time::{TimeElapsedFormatter, EXACT_FORMAT, SIMPLE_DATE_FORMAT}; + use crate::time::TimeElapsedFormatter; fn december_17_1989_10_30_00() -> DateTime { Utc.with_ymd_and_hms(1989, 12, 17, 10, 30, 0) @@ -77,7 +77,7 @@ mod tests { .expect("failed to set min"); let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, true); - assert_eq!(formatted, date.format(EXACT_FORMAT).to_string()); + assert_eq!(formatted, "1989-12-17 10:00:00 UTC"); } #[test] @@ -87,7 +87,7 @@ mod tests { .expect("failed to sub days"); let formatted = make_fixed_time_elapsed_fmtr().time_since_str(date, false); - assert_eq!(formatted, date.format(SIMPLE_DATE_FORMAT).to_string()); + assert_eq!(formatted, "1989/12/10"); } #[test] From e96128c58f5e514fae653130fb9eb4c5486f06ad Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Fri, 4 Oct 2024 12:56:26 -0300 Subject: [PATCH 9/9] chore: update docs --- .../fluvio-extension-common/src/common/time.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/crates/fluvio-extension-common/src/common/time.rs b/crates/fluvio-extension-common/src/common/time.rs index 2938405964..fa71f8d34f 100644 --- a/crates/fluvio-extension-common/src/common/time.rs +++ b/crates/fluvio-extension-common/src/common/time.rs @@ -18,6 +18,23 @@ impl TimeElapsedFormatter { Self { bot } } + /// Returns a string representation of the time elapsed between the- + /// `bot` (beginning of time) and the `date` provided. + /// + /// If `exact` is true, the exact date and time will be returned + /// instead of the free-form expression. + /// + /// Expressions supported are: + /// + /// - `Just now` + /// - `X minutes ago` + /// - `X hours ago` + /// - `Yesterday` + /// - `X days ago` + /// - `X weeks ago` + /// - `X months ago` + /// - `X years ago` + /// - `YYYY/MM/DD` (if the date is more 2 a years ago) pub fn time_since_str(&self, date: DateTime, exact: bool) -> String { let duration = self.bot.signed_duration_since(date);