summaryrefslogtreecommitdiff
path: root/library/std/src/sys/solid/time.rs
blob: f83f1644fe854483629bde2c4fbefed46c07ec15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use super::{abi, error::expect_success};
use crate::{mem::MaybeUninit, time::Duration};

pub use super::itron::time::Instant;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct SystemTime(abi::time_t);

pub const UNIX_EPOCH: SystemTime = SystemTime(0);

impl SystemTime {
    pub fn now() -> SystemTime {
        let rtc = unsafe {
            let mut out = MaybeUninit::zeroed();
            expect_success(abi::SOLID_RTC_ReadTime(out.as_mut_ptr()), &"SOLID_RTC_ReadTime");
            out.assume_init()
        };
        let t = unsafe {
            libc::mktime(&mut libc::tm {
                tm_sec: rtc.tm_sec,
                tm_min: rtc.tm_min,
                tm_hour: rtc.tm_hour,
                tm_mday: rtc.tm_mday,
                tm_mon: rtc.tm_mon - 1,
                tm_year: rtc.tm_year,
                tm_wday: rtc.tm_wday,
                tm_yday: 0,
                tm_isdst: 0,
                tm_gmtoff: 0,
                tm_zone: crate::ptr::null_mut(),
            })
        };
        assert_ne!(t, -1, "mktime failed");
        SystemTime(t)
    }

    pub(super) fn from_time_t(t: abi::time_t) -> Self {
        Self(t)
    }

    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
        if self.0 >= other.0 {
            Ok(Duration::from_secs((self.0 as u64).wrapping_sub(other.0 as u64)))
        } else {
            Err(Duration::from_secs((other.0 as u64).wrapping_sub(self.0 as u64)))
        }
    }

    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
        Some(SystemTime(self.0.checked_add_unsigned(other.as_secs())?))
    }

    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
        Some(SystemTime(self.0.checked_sub_unsigned(other.as_secs())?))
    }
}