atom: Display timestamps ourselves

chrono hides iso8601 output behind the alloc feature (or fragile Debug
output) so we annoyingly have to implement it ourselves
This commit is contained in:
xfnw 2024-03-27 12:49:55 -04:00
parent 960ff4a3bd
commit 915079bf98
2 changed files with 33 additions and 9 deletions

View File

@ -1,14 +1,18 @@
use crate::git::ModifyMap;
use chrono::{DateTime, NaiveDateTime};
use html_escaper::Escape;
use std::{collections::BTreeMap, path::PathBuf};
use std::{
collections::BTreeMap,
fmt::{self, Write},
path::PathBuf,
};
#[derive(boilerplate::Boilerplate)]
pub struct FeedXml<'a> {
pub title: &'a str,
pub id: &'a str,
pub url: &'a str,
pub updated: &'a NaiveDateTime,
pub updated: &'a AtomDateTime,
pub entries: &'a [AtomEntry<'a>],
}
@ -17,7 +21,29 @@ pub struct AtomEntry<'a> {
pub title: &'a str,
pub path: &'a str,
pub author: &'a str,
pub updated: NaiveDateTime,
pub updated: AtomDateTime,
}
/// NaiveDateTime that `Display`s to an atom feed compatible date (iso8601/rfc3339 subset)
/// without unnecessary allocation, as chrono gates iso8601 output behind the `alloc` feature
#[derive(Debug)]
pub struct AtomDateTime(pub NaiveDateTime);
impl AtomDateTime {
/// create a new AtomDateTime from a unix timestamp
pub fn new(unix: i64) -> Option<Self> {
let ts = DateTime::from_timestamp(unix, 0)?;
Some(Self(ts.naive_utc()))
}
}
impl fmt::Display for AtomDateTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.date().fmt(f)?;
f.write_char('T')?;
self.0.time().fmt(f)?;
f.write_char('Z')
}
}
pub fn entries<'a>(
@ -32,9 +58,7 @@ pub fn entries<'a>(
None => continue,
};
let (updated, author) = mtime.get(old).ok_or("missing modification info")?;
let updated = DateTime::from_timestamp(updated.seconds(), 0)
.ok_or("broken modification date")?
.naive_utc();
let updated = AtomDateTime::new(updated.seconds()).ok_or("broken modification date")?;
entries.push(AtomEntry {
title,
@ -44,6 +68,6 @@ pub fn entries<'a>(
});
}
entries.sort_by(|x, y| y.updated.cmp(&x.updated));
entries.sort_by(|x, y| y.updated.0.cmp(&x.updated.0));
Ok(entries)
}

View File

@ -3,14 +3,14 @@
<title>{{ self.title }}</title>
<id>{{ self.id }}/feed.xml</id>
<link rel="self" href="{{ self.url }}/feed.xml"/>
<updated>{{ format!("{:?}Z", self.updated) }}</updated>
<updated>{{ self.updated }}</updated>
%% for entry in self.entries {
<entry>
<title>{{ entry.title }}</title>
<id>{{ self.id }}/{{ entry.path }}</id>
<link rel="alternate" href="{{ self.url }}/{{ entry.path }}"/>
<author><name>{{ entry.author }}</name></author>
<updated>{{ format!("{:?}Z", entry.updated) }}</updated>
<updated>{{ entry.updated }}</updated>
</entry>
%% }
</feed>