Fix chat timestamps

This commit is contained in:
Joseph T. Lyons 2024-01-21 15:12:04 -05:00
parent 6c82380232
commit 4580172edb

View file

@ -325,8 +325,6 @@ impl ChatPanel {
Self::render_markdown_with_mentions(&self.languages, self.client.id(), &message) Self::render_markdown_with_mentions(&self.languages, self.client.id(), &message)
}); });
let now = OffsetDateTime::now_utc();
let belongs_to_user = Some(message.sender.id) == self.client.user_id(); let belongs_to_user = Some(message.sender.id) == self.client.user_id();
let message_id_to_remove = if let (ChannelMessageId::Saved(id), true) = let message_id_to_remove = if let (ChannelMessageId::Saved(id), true) =
(message.id, belongs_to_user || is_admin) (message.id, belongs_to_user || is_admin)
@ -362,8 +360,8 @@ impl ChatPanel {
) )
.child( .child(
Label::new(format_timestamp( Label::new(format_timestamp(
OffsetDateTime::now_utc(),
message.timestamp, message.timestamp,
now,
self.local_timezone, self.local_timezone,
)) ))
.size(LabelSize::Small) .size(LabelSize::Small)
@ -669,28 +667,44 @@ impl Panel for ChatPanel {
impl EventEmitter<PanelEvent> for ChatPanel {} impl EventEmitter<PanelEvent> for ChatPanel {}
fn format_timestamp( fn format_timestamp(
mut timestamp: OffsetDateTime, reference: OffsetDateTime,
mut now: OffsetDateTime, timestamp: OffsetDateTime,
local_timezone: UtcOffset, timezone: UtcOffset,
) -> String { ) -> String {
timestamp = timestamp.to_offset(local_timezone); let timestamp_local = timestamp.to_offset(timezone);
now = now.to_offset(local_timezone); let timestamp_local_hour = timestamp_local.hour();
let today = now.date(); let hour_12 = match timestamp_local_hour {
let date = timestamp.date(); 0 => 12, // Midnight
let mut hour = timestamp.hour(); 13..=23 => timestamp_local_hour - 12, // PM hours
let mut part = "am"; _ => timestamp_local_hour, // AM hours
if hour > 12 { };
hour -= 12; let meridiem = if timestamp_local_hour >= 12 {
part = "pm"; "pm"
}
if date == today {
format!("{:02}:{:02}{}", hour, timestamp.minute(), part)
} else if date.next_day() == Some(today) {
format!("yesterday at {:02}:{:02}{}", hour, timestamp.minute(), part)
} else { } else {
format!("{:02}/{}/{}", date.month() as u32, date.day(), date.year()) "am"
};
let timestamp_local_minute = timestamp_local.minute();
let formatted_time = format!("{:02}:{:02} {}", hour_12, timestamp_local_minute, meridiem);
let reference_local = reference.to_offset(timezone);
let reference_local_date = reference_local.date();
let timestamp_local_date = timestamp_local.date();
if timestamp_local_date == reference_local_date {
return formatted_time;
} }
if reference_local_date.previous_day() == Some(timestamp_local_date) {
return format!("yesterday at {}", formatted_time);
}
format!(
"{:02}/{:02}/{}",
timestamp_local_date.month() as u32,
timestamp_local_date.day(),
timestamp_local_date.year()
)
} }
#[cfg(test)] #[cfg(test)]
@ -699,6 +713,7 @@ mod tests {
use gpui::HighlightStyle; use gpui::HighlightStyle;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use rich_text::Highlight; use rich_text::Highlight;
use time::{Date, OffsetDateTime, Time, UtcOffset};
use util::test::marked_text_ranges; use util::test::marked_text_ranges;
#[gpui::test] #[gpui::test]
@ -747,4 +762,99 @@ mod tests {
] ]
); );
} }
#[test]
fn test_format_today() {
let reference = create_offset_datetime(1990, 4, 12, 16, 45, 0);
let timestamp = create_offset_datetime(1990, 4, 12, 15, 30, 0);
assert_eq!(
format_timestamp(reference, timestamp, test_timezone()),
"03:30 pm"
);
}
#[test]
fn test_format_yesterday() {
let reference = create_offset_datetime(1990, 4, 12, 10, 30, 0);
let timestamp = create_offset_datetime(1990, 4, 11, 9, 0, 0);
assert_eq!(
format_timestamp(reference, timestamp, test_timezone()),
"yesterday at 09:00 am"
);
}
#[test]
fn test_format_yesterday_less_than_24_hours_ago() {
let reference = create_offset_datetime(1990, 4, 12, 19, 59, 0);
let timestamp = create_offset_datetime(1990, 4, 11, 20, 0, 0);
assert_eq!(
format_timestamp(reference, timestamp, test_timezone()),
"yesterday at 08:00 pm"
);
}
#[test]
fn test_format_yesterday_more_than_24_hours_ago() {
let reference = create_offset_datetime(1990, 4, 12, 19, 59, 0);
let timestamp = create_offset_datetime(1990, 4, 11, 18, 0, 0);
assert_eq!(
format_timestamp(reference, timestamp, test_timezone()),
"yesterday at 06:00 pm"
);
}
#[test]
fn test_format_yesterday_over_midnight() {
let reference = create_offset_datetime(1990, 4, 12, 0, 5, 0);
let timestamp = create_offset_datetime(1990, 4, 11, 23, 55, 0);
assert_eq!(
format_timestamp(reference, timestamp, test_timezone()),
"yesterday at 11:55 pm"
);
}
#[test]
fn test_format_yesterday_over_month() {
let reference = create_offset_datetime(1990, 4, 2, 9, 0, 0);
let timestamp = create_offset_datetime(1990, 4, 1, 20, 0, 0);
assert_eq!(
format_timestamp(reference, timestamp, test_timezone()),
"yesterday at 08:00 pm"
);
}
#[test]
fn test_format_before_yesterday() {
let reference = create_offset_datetime(1990, 4, 12, 10, 30, 0);
let timestamp = create_offset_datetime(1990, 4, 10, 20, 20, 0);
assert_eq!(
format_timestamp(reference, timestamp, test_timezone()),
"04/10/1990"
);
}
fn test_timezone() -> UtcOffset {
UtcOffset::from_hms(0, 0, 0).expect("Valid timezone offset")
}
fn create_offset_datetime(
year: i32,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
) -> OffsetDateTime {
let date =
Date::from_calendar_date(year, time::Month::try_from(month).unwrap(), day).unwrap();
let time = Time::from_hms(hour, minute, second).unwrap();
date.with_time(time).assume_utc() // Assume UTC for simplicity
}
} }