From 0964d50bb32dcd69b77a7d4e3074e0a2845dccce Mon Sep 17 00:00:00 2001 From: Asuna Date: Mon, 19 Aug 2024 06:19:17 +0800 Subject: [PATCH] Don't convert `SystemTime` to `DateTime` if cache has not expired --- spdlog/src/formatter/local_time_cacher.rs | 56 +++++++++++++++-------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/spdlog/src/formatter/local_time_cacher.rs b/spdlog/src/formatter/local_time_cacher.rs index ddae4f25..345d9e3c 100644 --- a/spdlog/src/formatter/local_time_cacher.rs +++ b/spdlog/src/formatter/local_time_cacher.rs @@ -21,7 +21,7 @@ where #[derive(Clone)] pub(crate) struct LocalTimeCacher { - stored_key: i64, + stored_key: u64, cache_values: Option, } @@ -74,30 +74,19 @@ impl LocalTimeCacher { #[must_use] pub(crate) fn get(&mut self, system_time: SystemTime) -> TimeDate { - self.get_inner(system_time.into()) - } - - fn get_inner(&mut self, utc_time: DateTime) -> TimeDate { - const LEAP_BOUNDARY: u32 = 1_000_000_000; - - let nanosecond = utc_time.nanosecond(); - let is_leap_second = nanosecond >= LEAP_BOUNDARY; - let reduced_nanosecond = if is_leap_second { - nanosecond - LEAP_BOUNDARY - } else { - nanosecond - }; - let millisecond = reduced_nanosecond / 1_000_000; + let since_epoch = system_time.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let nanosecond = since_epoch.subsec_nanos(); + let millisecond = nanosecond / 1_000_000; - let cache_key = utc_time.timestamp(); + let cache_key = since_epoch.as_secs(); if self.cache_values.is_none() || self.stored_key != cache_key { - self.cache_values = Some(CacheValues::new(utc_time)); + self.cache_values = Some(CacheValues::new(system_time)); self.stored_key = cache_key; } TimeDate { cached: self.cache_values.as_mut().unwrap(), - nanosecond: reduced_nanosecond, + nanosecond, millisecond, } } @@ -299,9 +288,9 @@ impl<'a> TimeDate<'a> { impl CacheValues { #[must_use] - fn new(utc_time: DateTime) -> Self { + fn new(system_time: SystemTime) -> Self { CacheValues { - local_time: utc_time.into(), + local_time: system_time.into(), full_second_str: None, year: None, year_str: None, @@ -372,3 +361,30 @@ impl fmt::Debug for TimeDateLazyLocked<'_> { .finish() } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn validation() { + let mut cacher = LocalTimeCacher::new(); + + let begin = SystemTime::now(); + loop { + let now = SystemTime::now(); + if now.duration_since(begin).unwrap().as_secs() >= 3 { + break; + } + let from_cache = cacher.get(now); + let from_chrono = DateTime::::from(now); + + assert_eq!( + from_cache.cached.local_time.with_nanosecond(0), + from_chrono.with_nanosecond(0) + ); + assert_eq!(from_cache.nanosecond, from_chrono.nanosecond()); + assert_eq!(from_cache.millisecond, from_chrono.nanosecond() / 1_000_000); + } + } +}