From 9bca63ebefcb4c8338a60cf4842a4466e25aeff8 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Fri, 8 Sep 2023 08:59:05 -0500 Subject: [PATCH] update format date when using %x %X %r (#10272) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Apparently some strftime formats are already localized and when you "double localize" them, they don't work. This PR fixes that so that %x %X %r %c don't go through the localization step. Example: %x %X ### Before ```nushell ❯ date now | format date "%x %X %p" 09/08/2023 08 AM ``` ### After ```nushell ❯ date now | format date "%x %X %p" 09/08/23 08:09:14 AM ``` I started to make one format_datetime to rule them all but one returns a string and one returns a value. If we convert to the string, we lose the nice error messages. If we change to value, more code has to be changed elsewhere. So, I decided to just leave two functions. # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-command/src/strings/format/date.rs | 22 +++++++++++++------- crates/nu-protocol/src/value/mod.rs | 22 +++++++++++++------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/crates/nu-command/src/strings/format/date.rs b/crates/nu-command/src/strings/format/date.rs index 5c6c7b4e66..18b11f591b 100644 --- a/crates/nu-command/src/strings/format/date.rs +++ b/crates/nu-command/src/strings/format/date.rs @@ -117,13 +117,21 @@ where Tz::Offset: Display, { let mut formatter_buf = String::new(); - 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); + // These are already in locale format, so we don't need to localize them + let format = if ["%x", "%X", "%r"] + .iter() + .any(|item| formatter.contains(item)) + { + date_time.format(formatter) + } else { + 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); + date_time.format_localized(formatter, locale) + }; match formatter_buf.write_fmt(format_args!("{format}")) { Ok(_) => Value::string(formatter_buf, span), diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 7dbf522707..ee3247f23f 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -802,13 +802,21 @@ impl Value { Tz::Offset: Display, { let mut formatter_buf = String::new(); - 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); + // These are already in locale format, so we don't need to localize them + let format = if ["%x", "%X", "%r"] + .iter() + .any(|item| formatter.contains(item)) + { + date_time.format(formatter) + } else { + 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); + date_time.format_localized(formatter, locale) + }; match formatter_buf.write_fmt(format_args!("{format}")) { Ok(_) => (),