{"record":{"id":"eb98801e3ef2a093","repo":"getzola/zola","slug":"error-parsing-yaml-datetime","errorCode":null,"errorMessage":"Error parsing YAML datetime","messagePattern":"Error parsing YAML datetime","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"components/content/src/front_matter/datetime.rs","lineNumber":17,"sourceCode":"use std::sync::LazyLock;\n\nuse errors::{Result, anyhow};\nuse regex::Regex;\nuse serde::Deserialize;\nuse time::format_description::well_known::Rfc3339;\n\n// See https://github.com/getzola/zola/issues/2071#issuecomment-1530610650\nstatic YAML_DATETIME_RE: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(r#\"^\"?(?P<year>[0-9]{4})-(?P<month>[0-9][0-9]?)-(?P<day>[0-9][0-9]?)(?:(?:[Tt]|[ \\t]+)(?P<hour>[0-9][0-9]?):(?P<minute>[0-9]{2}):(?P<second>[0-9]{2})(?P<fraction>\\.[0-9]{0,9})?[ \\t]*(?:(?P<utc>Z)|(?P<offset>(?P<offset_hour>[-+][0-9][0-9]?)(?::(?P<offset_minute>[0-9][0-9]))?))?)?\"?$\"#).unwrap()\n});\n\nfn parse_yaml_datetime(date_string: &str) -> Result<time::OffsetDateTime> {\n    let captures = if let Some(captures_) = YAML_DATETIME_RE.captures(date_string) {\n        Ok(captures_)\n    } else {\n        Err(anyhow!(\"Error parsing YAML datetime\"))\n    }?;\n    let year = captures.name(\"year\").unwrap().as_str();\n    let month = captures.name(\"month\").unwrap().as_str();\n    let day = captures.name(\"day\").unwrap().as_str();\n    let hour = if let Some(hour_) = captures.name(\"hour\") { hour_.as_str() } else { \"0\" };\n    let minute = if let Some(minute_) = captures.name(\"minute\") { minute_.as_str() } else { \"0\" };\n    let second = if let Some(second_) = captures.name(\"second\") { second_.as_str() } else { \"0\" };\n    let fraction_raw =\n        if let Some(fraction_) = captures.name(\"fraction\") { fraction_.as_str() } else { \"\" };\n    let fraction_intermediate = fraction_raw.trim_end_matches(\"0\");\n    //\n    // Prepare for eventual conversion into nanoseconds\n    let fraction = if !fraction_intermediate.is_empty() { fraction_intermediate } else { \"0\" };\n    let maybe_timezone_hour = captures.name(\"offset_hour\");\n    let maybe_timezone_minute = captures.name(\"offset_minute\");\n\n    let mut offset_datetime = time::OffsetDateTime::UNIX_EPOCH;\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/components/content/src/front_matter/datetime.rs#L1-L35","documentation":"`parse_yaml_datetime` parses datetime strings from YAML front matter using the `YAML_DATETIME_RE` regex (accepting ISO-8601-like `YYYY-MM-DD[Thh:mm[:ss[.frac]][Z|±hh:mm]]` forms). If the string does not match the regex at all, this generic error is raised. YAML's unquoted `date: 2024-01-01` scalar type is a known source of oddities since serde_yaml may decode it as a string only in specific formats.","triggerScenarios":"A front-matter field expected to be a datetime (e.g. `date`, or a serialized datetime in extra/page data) contains a string that doesn't match the YAML datetime regex — wrong format, extra text, or an unsupported timezone form.","commonSituations":"Writing `date: 2024/01/01` (slashes instead of hyphens); including a locale-formatted date like `date: Jan 1, 2024`; quoting issues that leave stray characters; a datetime field fed a plain string like \"today\".","solutions":["Use ISO 8601 format in front matter: `date = 2024-01-01` or `date = 2024-01-01T10:30:00Z`","Check for typos/extra characters in the date string (slashes, month names, trailing spaces)","If a custom field, quote it consistently and keep to `YYYY-MM-DD[Thh:mm[:ss]][Z|±hh:mm]`"],"exampleFix":"// before (front matter)\ndate: 2024/01/01\n// after\ndate: 2024-01-01","handlingStrategy":"validation","validationCode":"use regex::Regex;\nlet yaml_dt = Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}([Tt ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?([Zz]|[+-]\\d{2}:?\\d{2})?)?$\").unwrap();\nif !yaml_dt.is_match(date_str) { /* fix front matter format before parsing */ }","typeGuard":"fn looks_like_yaml_datetime(s: &str) -> bool {\n    s.len() >= 10 && s[..4].chars().all(|c| c.is_ascii_digit()) && s.as_bytes().get(4) == Some(&b'-') && s.as_bytes().get(7) == Some(&b'-')\n}","tryCatchPattern":"match parse_yaml_datetime(s) {\n    Ok(dt) => dt,\n    Err(e) if e.to_string() == \"Error parsing YAML datetime\" =>\n        bail!(\"Front matter date '{}' must be ISO 8601, e.g. 2024-01-01T10:30:00Z\", s),\n    Err(e) => return Err(e),\n}","preventionTips":["Always write front-matter dates as YYYY-MM-DD with hyphens, not slashes","Include an explicit time and timezone when precision matters","Add a front-matter lint/check step in CI to validate all date fields","Quote date strings only if you also keep the ISO format"],"tags":["yaml","front-matter","datetime","parsing"],"backgroundTag":"invalid-datetime-format","analyzedSha":"61d30828217957120309db657950224edf9707e2","analyzedAt":"2026-09-03T14:39:09.727Z","contentChangedAt":"2026-09-03T14:39:09.727Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}