use std::sync::OnceLock;
use time::{OffsetDateTime, UtcOffset};
use tracing_subscriber::fmt::format::Writer;
use tracing_subscriber::fmt::time::FormatTime;
static LOCAL_OFFSET: OnceLock<UtcOffset> = OnceLock::new();
pub fn init() {
let offset = UtcOffset::current_local_offset().unwrap_or(UtcOffset::UTC);
let _ = LOCAL_OFFSET.set(offset);
}
pub fn offset() -> UtcOffset {
LOCAL_OFFSET.get().copied().unwrap_or(UtcOffset::UTC)
}
pub fn now_local() -> OffsetDateTime {
OffsetDateTime::now_utc().to_offset(offset())
}
pub struct LocalTimer;
impl FormatTime for LocalTimer {
fn format_time(&self, w: &mut Writer<'_>) -> std::fmt::Result {
let fmt =
time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
let s = now_local().format(&fmt).map_err(|_| std::fmt::Error)?;
write!(w, "{}", s)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn offset_returns_utc_or_captured_value() {
let _ = offset();
}
#[test]
fn init_is_idempotent() {
init();
init();
}
#[test]
fn now_local_does_not_panic_and_uses_captured_offset() {
let dt = now_local();
assert_eq!(dt.offset(), offset());
}
#[test]
fn local_timer_writes_yyyy_mm_dd_hh_mm_ss() {
let mut buf = String::new();
let mut writer = Writer::new(&mut buf);
LocalTimer.format_time(&mut writer).expect("format");
assert_eq!(buf.len(), 19, "unexpected output: {buf:?}");
let bytes = buf.as_bytes();
assert_eq!(bytes[4], b'-');
assert_eq!(bytes[7], b'-');
assert_eq!(bytes[10], b' ');
assert_eq!(bytes[13], b':');
assert_eq!(bytes[16], b':');
}
}