use comfy_table::{presets::UTF8_FULL_CONDENSED, Table, ContentArrangement};
pub fn print_table_or_json<T: serde::Serialize>(
headers: &[&str],
rows: Vec<Vec<String>>,
data: &T,
json: bool,
) {
if json {
println!(
"{}",
serde_json::to_string_pretty(data).expect("json serialization failed")
);
return;
}
if rows.is_empty() {
println!("No results.");
return;
}
let mut table = Table::new();
table.load_preset(UTF8_FULL_CONDENSED);
table.set_content_arrangement(ContentArrangement::Dynamic);
table.set_header(headers);
for row in rows {
table.add_row(row);
}
println!("{table}");
}
pub fn print_kv_or_json<T: serde::Serialize>(
pairs: &[(&str, &str)],
data: &T,
json: bool,
) {
if json {
println!(
"{}",
serde_json::to_string_pretty(data).expect("json serialization failed")
);
return;
}
let max_key_len = pairs.iter().map(|(k, _)| k.len()).max().unwrap_or(0);
for (key, value) in pairs {
println!(
" {:<width$} {}",
colored::Colorize::bold(key.to_owned()),
value,
width = max_key_len
);
}
}
pub fn format_timestamp_ms(ts_ms: i64) -> String {
let secs = ts_ms / 1000;
const SECS_PER_MIN: i64 = 60;
const SECS_PER_HOUR: i64 = 3600;
const SECS_PER_DAY: i64 = 86400;
let mut days = secs / SECS_PER_DAY;
let day_secs = secs % SECS_PER_DAY;
let hour = day_secs / SECS_PER_HOUR;
let min = (day_secs % SECS_PER_HOUR) / SECS_PER_MIN;
let mut year = 1970i64;
loop {
let days_in_year = if is_leap(year) { 366 } else { 365 };
if days < days_in_year {
break;
}
days -= days_in_year;
year += 1;
}
let month_days: &[i64] = if is_leap(year) {
&[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
} else {
&[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
};
let mut month = 0usize;
for &md in month_days {
if days < md {
break;
}
days -= md;
month += 1;
}
format!(
"{:04}-{:02}-{:02} {:02}:{:02} UTC",
year,
month + 1,
days + 1,
hour,
min,
)
}
fn is_leap(y: i64) -> bool {
y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)
}
pub fn print_success(message: &str, hint: Option<&str>) {
println!("{} {message}", colored::Colorize::green("ok:"));
if let Some(hint) = hint {
println!("\n {}: {hint}", colored::Colorize::cyan("next"));
}
}