hinoirisetr 1.2.0

A daemon to dim the screen at night
Documentation
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)
    }
}