use chrono::{DateTime, Local, Utc, offset};
use std::time::{Duration, Instant};
pub fn now() -> String {
Local::now().to_string()
}
pub fn timestamp() -> i64 {
Utc::now().timestamp()
}
pub fn from_timestamp(secs: i64, nsecs: u32) -> String {
if let Some(value) = DateTime::from_timestamp(secs, nsecs) {
value.with_timezone(&offset::Local).to_string()
} else {
String::new()
}
}
#[derive(Debug, Clone, Copy)]
pub struct Stopwatch {
start: Instant,
}
impl Stopwatch {
pub fn new() -> Self {
Self {
start: Instant::now(),
}
}
pub fn elapsed(&self) -> Duration {
self.start.elapsed()
}
pub fn elapsed_ms(&self) -> u32 {
u32::try_from(self.elapsed().as_millis()).unwrap_or(u32::MAX)
}
pub fn elapsed_us(&self) -> u64 {
u64::try_from(self.elapsed().as_micros()).unwrap_or(u64::MAX)
}
pub fn elapsed_human(&self) -> String {
humantime::format_duration(self.elapsed()).to_string()
}
}
impl Default for Stopwatch {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn sub_millisecond_reports_zero_not_one() {
let sw = Stopwatch::new();
assert_eq!(
sw.elapsed_ms(),
0,
"亚毫秒操作应报 0,此前被 .max(1) 抬成 1"
);
}
#[test]
fn microsecond_resolution_is_available() {
let sw = Stopwatch::new();
std::thread::sleep(Duration::from_millis(2));
assert!(sw.elapsed_ms() >= 2);
assert!(
sw.elapsed_us() >= 2_000,
"微秒读数应至少与毫秒读数一致,实际 {}",
sw.elapsed_us()
);
}
#[test]
fn elapsed_is_monotonic() {
let sw = Stopwatch::new();
let first = sw.elapsed_us();
std::thread::sleep(Duration::from_millis(1));
assert!(sw.elapsed_us() > first);
}
}