use chrono::{DateTime, SecondsFormat, Utc};
pub fn now_iso() -> String {
to_iso(Utc::now())
}
pub fn to_iso(t: DateTime<Utc>) -> String {
t.to_rfc3339_opts(SecondsFormat::Millis, true)
}
pub fn parse_iso(s: &str) -> Option<DateTime<Utc>> {
DateTime::parse_from_rfc3339(s)
.ok()
.map(|d| d.with_timezone(&Utc))
}
pub fn parse_tz(name: &str) -> chrono_tz::Tz {
name.parse::<chrono_tz::Tz>().unwrap_or(chrono_tz::UTC)
}
pub fn is_valid_timezone(name: &str) -> bool {
name.parse::<chrono_tz::Tz>().is_ok()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn iso_format_matches_js() {
let t = parse_iso("2026-01-02T03:04:05.006Z").unwrap();
assert_eq!(to_iso(t), "2026-01-02T03:04:05.006Z");
assert_eq!(now_iso().len(), 24);
}
#[test]
fn timezone_validation() {
assert!(is_valid_timezone("Europe/Berlin"));
assert!(!is_valid_timezone("Mars/Base"));
}
}