use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize, Serializer};
fn serialize_datetime_as_iso8601<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&dt.format("%Y-%m-%dT%H:%M:%SZ").to_string())
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct TemplateMetadata {
#[serde(serialize_with = "serialize_datetime_as_iso8601")]
generated_at: DateTime<Utc>,
}
impl TemplateMetadata {
#[must_use]
pub fn new(generated_at: DateTime<Utc>) -> Self {
Self { generated_at }
}
#[must_use]
pub fn generated_at(&self) -> &DateTime<Utc> {
&self.generated_at
}
#[must_use]
pub fn generated_at_iso8601(&self) -> String {
self.generated_at.format("%Y-%m-%dT%H:%M:%SZ").to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::TimeZone;
#[test]
fn it_should_create_template_metadata_with_timestamp() {
let timestamp = Utc.with_ymd_and_hms(2026, 1, 27, 14, 30, 0).unwrap();
let metadata = TemplateMetadata::new(timestamp);
assert_eq!(metadata.generated_at(), ×tamp);
}
#[test]
fn it_should_format_timestamp_as_iso8601() {
let timestamp = Utc.with_ymd_and_hms(2026, 1, 27, 14, 30, 0).unwrap();
let metadata = TemplateMetadata::new(timestamp);
assert_eq!(metadata.generated_at_iso8601(), "2026-01-27T14:30:00Z");
}
#[test]
fn it_should_serialize_metadata_correctly() {
let timestamp = Utc.with_ymd_and_hms(2026, 1, 27, 14, 30, 0).unwrap();
let metadata = TemplateMetadata::new(timestamp);
let json = serde_json::to_string(&metadata).unwrap();
assert!(json.contains("\"generated_at\""));
assert!(json.contains("2026-01-27T14:30:00Z"));
}
#[test]
fn it_should_deserialize_metadata_correctly() {
let json = r#"{"generated_at":"2026-01-27T14:30:00Z"}"#;
let metadata: TemplateMetadata = serde_json::from_str(json).unwrap();
assert_eq!(
metadata.generated_at(),
&Utc.with_ymd_and_hms(2026, 1, 27, 14, 30, 0).unwrap()
);
}
#[test]
fn it_should_implement_clone() {
let timestamp = Utc.with_ymd_and_hms(2026, 1, 27, 14, 30, 0).unwrap();
let metadata = TemplateMetadata::new(timestamp);
let cloned = metadata.clone();
assert_eq!(metadata, cloned);
}
}