|
21 | 21 |
|
22 | 22 | #[derive(Clone)]
|
23 | 23 | pub(crate) struct LocalTimeCacher {
|
24 |
| - stored_key: i64, |
| 24 | + stored_key: u64, |
25 | 25 | cache_values: Option<CacheValues>,
|
26 | 26 | }
|
27 | 27 |
|
@@ -74,30 +74,19 @@ impl LocalTimeCacher {
|
74 | 74 |
|
75 | 75 | #[must_use]
|
76 | 76 | pub(crate) fn get(&mut self, system_time: SystemTime) -> TimeDate {
|
77 |
| - self.get_inner(system_time.into()) |
78 |
| - } |
79 |
| - |
80 |
| - fn get_inner(&mut self, utc_time: DateTime<Utc>) -> TimeDate { |
81 |
| - const LEAP_BOUNDARY: u32 = 1_000_000_000; |
82 |
| - |
83 |
| - let nanosecond = utc_time.nanosecond(); |
84 |
| - let is_leap_second = nanosecond >= LEAP_BOUNDARY; |
85 |
| - let reduced_nanosecond = if is_leap_second { |
86 |
| - nanosecond - LEAP_BOUNDARY |
87 |
| - } else { |
88 |
| - nanosecond |
89 |
| - }; |
90 |
| - let millisecond = reduced_nanosecond / 1_000_000; |
| 77 | + let since_epoch = system_time.duration_since(SystemTime::UNIX_EPOCH).unwrap(); |
| 78 | + let nanosecond = since_epoch.subsec_nanos(); |
| 79 | + let millisecond = nanosecond / 1_000_000; |
91 | 80 |
|
92 |
| - let cache_key = utc_time.timestamp(); |
| 81 | + let cache_key = since_epoch.as_secs(); |
93 | 82 | if self.cache_values.is_none() || self.stored_key != cache_key {
|
94 |
| - self.cache_values = Some(CacheValues::new(utc_time)); |
| 83 | + self.cache_values = Some(CacheValues::new(system_time)); |
95 | 84 | self.stored_key = cache_key;
|
96 | 85 | }
|
97 | 86 |
|
98 | 87 | TimeDate {
|
99 | 88 | cached: self.cache_values.as_mut().unwrap(),
|
100 |
| - nanosecond: reduced_nanosecond, |
| 89 | + nanosecond, |
101 | 90 | millisecond,
|
102 | 91 | }
|
103 | 92 | }
|
@@ -299,9 +288,9 @@ impl<'a> TimeDate<'a> {
|
299 | 288 |
|
300 | 289 | impl CacheValues {
|
301 | 290 | #[must_use]
|
302 |
| - fn new(utc_time: DateTime<Utc>) -> Self { |
| 291 | + fn new(system_time: SystemTime) -> Self { |
303 | 292 | CacheValues {
|
304 |
| - local_time: utc_time.into(), |
| 293 | + local_time: system_time.into(), |
305 | 294 | full_second_str: None,
|
306 | 295 | year: None,
|
307 | 296 | year_str: None,
|
@@ -372,3 +361,30 @@ impl fmt::Debug for TimeDateLazyLocked<'_> {
|
372 | 361 | .finish()
|
373 | 362 | }
|
374 | 363 | }
|
| 364 | + |
| 365 | +#[cfg(test)] |
| 366 | +mod tests { |
| 367 | + use super::*; |
| 368 | + |
| 369 | + #[test] |
| 370 | + fn validation() { |
| 371 | + let mut cacher = LocalTimeCacher::new(); |
| 372 | + |
| 373 | + let begin = SystemTime::now(); |
| 374 | + loop { |
| 375 | + let now = SystemTime::now(); |
| 376 | + if now.duration_since(begin).unwrap().as_secs() >= 3 { |
| 377 | + break; |
| 378 | + } |
| 379 | + let from_cache = cacher.get(now); |
| 380 | + let from_chrono = DateTime::<Local>::from(now); |
| 381 | + |
| 382 | + assert_eq!( |
| 383 | + from_cache.cached.local_time.with_nanosecond(0), |
| 384 | + from_chrono.with_nanosecond(0) |
| 385 | + ); |
| 386 | + assert_eq!(from_cache.nanosecond, from_chrono.nanosecond()); |
| 387 | + assert_eq!(from_cache.millisecond, from_chrono.nanosecond() / 1_000_000); |
| 388 | + } |
| 389 | + } |
| 390 | +} |
0 commit comments