diff --git a/CHANGELOG.md b/CHANGELOG.md index 068417ac..57109625 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.20.1 (2025-03-00) + +- Make `date` filter work on a RFC3339 string as well thanks to @blfpd + ## 1.20.0 (2024-05-27) - Support parenthesis in if statemetns diff --git a/docs/content/docs/_index.md b/docs/content/docs/_index.md index 7eda240e..92acfd63 100644 --- a/docs/content/docs/_index.md +++ b/docs/content/docs/_index.md @@ -1215,6 +1215,8 @@ Example: {{ "2019-09-19T13:18:48.731Z" | date(format="%Y-%m-%d %H:%M", timezone="Asia/Shanghai") }} {{ 1648252203 | date(timezone="Europe/Berlin") }} + +{{ "Thu, 19 09 2019 13:18:48 GMT" | date(timezone="UTC") }} ``` Locale can be specified (excepted when the input is a timestamp without timezone argument), default being POSIX. (only available if the `date-locale` feature is enabled) diff --git a/src/builtins/filters/common.rs b/src/builtins/filters/common.rs index 17e01219..2f381065 100644 --- a/src/builtins/filters/common.rs +++ b/src/builtins/filters/common.rs @@ -62,7 +62,7 @@ pub fn json_encode(value: &Value, args: &HashMap) -> Result) -> Result { } }, Value::String(s) => { - if s.contains('T') { + if s.chars().filter(|&c| c == ' ').count() >= 3 { + match DateTime::parse_from_rfc2822(s) { + Ok(val) => val.format(&format), + Err(_) => { + return Err(Error::msg(format!( + "Error parsing `{:?}` as rfc2822 date", + s + ))); + } + } + } else if s.contains('T') { match s.parse::>() { Ok(val) => match timezone { Some(timezone) => { @@ -183,7 +193,14 @@ pub fn date(value: &Value, args: &HashMap) -> Result { None => return Err(Error::msg(format!("Filter `date` was invoked on a float: {}", n))), }, Value::String(s) => { - if s.contains('T') { + if s.chars().filter(|&c| c == ' ').count() >= 3 { + match DateTime::parse_from_rfc2822(s) { + Ok(val) => val.format(&format), + Err(_) => { + return Err(Error::msg(format!("Error parsing `{:?}` as rfc2822 date", s))); + } + } + } else if s.contains('T') { match s.parse::>() { Ok(val) => match timezone { Some(timezone) => val.with_timezone(&timezone).format(&format), @@ -371,6 +388,26 @@ mod tests { assert_eq!(result.unwrap(), to_value("1996-12-19 -0800").unwrap()); } + #[cfg(feature = "builtins")] + #[test] + fn date_rfc2822() { + let args = HashMap::new(); + let dt: DateTime = Local::now(); + let result = date(&to_value(dt.to_rfc2822()).unwrap(), &args); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), to_value(dt.format("%Y-%m-%d").to_string()).unwrap()); + } + + #[cfg(feature = "builtins")] + #[test] + fn date_rfc2822_preserves_timezone() { + let mut args = HashMap::new(); + args.insert("format".to_string(), to_value("%Y-%m-%d %z").unwrap()); + let result = date(&to_value("Wed, 18 Feb 2015 23:16:09 GMT").unwrap(), &args); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), to_value("2015-02-18 +0000").unwrap()); + } + #[cfg(feature = "builtins")] #[test] fn date_yyyy_mm_dd() {