130 lines
3.1 KiB
Rust
130 lines
3.1 KiB
Rust
use std::ffi::c_int;
|
|
use std::fmt::{Display, Formatter};
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
// Convert seconds since epoch to YYYY-MM-DD HH:MM:SS (UTC)
|
|
// Define the Tm struct from the C standard library
|
|
#[repr(C)]
|
|
#[derive(Debug, Copy, Clone)]
|
|
struct Tm {
|
|
tm_sec: c_int, // Seconds (0-60)
|
|
tm_min: c_int, // Minutes (0-59)
|
|
tm_hour: c_int, // Hours (0-23)
|
|
tm_mday: c_int, // Day of the month (1-31)
|
|
tm_mon: c_int, // Month (0-11)
|
|
tm_year: c_int, // Year since 1900
|
|
tm_wday: c_int, // Day of the week (0-6, Sunday = 0)
|
|
tm_yday: c_int, // Day of the year (0-365)
|
|
tm_isdst: c_int, // Daylight saving time flag
|
|
}
|
|
|
|
unsafe extern "C" {
|
|
fn localtime_r(timep: *const i64, result: *mut Tm) -> *mut Tm;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Time {
|
|
year: i32,
|
|
month: i32,
|
|
day: i32,
|
|
hour: i32,
|
|
minute: i32,
|
|
second: i32,
|
|
}
|
|
|
|
impl Time {
|
|
pub fn now() -> Result<Self, TimeError> {
|
|
let now = SystemTime::now();
|
|
Time::try_from(now)
|
|
}
|
|
/// seconds: seconds since epoch
|
|
pub fn new(seconds: i64) -> Result<Self, TimeError> {
|
|
let mut tm: Tm = unsafe { std::mem::zeroed() };
|
|
// Call localtime_r with a pointer to our Tm struct
|
|
let result = unsafe { localtime_r(&seconds, &mut tm) };
|
|
|
|
// Check if the conversion was successful
|
|
if result.is_null() {
|
|
return Err(TimeError::InvalidTime);
|
|
}
|
|
|
|
Ok(tm.into())
|
|
}
|
|
|
|
/// Getter for year
|
|
pub fn year(&self) -> i32 {
|
|
self.year
|
|
}
|
|
|
|
/// Getter for month
|
|
pub fn month(&self) -> i32 {
|
|
self.month
|
|
}
|
|
|
|
/// Getter for day
|
|
pub fn day(&self) -> i32 {
|
|
self.day
|
|
}
|
|
|
|
/// Getter for hour
|
|
pub fn hour(&self) -> i32 {
|
|
self.hour
|
|
}
|
|
|
|
/// Getter for minute
|
|
pub fn minute(&self) -> i32 {
|
|
self.minute
|
|
}
|
|
|
|
/// Getter for second
|
|
pub fn second(&self) -> i32 {
|
|
self.second
|
|
}
|
|
|
|
pub fn format_time(&self) -> String {
|
|
format!(
|
|
"{:04}-{:02}-{:02} {:02}:{:02}:{:02}",
|
|
self.year, self.month, self.day, self.hour, self.minute, self.second
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Display for Time {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.format_time())
|
|
}
|
|
}
|
|
|
|
impl TryFrom<SystemTime> for Time {
|
|
type Error = TimeError; // Define an appropriate error type
|
|
|
|
fn try_from(time: SystemTime) -> Result<Self, Self::Error> {
|
|
let seconds = time.duration_since(UNIX_EPOCH)?.as_secs() as i64;
|
|
Time::new(seconds)
|
|
}
|
|
}
|
|
|
|
impl From<Tm> for Time {
|
|
fn from(tm: Tm) -> Self {
|
|
Self {
|
|
year: tm.tm_year + 1900,
|
|
month: tm.tm_mon + 1,
|
|
day: tm.tm_mday,
|
|
hour: tm.tm_hour,
|
|
minute: tm.tm_min,
|
|
second: tm.tm_sec,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum TimeError {
|
|
SystemTimeError(std::time::SystemTimeError),
|
|
InvalidTime,
|
|
}
|
|
|
|
impl From<std::time::SystemTimeError> for TimeError {
|
|
fn from(err: std::time::SystemTimeError) -> Self {
|
|
TimeError::SystemTimeError(err)
|
|
}
|
|
}
|