From 8e24b568abaafede46ccd4082537c33e6e68364d Mon Sep 17 00:00:00 2001 From: murgeljm Date: Thu, 14 Mar 2024 10:13:59 +0100 Subject: [PATCH] Add unix epoch as timezone option (#5450) * Closes #4866 ### What Added a unix epoch timestamp display option, as mentioned in issue [4866](https://github.com/rerun-io/rerun/issues/4866) Screenshot 2024-03-10 at 23 25 16-min Not quite sure how compact time display should be handled: ```diff /// Useful when showing dates/times on a timeline /// and you want it compact. /// /// Shows dates when zoomed out, shows times when zoomed in, /// shows relative millisecond when really zoomed in. pub fn format_time_compact(&self, time_zone_for_timestamps: TimeZone) -> String { ... if let Some(datetime) = self.to_datetime() { let is_whole_minute = ns % 60_000_000_000 == 0; let time_format = if self.is_exactly_midnight() { "[year]-[month]-[day]" } else if is_whole_minute { "[hour]:[minute]" } else { - "[hour]:[minute]:[second]" + Self::get_time_prefix(&time_zone_for_timestamps) }; let parsed_format = time::format_description::parse(time_format).unwrap(); return Self::time_string(datetime, &parsed_format, time_zone_for_timestamps); } ... } ``` Should the `[hour]:[minute]` be changed as well when unix timestamp is chosen? ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5450/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5450/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5450/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5450) - [Docs preview](https://rerun.io/preview/7e0f542930b6d1279c55190e3f375f0dcf2b2603/docs) - [Examples preview](https://rerun.io/preview/7e0f542930b6d1279c55190e3f375f0dcf2b2603/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: mm Co-authored-by: Emil Ernerfeldt --- crates/re_log_types/src/time.rs | 39 ++++++++++++++++++++++----- crates/re_viewer/src/ui/rerun_menu.rs | 10 +++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/re_log_types/src/time.rs b/crates/re_log_types/src/time.rs index caebf376b84b..c7fb28719cf8 100644 --- a/crates/re_log_types/src/time.rs +++ b/crates/re_log_types/src/time.rs @@ -6,6 +6,9 @@ use time::{format_description::FormatItem, OffsetDateTime, UtcOffset}; pub enum TimeZone { Local, Utc, + + /// Seconds since unix epoch + UnixEpoch, } /// A date-time represented as nanoseconds since unix epoch @@ -91,6 +94,7 @@ impl Time { TimeZone::Utc => { format!("{}Z", datetime.format(&parsed_format).unwrap()) } + TimeZone::UnixEpoch => datetime.format(&parsed_format).unwrap(), } } @@ -101,19 +105,23 @@ impl Time { if let Some(datetime) = self.to_datetime() { let is_whole_second = nanos_since_epoch % 1_000_000_000 == 0; let is_whole_millisecond = nanos_since_epoch % 1_000_000 == 0; + let prefix = match time_zone_for_timestamps { + TimeZone::UnixEpoch => "[unix_timestamp]", + TimeZone::Utc | TimeZone::Local => "[hour]:[minute]:[second]", + }; let time_format = if is_whole_second { - "[hour]:[minute]:[second]" + prefix.to_owned() } else if is_whole_millisecond { - "[hour]:[minute]:[second].[subsecond digits:3]" + format!("{prefix}.[subsecond digits:3]") } else { - "[hour]:[minute]:[second].[subsecond digits:6]" + format!("{prefix}.[subsecond digits:6]") }; let date_is_today = datetime.date() == OffsetDateTime::now_utc().date(); let date_format = format!("[year]-[month]-[day] {time_format}"); let parsed_format = if date_is_today { - time::format_description::parse(time_format).unwrap() + time::format_description::parse(&time_format).unwrap() } else { time::format_description::parse(&date_format).unwrap() }; @@ -147,9 +155,15 @@ impl Time { let time_format = if self.is_exactly_midnight() { "[year]-[month]-[day]" } else if is_whole_minute { - "[hour]:[minute]" + match time_zone_for_timestamps { + TimeZone::UnixEpoch => "[unix_timestamp]", + TimeZone::Utc | TimeZone::Local => "[hour]:[minute]", + } } else { - "[hour]:[minute]:[second]" + match time_zone_for_timestamps { + TimeZone::UnixEpoch => "[unix_timestamp]", + TimeZone::Utc | TimeZone::Local => "[hour]:[minute]:[second]", + } }; let parsed_format = time::format_description::parse(time_format).unwrap(); @@ -302,6 +316,19 @@ mod tests { &Time::from_us_since_epoch(69_900).format(TimeZone::Local), "+0.070s" ); + + assert_eq!( + &Time::from_us_since_epoch(42_000_000).format(TimeZone::UnixEpoch), + "+42s" + ); + assert_eq!( + &Time::from_us_since_epoch(69_000).format(TimeZone::UnixEpoch), + "+0.069s" + ); + assert_eq!( + &Time::from_us_since_epoch(69_900).format(TimeZone::UnixEpoch), + "+0.070s" + ); } #[test] diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index b9288b6d22dd..aa0a945b6e57 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -319,12 +319,22 @@ fn options_menu_ui( ui.horizontal(|ui| { ui.label("Timezone:"); + }); + ui.horizontal(|ui| { re_ui .radio_value(ui, &mut app_options.time_zone, TimeZone::Utc, "UTC") .on_hover_text("Display timestamps in UTC"); re_ui .radio_value(ui, &mut app_options.time_zone, TimeZone::Local, "Local") .on_hover_text("Display timestamps in the local timezone"); + re_ui + .radio_value( + ui, + &mut app_options.time_zone, + TimeZone::UnixEpoch, + "Unix Epoch", + ) + .on_hover_text("Display timestamps in seconds since unix epoch"); }); {