Consolidate and extract timestamp display functions in one file

The functionality for absolute timestamps was duplicated. A
function for displaying relative timestamps will be needed in
the next commit.
This commit is contained in:
Ilya Grigoriev 2023-01-06 19:43:46 -08:00
parent d5430a9258
commit c5563115a4
2 changed files with 28 additions and 40 deletions

View file

@ -22,12 +22,11 @@ use std::sync::Mutex;
use std::time::Instant; use std::time::Instant;
use std::{fs, io}; use std::{fs, io};
use chrono::{FixedOffset, LocalResult, TimeZone, Utc};
use clap::builder::NonEmptyStringValueParser; use clap::builder::NonEmptyStringValueParser;
use clap::{ArgGroup, ArgMatches, CommandFactory, FromArgMatches, Subcommand}; use clap::{ArgGroup, ArgMatches, CommandFactory, FromArgMatches, Subcommand};
use config::Source; use config::Source;
use itertools::Itertools; use itertools::Itertools;
use jujutsu_lib::backend::{CommitId, ObjectId, Timestamp, TreeValue}; use jujutsu_lib::backend::{CommitId, ObjectId, TreeValue};
use jujutsu_lib::commit::Commit; use jujutsu_lib::commit::Commit;
use jujutsu_lib::dag_walk::topo_order_reverse; use jujutsu_lib::dag_walk::topo_order_reverse;
use jujutsu_lib::git::{GitFetchError, GitRefUpdate}; use jujutsu_lib::git::{GitFetchError, GitRefUpdate};
@ -61,7 +60,7 @@ use crate::diff_util::{self, DiffFormat, DiffFormatArgs};
use crate::formatter::{Formatter, PlainTextFormatter}; use crate::formatter::{Formatter, PlainTextFormatter};
use crate::graphlog::{AsciiGraphDrawer, Edge}; use crate::graphlog::{AsciiGraphDrawer, Edge};
use crate::progress::Progress; use crate::progress::Progress;
use crate::template_parser::TemplateParser; use crate::template_parser::{format_absolute_timestamp, TemplateParser};
use crate::templater::Template; use crate::templater::Template;
use crate::ui::Ui; use crate::ui::Ui;
@ -3343,26 +3342,6 @@ fn cmd_debug(
Ok(()) Ok(())
} }
// TODO: Move this somewhere where it can be reused by
// `template_parser::SignatureTimestamp`.
fn format_timestamp(timestamp: &Timestamp) -> String {
let utc = match Utc.timestamp_opt(
timestamp.timestamp.0.div_euclid(1000),
(timestamp.timestamp.0.rem_euclid(1000)) as u32 * 1000000,
) {
LocalResult::None => {
return "<out-of-range date>".to_string();
}
LocalResult::Single(x) => x,
LocalResult::Ambiguous(y, _z) => y,
};
let datetime = utc.with_timezone(
&FixedOffset::east_opt(timestamp.tz_offset * 60)
.unwrap_or_else(|| FixedOffset::east_opt(0).unwrap()),
);
datetime.format("%Y-%m-%d %H:%M:%S.%3f %:z").to_string()
}
fn cmd_op_log( fn cmd_op_log(
ui: &mut Ui, ui: &mut Ui,
command: &CommandHelper, command: &CommandHelper,
@ -3389,8 +3368,8 @@ fn cmd_op_log(
formatter.with_label("time", |formatter| { formatter.with_label("time", |formatter| {
formatter.write_str(&format!( formatter.write_str(&format!(
"{} - {}", "{} - {}",
format_timestamp(&metadata.start_time), format_absolute_timestamp(&metadata.start_time),
format_timestamp(&metadata.end_time) format_absolute_timestamp(&metadata.end_time)
)) ))
})?; })?;
formatter.write_str("\n")?; formatter.write_str("\n")?;

View file

@ -95,6 +95,7 @@ impl TemplateProperty<Signature, String> for SignatureEmail {
} }
} }
// TODO: Find a better place for the timestamp functions, e.g. their own module
fn datetime_from_timestamp(context: &Timestamp) -> Option<DateTime<FixedOffset>> { fn datetime_from_timestamp(context: &Timestamp) -> Option<DateTime<FixedOffset>> {
let utc = match Utc.timestamp_opt( let utc = match Utc.timestamp_opt(
context.timestamp.0.div_euclid(1000), context.timestamp.0.div_euclid(1000),
@ -115,11 +116,15 @@ fn datetime_from_timestamp(context: &Timestamp) -> Option<DateTime<FixedOffset>>
) )
} }
struct RelativeTimestampString; pub fn format_absolute_timestamp(timestamp: &Timestamp) -> String {
match datetime_from_timestamp(timestamp) {
Some(datetime) => datetime.format("%Y-%m-%d %H:%M:%S.%3f %:z").to_string(),
None => "<out-of-range date>".to_string(),
}
}
impl TemplateProperty<Timestamp, String> for RelativeTimestampString { pub fn format_timestamp_relative_to_now(timestamp: &Timestamp) -> String {
fn extract(&self, context: &Timestamp) -> String { datetime_from_timestamp(timestamp)
datetime_from_timestamp(context)
.and_then(|datetime| { .and_then(|datetime| {
let now = chrono::Local::now(); let now = chrono::Local::now();
@ -131,6 +136,13 @@ impl TemplateProperty<Timestamp, String> for RelativeTimestampString {
}) })
.unwrap_or_else(|| "<out-of-range date>".to_string()) .unwrap_or_else(|| "<out-of-range date>".to_string())
} }
struct RelativeTimestampString;
impl TemplateProperty<Timestamp, String> for RelativeTimestampString {
fn extract(&self, context: &Timestamp) -> String {
format_timestamp_relative_to_now(context)
}
} }
fn parse_method_chain<'a, I: 'a>( fn parse_method_chain<'a, I: 'a>(
@ -324,10 +336,7 @@ fn coerce_to_string<'a, I: 'a>(
)), )),
Property::Timestamp(property) => Box::new(TemplateFunction::new( Property::Timestamp(property) => Box::new(TemplateFunction::new(
property, property,
Box::new(|timestamp| match datetime_from_timestamp(&timestamp) { Box::new(|timestamp| format_absolute_timestamp(&timestamp)),
Some(datetime) => datetime.format("%Y-%m-%d %H:%M:%S.%3f %:z").to_string(),
None => "<out-of-range date>".to_string(),
}),
)), )),
} }
} }