vtcode_commons/
message_timestamp.rs1use chrono::{DateTime, Local};
9
10pub fn format_message_time(now: DateTime<Local>) -> String {
15 now.format("%-I:%M %p").to_string()
16}
17
18pub fn message_timestamp_footer(now: DateTime<Local>) -> String {
23 format!("· {}", format_message_time(now))
24}
25
26pub fn current_message_timestamp_footer() -> String {
28 message_timestamp_footer(Local::now())
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34 use chrono::TimeZone;
35
36 fn local_at(hour: u32, minute: u32) -> DateTime<Local> {
37 Local
38 .with_ymd_and_hms(2026, 11, 2, hour, minute, 0)
39 .single()
40 .expect("fixture timestamp must be unambiguous")
41 }
42
43 #[test]
44 fn formats_afternoon_without_leading_zero() {
45 assert_eq!(format_message_time(local_at(15, 12)), "3:12 PM");
46 }
47
48 #[test]
49 fn formats_single_digit_morning_hour() {
50 assert_eq!(format_message_time(local_at(9, 5)), "9:05 AM");
51 }
52
53 #[test]
54 fn formats_double_digit_morning_hour() {
55 assert_eq!(format_message_time(local_at(11, 55)), "11:55 AM");
56 }
57
58 #[test]
59 fn midnight_is_twelve_am_not_zero() {
60 assert_eq!(format_message_time(local_at(0, 5)), "12:05 AM");
61 }
62
63 #[test]
64 fn noon_is_twelve_pm_not_zero() {
65 assert_eq!(format_message_time(local_at(12, 0)), "12:00 PM");
66 }
67
68 #[test]
69 fn footer_prefixes_time_with_middot() {
70 assert_eq!(message_timestamp_footer(local_at(15, 12)), "· 3:12 PM");
71 }
72
73 #[test]
74 fn current_footer_has_footer_shape() {
75 let footer = current_message_timestamp_footer();
76 let time = footer.strip_prefix("· ").expect("current footer must carry the middot");
77 assert!(time.contains(':'), "current footer must show clock time: {footer:?}");
78 assert!(time.ends_with("AM") || time.ends_with("PM"), "current footer must show meridiem: {footer:?}");
79 }
80}