fix: rss date formats 37f0987a
fixes issue with rss feeds from post and cellar not using the correct
date/time format to ne consumed by readers
Steve Simkins · 2026-04-19 01:50 5 file(s) · +25 −7
Cargo.lock +2 −0
704 704
 "askama_web",
705 705
 "axum",
706 706
 "base64",
707 +
 "chrono",
707 708
 "dotenvy",
708 709
 "image",
709 710
 "nanoid",
3154 3155
 "askama 0.15.6",
3155 3156
 "askama_web",
3156 3157
 "axum",
3158 +
 "chrono",
3157 3159
 "dotenvy",
3158 3160
 "nanoid",
3159 3161
 "pulldown-cmark",
apps/cellar/Cargo.toml +2 −1
1 1
[package]
2 2
name = "cellar"
3 -
version = "0.2.0"
3 +
version = "0.2.1"
4 4
edition = "2024"
5 5
description = "Personal wine tasting log"
6 6
license = "MIT"
29 29
base64 = "0.22"
30 30
image = "0.25"
31 31
serde_rusqlite = "0.41"
32 +
chrono = "0.4"
apps/cellar/src/server/handlers/public.rs +9 −3
114 114
        .replace('\'', "'")
115 115
}
116 116
117 +
fn to_rfc2822(sqlite_ts: &str) -> String {
118 +
    chrono::NaiveDateTime::parse_from_str(sqlite_ts, "%Y-%m-%d %H:%M:%S")
119 +
        .map(|naive| naive.and_utc().to_rfc2822())
120 +
        .unwrap_or_else(|_| sqlite_ts.to_string())
121 +
}
122 +
117 123
pub async fn rss_feed(State(state): State<Arc<AppState>>) -> Response {
118 124
    let site_url = &state.site_url;
119 125
140 146
            desc_parts.push(wine.notes.clone());
141 147
        }
142 148
        let description = xml_escape(&desc_parts.join(" — "));
143 -
        let pub_date = &wine.created_at;
149 +
        let pub_date = to_rfc2822(&wine.created_at);
144 150
        let guid = format!("{}/wines/{}", site_url, xml_escape(&wine.short_id));
145 151
146 152
        items.push_str(&format!(
150 156
151 157
    let last_build = wines
152 158
        .first()
153 -
        .map(|w| w.created_at.as_str())
154 -
        .unwrap_or("");
159 +
        .map(|w| to_rfc2822(&w.created_at))
160 +
        .unwrap_or_default();
155 161
156 162
    let xml = format!(
157 163
        r#"<?xml version="1.0" encoding="UTF-8"?>
apps/posts/Cargo.toml +2 −1
1 1
[package]
2 2
name = "posts"
3 -
version = "0.1.4"
3 +
version = "0.1.5"
4 4
edition = "2024"
5 5
description = "CMS blog with admin interface"
6 6
license = "MIT"
27 27
askama = "0.15"
28 28
askama_web = { version = "0.15", features = ["axum-0.8"] }
29 29
pulldown-cmark = "0.12"
30 +
chrono = "0.4"
30 31
zip = { workspace = true }
apps/posts/src/server/handlers/public.rs +10 −2
193 193
        .replace('\'', "&apos;")
194 194
}
195 195
196 +
fn to_rfc2822(sqlite_ts: &str) -> String {
197 +
    chrono::NaiveDateTime::parse_from_str(sqlite_ts, "%Y-%m-%d %H:%M:%S")
198 +
        .map(|naive| naive.and_utc().to_rfc2822())
199 +
        .unwrap_or_else(|_| sqlite_ts.to_string())
200 +
}
201 +
196 202
pub async fn rss_feed(State(state): State<Arc<AppState>>) -> Response {
197 203
    let blog_title = get_blog_title(&state.db);
198 204
    let blog_description = get_setting_or_default(&state.db, "blog_description");
217 223
                xml_escape(&plain)
218 224
            }
219 225
        };
220 -
        let pub_date = post.published_date.as_deref().unwrap_or(&post.created_at);
226 +
        let raw_date = post.published_date.as_deref().unwrap_or(&post.created_at);
227 +
        let pub_date = to_rfc2822(raw_date);
221 228
        let guid = format!("{}/posts/{}", site_url, xml_escape(&post.slug));
222 229
223 230
        items.push_str(&format!(
228 235
    let last_build = posts
229 236
        .first()
230 237
        .and_then(|p| p.published_date.as_deref())
231 -
        .unwrap_or("");
238 +
        .map(to_rfc2822)
239 +
        .unwrap_or_default();
232 240
233 241
    let xml = format!(
234 242
        r#"<?xml version="1.0" encoding="UTF-8"?>