diff --git a/Cargo.lock b/Cargo.lock index c4d2dafb66..e0424551ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2115,6 +2115,7 @@ dependencies = [ "settings", "smallvec", "story", + "sys-locale", "theme", "theme_selector", "time", diff --git a/Cargo.toml b/Cargo.toml index 7966646223..c115a46231 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -272,6 +272,7 @@ unindent = "0.1.7" url = "2.2" uuid = { version = "1.1.2", features = ["v4"] } wasmtime = "16" +sys-locale = "0.3.1" [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "1d8975319c2d5de1bf710e7e21db25b0eee4bc66" } diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index e1e1aa7798..26237de4c6 100644 --- a/crates/collab_ui/Cargo.toml +++ b/crates/collab_ui/Cargo.toml @@ -66,6 +66,7 @@ util.workspace = true vcs_menu.workspace = true workspace.workspace = true zed_actions.workspace = true +sys-locale.workspace = true [dev-dependencies] call = { workspace = true, features = ["test-support"] } diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index abe345db6d..0181ed8587 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -480,6 +480,7 @@ impl ChatPanel { OffsetDateTime::now_utc(), message.timestamp, self.local_timezone, + None, )) .size(LabelSize::Small) .color(Color::Muted), @@ -917,26 +918,58 @@ impl Panel for ChatPanel { impl EventEmitter for ChatPanel {} +fn is_12_hour_clock(locale: String) -> bool { + [ + "es-MX", "es-CO", "es-SV", "es-NI", + "es-HN", // Mexico, Colombia, El Salvador, Nicaragua, Honduras + "en-US", "en-CA", "en-AU", "en-NZ", // U.S, Canada, Australia, New Zealand + "ar-SA", "ar-EG", "ar-JO", // Saudi Arabia, Egypt, Jordan + "en-IN", "hi-IN", // India, Hindu + "en-PK", "ur-PK", // Pakistan, Urdu + "en-PH", "fil-PH", // Philippines, Filipino + "bn-BD", "ccp-BD", // Bangladesh, Chakma + "en-IE", "ga-IE", // Ireland, Irish + "en-MY", "ms-MY", // Malaysia, Malay + ] + .contains(&locale.as_str()) +} + fn format_timestamp( reference: OffsetDateTime, timestamp: OffsetDateTime, timezone: UtcOffset, + locale: Option, ) -> String { + let locale = match locale { + Some(locale) => locale, + None => sys_locale::get_locale().unwrap_or_else(|| String::from("en-US")), + }; let timestamp_local = timestamp.to_offset(timezone); let timestamp_local_hour = timestamp_local.hour(); - - let hour_12 = match timestamp_local_hour { - 0 => 12, // Midnight - 13..=23 => timestamp_local_hour - 12, // PM hours - _ => timestamp_local_hour, // AM hours - }; - let meridiem = if timestamp_local_hour >= 12 { - "pm" - } else { - "am" - }; let timestamp_local_minute = timestamp_local.minute(); - let formatted_time = format!("{:02}:{:02} {}", hour_12, timestamp_local_minute, meridiem); + + let (hour, meridiem) = if is_12_hour_clock(locale) { + let meridiem = if timestamp_local_hour >= 12 { + "pm" + } else { + "am" + }; + + let hour_12 = match timestamp_local_hour { + 0 => 12, // Midnight + 13..=23 => timestamp_local_hour - 12, // PM hours + _ => timestamp_local_hour, // AM hours + }; + + (hour_12, Some(meridiem)) + } else { + (timestamp_local_hour, None) + }; + + let formatted_time = match meridiem { + Some(meridiem) => format!("{:02}:{:02} {}", hour, timestamp_local_minute, meridiem), + None => format!("{:02}:{:02}", hour, timestamp_local_minute), + }; let reference_local = reference.to_offset(timezone); let reference_local_date = reference_local.date(); @@ -950,12 +983,20 @@ fn format_timestamp( return format!("yesterday at {}", formatted_time); } - format!( - "{:02}/{:02}/{}", - timestamp_local_date.month() as u32, - timestamp_local_date.day(), - timestamp_local_date.year() - ) + match meridiem { + Some(_) => format!( + "{:02}/{:02}/{}", + timestamp_local_date.month() as u32, + timestamp_local_date.day(), + timestamp_local_date.year() + ), + None => format!( + "{:02}/{:02}/{}", + timestamp_local_date.day(), + timestamp_local_date.month() as u32, + timestamp_local_date.year() + ), + } } #[cfg(test)] @@ -1015,13 +1056,34 @@ mod tests { ); } + #[test] + fn test_format_locale() { + 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(), + Some(String::from("en-GB")) + ), + "15:30" + ); + } + #[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()), + format_timestamp( + reference, + timestamp, + test_timezone(), + Some(String::from("en-US")) + ), "03:30 pm" ); } @@ -1032,7 +1094,12 @@ mod tests { let timestamp = create_offset_datetime(1990, 4, 11, 9, 0, 0); assert_eq!( - format_timestamp(reference, timestamp, test_timezone()), + format_timestamp( + reference, + timestamp, + test_timezone(), + Some(String::from("en-US")) + ), "yesterday at 09:00 am" ); } @@ -1043,7 +1110,12 @@ mod tests { let timestamp = create_offset_datetime(1990, 4, 11, 20, 0, 0); assert_eq!( - format_timestamp(reference, timestamp, test_timezone()), + format_timestamp( + reference, + timestamp, + test_timezone(), + Some(String::from("en-US")) + ), "yesterday at 08:00 pm" ); } @@ -1054,7 +1126,12 @@ mod tests { let timestamp = create_offset_datetime(1990, 4, 11, 18, 0, 0); assert_eq!( - format_timestamp(reference, timestamp, test_timezone()), + format_timestamp( + reference, + timestamp, + test_timezone(), + Some(String::from("en-US")) + ), "yesterday at 06:00 pm" ); } @@ -1065,7 +1142,12 @@ mod tests { let timestamp = create_offset_datetime(1990, 4, 11, 23, 55, 0); assert_eq!( - format_timestamp(reference, timestamp, test_timezone()), + format_timestamp( + reference, + timestamp, + test_timezone(), + Some(String::from("en-US")) + ), "yesterday at 11:55 pm" ); } @@ -1076,7 +1158,12 @@ mod tests { let timestamp = create_offset_datetime(1990, 4, 1, 20, 0, 0); assert_eq!( - format_timestamp(reference, timestamp, test_timezone()), + format_timestamp( + reference, + timestamp, + test_timezone(), + Some(String::from("en-US")) + ), "yesterday at 08:00 pm" ); } @@ -1087,7 +1174,12 @@ mod tests { let timestamp = create_offset_datetime(1990, 4, 10, 20, 20, 0); assert_eq!( - format_timestamp(reference, timestamp, test_timezone()), + format_timestamp( + reference, + timestamp, + test_timezone(), + Some(String::from("en-US")) + ), "04/10/1990" ); }