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
This commit is contained in:
Gered 2023-06-28 15:16:24 -04:00
parent 3f18b2a58a
commit 83d75d4885
7 changed files with 37 additions and 15 deletions

View file

@ -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"
},
{

View file

@ -8,7 +8,7 @@
<table>
{% for post in posts %}
<tr>
<td><time>{{ post.date }}</time></td>
<td><time>{{ post.date | date(format="%Y-%b-%d") }}</time></td>
<td>
<a href="{{ post.url }}">{{ post.title }}</a>
<span class="tags">

View file

@ -2,7 +2,7 @@
<header>
<h1>{{ post.title }}</h1>
<div class="meta">
{{ post.date }} &mdash;
{{ post.date | date(format="%B %e, %Y") }} &mdash;
<span class="tags">
{%- for tag in post.tags -%}
<span><a href="/tag/{{ tag }}/">{{ tag }}</a></span>

View file

@ -8,7 +8,7 @@
<table>
{% for post in posts %}
<tr>
<td><time>{{ post.date }}</time></td>
<td><time>{{ post.date | date }}</time></td>
<td><a href="{{ post.url }}">{{ post.title }}</a></td>
</tr>
{% endfor %}

View file

@ -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<Vec<String>>,
pub tags: Option<Vec<String>>,

View file

@ -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<Tag>,
}
@ -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::<Vec<rss::Item>>(),

View file

@ -1,10 +1,32 @@
pub fn deserialize_naivedate<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<chrono::NaiveDate, D::Error> {
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<chrono::NaiveDateTime, chrono::ParseError> {
let dt = chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S");
if dt.is_ok() {
return dt;
}
pub fn serialize_naivedate<S: serde::Serializer>(value: &chrono::NaiveDate, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&value.to_string())
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 deserialize_string_to_naivedatetime<'de, D: serde::Deserializer<'de>>(
deserializer: D,
) -> Result<chrono::NaiveDateTime, D::Error> {
let s: String = serde::Deserialize::deserialize(deserializer)?;
parse_datetime_from_str(&s).map_err(serde::de::Error::custom)
}
pub fn serialize_naivedatetime_to_i64<S: serde::Serializer>(
value: &chrono::NaiveDateTime,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_i64(value.timestamp())
}
pub fn safe_subslice<T>(slice: &[T], start: usize, count: usize) -> Option<&[T]> {