use chrono::{DateTime, Local, Utc};
use std::time::Instant as StdInstant;
pub use std::time::SystemTime;
pub use chrono::Duration;
#[derive(Debug, Clone, Copy)]
pub struct Instant {
inner: StdInstant,
}
impl Instant {
pub fn duration_since(&self, earlier: &Instant) -> Duration {
let elapsed = self.inner.duration_since(earlier.inner);
Duration::from_std(elapsed).unwrap_or_else(|_| Duration::zero())
}
}
pub fn now() -> Instant {
Instant {
inner: StdInstant::now(),
}
}
pub fn timestamp() -> i64 {
Utc::now().timestamp()
}
pub fn now_millis() -> i64 {
Utc::now().timestamp_millis()
}
pub fn now_string() -> String {
Utc::now().to_rfc3339()
}
pub fn now_local() -> String {
Local::now().to_rfc3339()
}
pub fn parse(s: &str) -> Result<i64, String> {
s.parse::<DateTime<Utc>>()
.map(|dt| dt.timestamp())
.map_err(|e| e.to_string())
}
pub fn parse_format(s: &str, fmt: &str) -> Result<i64, String> {
DateTime::parse_from_str(s, fmt)
.map(|dt| dt.timestamp())
.map_err(|e| e.to_string())
}
pub fn format(timestamp: i64, format: &str) -> String {
DateTime::from_timestamp(timestamp, 0)
.unwrap_or_else(Utc::now)
.format(format)
.to_string()
}
pub fn sleep(secs: u64) {
std::thread::sleep(std::time::Duration::from_secs(secs));
}
pub fn sleep_millis(millis: u64) {
std::thread::sleep(std::time::Duration::from_millis(millis));
}
pub fn add_seconds(timestamp: i64, seconds: i64) -> i64 {
DateTime::from_timestamp(timestamp, 0)
.and_then(|dt| dt.checked_add_signed(Duration::seconds(seconds)))
.map(|dt| dt.timestamp())
.unwrap_or(timestamp)
}
pub fn add_days(timestamp: i64, days: i64) -> i64 {
DateTime::from_timestamp(timestamp, 0)
.and_then(|dt| dt.checked_add_signed(Duration::days(days)))
.map(|dt| dt.timestamp())
.unwrap_or(timestamp)
}
pub fn duration_secs(start: i64, end: i64) -> i64 {
end - start
}
pub fn duration_millis(start: i64, end: i64) -> i64 {
(end - start) * 1000
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_now() {
let ts = timestamp();
assert!(ts > 1_600_000_000); }
#[test]
fn test_now_string() {
let s = now_string();
assert!(s.contains('T')); assert!(s.contains('Z') || s.contains('+'));
}
#[test]
fn test_parse() {
let result = parse("2024-01-01T00:00:00Z");
assert!(result.is_ok());
}
#[test]
fn test_add_seconds() {
let ts = 1_700_000_000i64;
let new_ts = add_seconds(ts, 3600);
assert_eq!(new_ts, ts + 3600);
}
#[test]
fn test_add_days() {
let ts = 1_700_000_000i64;
let new_ts = add_days(ts, 1);
assert_eq!(new_ts, ts + 86400);
}
}