Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions crates/openshell-cli/src/commands/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,22 +140,6 @@ pub fn format_timestamp(d: Duration) -> String {
format!("[{secs:.1}s]")
}

/// Format a millisecond timestamp into a readable string.
pub fn format_timestamp_ms(ms: i64) -> String {
if ms <= 0 {
return "-".to_string();
}
let secs = ms / 1000;
let mins = (secs / 60) % 60;
let hours = (secs / 3600) % 24;
let days = secs / 86400;
if days > 0 {
format!("{days}d {hours:02}:{mins:02}")
} else {
format!("{hours:02}:{mins:02}")
}
}

pub fn truncate_status_field(value: &str, max_chars: usize) -> String {
if value.is_empty() {
return "-".to_string();
Expand Down Expand Up @@ -1072,6 +1056,20 @@ pub fn scrub_git_env(command: &mut Command) -> &mut Command {
mod tests {
use super::*;

#[test]
fn optional_epoch_ms_renders_absolute_date_not_day_count() {
// Rule-history entries carry an absolute `google.protobuf.Timestamp`
// (epoch ms), so the rendered string must be a readable wall-clock
// date, never a days-since-epoch count. 1_700_000_000_000 ms is
// 2023-11-14T22:13:20Z.
assert_eq!(
format_optional_epoch_ms(1_700_000_000_000),
"2023-11-14 22:13:20"
);
// A missing timestamp (proto default -> 0 ms) renders as a placeholder.
assert_eq!(format_optional_epoch_ms(0), "-");
}

#[test]
fn parse_duration_to_ms_parses_supported_units() {
assert_eq!(parse_duration_to_ms("30s").expect("parse"), 30_000);
Expand Down
10 changes: 5 additions & 5 deletions crates/openshell-cli/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ pub use crate::commands::common::{
};
use crate::commands::common::{
ProvisioningDisplay, ProvisioningStep, confirm_global_setting_delete,
confirm_global_setting_takeover, format_epoch_ms, format_setting_value, format_timestamp,
format_timestamp_ms, handle_platform_progress_event, is_provisioning_progress_event,
non_empty_or, parse_cli_setting_value, parse_duration_to_ms, phase_name,
print_policy_merge_warnings, print_sandbox_header, print_sandbox_policy,
confirm_global_setting_takeover, format_epoch_ms, format_optional_epoch_ms,
format_setting_value, format_timestamp, handle_platform_progress_event,
is_provisioning_progress_event, non_empty_or, parse_cli_setting_value, parse_duration_to_ms,
phase_name, print_policy_merge_warnings, print_sandbox_header, print_sandbox_policy,
provisioning_timeout_message, ready_false_condition_message, scrub_git_env, short_hash,
truncate_status_field,
};
Expand Down Expand Up @@ -6588,7 +6588,7 @@ pub async fn sandbox_draft_history(

println!(
" {} {} [{}] {}",
format_timestamp_ms(proto_timestamp_ms(entry.event_time.as_ref())).dimmed(),
format_optional_epoch_ms(proto_timestamp_ms(entry.event_time.as_ref())).dimmed(),
event_colored,
entry.chunk_id.get(..8).unwrap_or(&entry.chunk_id),
entry.description,
Expand Down
Loading