From 83d75d48851a53271fc102824a91b4970755c1a5 Mon Sep 17 00:00:00 2001 From: gered Date: Wed, 28 Jun 2023 15:16:24 -0400 Subject: [PATCH] represent post dates as a NaiveDateTime, still allowing for date-only posts can be specified with a date only, or date and time as desired. it is up to the site's specific template to render posts with an appropriate date/time format string based on what the author's preferences --- example-site/posts.json | 4 +-- example-site/templates/archive.html | 2 +- example-site/templates/partials/post.html | 2 +- example-site/templates/tag.html | 2 +- src/config.rs | 4 +-- src/site.rs | 6 ++--- src/util.rs | 32 +++++++++++++++++++---- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/example-site/posts.json b/example-site/posts.json index 6551497..9a8da45 100644 --- a/example-site/posts.json +++ b/example-site/posts.json @@ -3,7 +3,7 @@ { "file_path": "2023-01-01-hello-world.md", "title": "Hello, world!", - "date": "2023-01-01", + "date": "2023-01-01 12:30:42", "slug": "hello-world", "tags": ["aaa", "hello", "testing"] }, @@ -17,7 +17,7 @@ { "file_path": "2023-03-20-lorem-ipsum.md", "title": "Lorem Ipsum", - "date": "2023-03-20", + "date": "2023-03-20 18:01", "slug": "lorem-ipsum" }, { diff --git a/example-site/templates/archive.html b/example-site/templates/archive.html index 29d98c1..113641a 100644 --- a/example-site/templates/archive.html +++ b/example-site/templates/archive.html @@ -8,7 +8,7 @@ {% for post in posts %} - +
{{ post.title }} diff --git a/example-site/templates/partials/post.html b/example-site/templates/partials/post.html index 251bf17..b87f92c 100644 --- a/example-site/templates/partials/post.html +++ b/example-site/templates/partials/post.html @@ -2,7 +2,7 @@

{{ post.title }}

- {{ post.date }} — + {{ post.date | date(format="%B %e, %Y") }} — {%- for tag in post.tags -%} {{ tag }} diff --git a/example-site/templates/tag.html b/example-site/templates/tag.html index dbcbe0a..f2fc46a 100644 --- a/example-site/templates/tag.html +++ b/example-site/templates/tag.html @@ -8,7 +8,7 @@ {% for post in posts %} - + {% endfor %} diff --git a/src/config.rs b/src/config.rs index 1658c9f..3ee0339 100644 --- a/src/config.rs +++ b/src/config.rs @@ -37,8 +37,8 @@ pub struct Pages { pub struct Post { pub file_path: PathBuf, pub title: String, - #[serde(deserialize_with = "crate::util::deserialize_naivedate")] - pub date: chrono::NaiveDate, + #[serde(deserialize_with = "crate::util::deserialize_string_to_naivedatetime")] + pub date: chrono::NaiveDateTime, pub slug: String, pub old_urls: Option>, pub tags: Option>, diff --git a/src/site.rs b/src/site.rs index 5f45639..646343c 100644 --- a/src/site.rs +++ b/src/site.rs @@ -106,8 +106,8 @@ pub struct Post { pub url: UriPath, pub title: String, pub content_html: String, - #[serde(serialize_with = "crate::util::serialize_naivedate")] - pub date: chrono::NaiveDate, + #[serde(serialize_with = "crate::util::serialize_naivedatetime_to_i64")] + pub date: chrono::NaiveDateTime, pub tags: Vec, } @@ -327,7 +327,7 @@ impl SiteService { .title(post.title.clone()) .content(post.content_html.clone()) .link(base_url.clone().join(&post.url).unwrap().to_string()) - .pub_date(chrono::Local.from_local_date(&post.date).unwrap().to_string()) + .pub_date(chrono::Local.from_local_datetime(&post.date).unwrap().to_string()) .build() }) .collect::>(), diff --git a/src/util.rs b/src/util.rs index ecfefb3..7443ba4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,10 +1,32 @@ -pub fn deserialize_naivedate<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result { - let s: String = serde::Deserialize::deserialize(deserializer)?; - chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d").map_err(serde::de::Error::custom) +fn parse_datetime_from_str(s: &str) -> Result { + let dt = chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S"); + if dt.is_ok() { + return dt; + } + + let dt = chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M"); + if dt.is_ok() { + return dt; + } + + match chrono::NaiveDate::parse_from_str(s, "%Y-%m-%d") { + Ok(date) => Ok(date.and_time(chrono::NaiveTime::default())), + Err(e) => Err(e), + } } -pub fn serialize_naivedate(value: &chrono::NaiveDate, serializer: S) -> Result { - serializer.serialize_str(&value.to_string()) +pub fn deserialize_string_to_naivedatetime<'de, D: serde::Deserializer<'de>>( + deserializer: D, +) -> Result { + let s: String = serde::Deserialize::deserialize(deserializer)?; + parse_datetime_from_str(&s).map_err(serde::de::Error::custom) +} + +pub fn serialize_naivedatetime_to_i64( + value: &chrono::NaiveDateTime, + serializer: S, +) -> Result { + serializer.serialize_i64(value.timestamp()) } pub fn safe_subslice(slice: &[T], start: usize, count: usize) -> Option<&[T]> {
{{ post.title }}