make date format supports locale (#6306)

* add --locale flag to make output support locale

* implement again based on nu-utils get_system_locale_string

* add comment
This commit is contained in:
WindSoilder 2022-08-14 21:07:04 +08:00 committed by GitHub
parent 6145f734b7
commit 21770367e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 6 deletions

7
Cargo.lock generated
View File

@ -539,6 +539,7 @@ dependencies = [
"js-sys", "js-sys",
"num-integer", "num-integer",
"num-traits", "num-traits",
"pure-rust-locales",
"serde", "serde",
"time 0.1.44", "time 0.1.44",
"wasm-bindgen", "wasm-bindgen",
@ -3676,6 +3677,12 @@ dependencies = [
"rustix", "rustix",
] ]
[[package]]
name = "pure-rust-locales"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45c49fc4f91f35bae654f85ebb3a44d60ac64f11b3166ffa609def390c732d8"
[[package]] [[package]]
name = "pwd" name = "pwd"
version = "1.4.0" version = "1.4.0"

View File

@ -33,7 +33,7 @@ base64 = "0.13.0"
byteorder = "1.4.3" byteorder = "1.4.3"
bytesize = "1.1.0" bytesize = "1.1.0"
calamine = "0.18.0" calamine = "0.18.0"
chrono = { version = "0.4.21", features = ["serde"] } chrono = { version = "0.4.21", features = ["serde", "unstable-locales"] }
chrono-humanize = "0.2.1" chrono-humanize = "0.2.1"
chrono-tz = "0.6.3" chrono-tz = "0.6.3"
crossterm = "0.24.0" crossterm = "0.24.0"

View File

@ -1,5 +1,4 @@
use chrono::Local; use chrono::{DateTime, Local, Locale, TimeZone};
use chrono::{DateTime, TimeZone};
use nu_engine::CallExt; use nu_engine::CallExt;
use nu_protocol::{ use nu_protocol::{
@ -7,6 +6,7 @@ use nu_protocol::{
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value, Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
}; };
use nu_utils::locale::get_system_locale_string;
use std::fmt::{Display, Write}; use std::fmt::{Display, Write};
use super::utils::parse_date_from_string; use super::utils::parse_date_from_string;
@ -98,7 +98,13 @@ where
Tz::Offset: Display, Tz::Offset: Display,
{ {
let mut formatter_buf = String::new(); let mut formatter_buf = String::new();
let format = date_time.format(formatter); let locale: Locale = get_system_locale_string()
.map(|l| l.replace('-', "_")) // `chrono::Locale` needs something like `xx_xx`, rather than `xx-xx`
.unwrap_or_else(|| String::from("en_US"))
.as_str()
.try_into()
.unwrap_or(Locale::en_US);
let format = date_time.format_localized(formatter, locale);
match formatter_buf.write_fmt(format_args!("{}", format)) { match formatter_buf.write_fmt(format_args!("{}", format)) {
Ok(_) => Value::String { Ok(_) => Value::String {

View File

@ -12,3 +12,66 @@ fn formatter_not_valid() {
assert!(actual.err.contains("invalid format")); assert!(actual.err.contains("invalid format"));
} }
#[test]
fn locale_format_respect_different_locale() {
let actual = nu!(
locale: "en_US",
pipeline(
r#"
"2021-10-22 20:00:12 +01:00" | date format "%c"
"#
)
);
assert!(actual.out.contains("Fri 22 Oct 2021 08:00:12 PM +01:00"));
let actual = nu!(
locale: "en_GB",
pipeline(
r#"
"2021-10-22 20:00:12 +01:00" | date format "%c"
"#
)
);
assert!(actual.out.contains("Fri 22 Oct 2021 20:00:12 +01:00"));
let actual = nu!(
locale: "de_DE",
pipeline(
r#"
"2021-10-22 20:00:12 +01:00" | date format "%c"
"#
)
);
assert!(actual.out.contains("Fr 22 Okt 2021 20:00:12 +01:00"));
let actual = nu!(
locale: "zh_CN",
pipeline(
r#"
"2021-10-22 20:00:12 +01:00" | date format "%c"
"#
)
);
assert!(actual.out.contains("2021年10月22日 星期五 20时00分12秒"));
let actual = nu!(
locale: "ja_JP",
pipeline(
r#"
"2021-10-22 20:00:12 +01:00" | date format "%c"
"#
)
);
assert!(actual.out.contains("2021年10月22日 20時00分12秒"));
let actual = nu!(
locale: "fr_FR",
pipeline(
r#"
"2021-10-22 20:00:12 +01:00" | date format "%c"
"#
)
);
assert!(actual.out.contains("ven. 22 oct. 2021 20:00:12 +01:00"));
}

View File

@ -27,13 +27,13 @@ pub fn get_system_locale() -> Locale {
} }
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
fn get_system_locale_string() -> Option<String> { pub fn get_system_locale_string() -> Option<String> {
std::env::var(LOCALE_OVERRIDE_ENV_VAR) std::env::var(LOCALE_OVERRIDE_ENV_VAR)
.ok() .ok()
.or_else(sys_locale::get_locale) .or_else(sys_locale::get_locale)
} }
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
fn get_system_locale_string() -> Option<String> { pub fn get_system_locale_string() -> Option<String> {
sys_locale::get_locale() sys_locale::get_locale()
} }