#[cfg(not(feature = "use_chrono_for_offset"))]
use crate::util::{eprint_err, ERRCODE};
#[cfg(feature = "use_chrono_for_offset")]
use chrono::{Local, Offset};
use std::sync::{Arc, Mutex};
use time::{formatting::Formattable, OffsetDateTime, UtcOffset};
#[derive(Debug, Default)]
pub struct DeferredNow(Option<OffsetDateTime>);
impl DeferredNow {
#[must_use]
pub fn new() -> Self {
Self(None)
}
pub fn now(&mut self) -> &OffsetDateTime {
self.0.get_or_insert_with(Self::now_local)
}
pub fn format(&mut self, fmt: &(impl Formattable + ?Sized)) -> String {
self.now().format(fmt).unwrap()
}
#[cfg(feature = "syslog_writer")]
pub(crate) fn format_rfc3339(&mut self) -> String {
self.format(&time::format_description::well_known::Rfc3339)
}
pub fn force_utc() {
let mut guard = FORCE_UTC.lock().unwrap();
match *guard {
Some(false) => {
panic!("offset is already initialized not to enforce UTC");
}
Some(true) => {
}
None => *guard = Some(true),
}
}
#[doc(hidden)]
#[must_use]
pub fn now_local() -> OffsetDateTime {
OffsetDateTime::now_utc().to_offset(*OFFSET)
}
}
lazy_static::lazy_static! {
static ref OFFSET: UtcOffset = {
let mut force_utc_guard = FORCE_UTC.lock().unwrap();
if let Some(true) = *force_utc_guard { UtcOffset::UTC } else {
if force_utc_guard.is_none() {
*force_utc_guard = Some(false);
}
#[cfg(feature = "use_chrono_for_offset")]
{
let chrono_offset_seconds = Local::now().offset().fix().local_minus_utc();
UtcOffset::from_whole_seconds(chrono_offset_seconds).unwrap()
}
#[cfg(not(feature = "use_chrono_for_offset"))]
{
match OffsetDateTime::now_local() {
Ok(ts) => {ts.offset()},
Err(e) => {
eprint_err(
ERRCODE::Time,
"flexi_logger has to work with UTC rather than with local time",
&e,
);
UtcOffset::UTC
}
}
}
}
};
}
lazy_static::lazy_static! {
static ref FORCE_UTC: Arc<Mutex<Option<bool>>> =
Arc::new(Mutex::new(None));
}
#[cfg(test)]
mod test {
#[test]
fn test_deferred_now() {
let mut deferred_now = super::DeferredNow::new();
let once = deferred_now.now().to_string();
println!("This should be the current timestamp: {}", once);
std::thread::sleep(std::time::Duration::from_millis(300));
let again = deferred_now.now().to_string();
println!("This must be the same timestamp: {}", again);
assert_eq!(once, again);
}
}