1use crate::{
3 core::{
4 optional::{gen_optional, NSTDOptional},
5 time::{
6 nstd_core_time_duration_get, nstd_core_time_duration_nanoseconds,
7 nstd_core_time_duration_new, nstd_core_time_duration_seconds, NSTDDuration,
8 },
9 },
10 NSTDFloat64, NSTDInt64, NSTDUInt32,
11};
12use core::mem::MaybeUninit;
13use libc::{clock_gettime, timespec, CLOCK_REALTIME};
14use nstdapi::nstdapi;
15
16#[nstdapi]
18#[derive(Clone, Copy, PartialEq)]
19pub struct NSTDUnixTime {
20 duration: NSTDDuration,
22}
23impl NSTDUnixTime {
24 #[inline]
26 #[allow(dead_code)]
27 pub(crate) const fn from_duration(duration: NSTDDuration) -> Self {
28 Self { duration }
29 }
30}
31impl From<timespec> for NSTDUnixTime {
32 #[allow(clippy::cast_precision_loss)]
34 fn from(value: timespec) -> Self {
35 const NANOS_IN_SEC: NSTDFloat64 = 1_000_000_000.0;
37 let mut seconds = value.tv_sec as _;
38 seconds += value.tv_nsec as NSTDFloat64 / NANOS_IN_SEC;
39 #[allow(unused_unsafe)]
40 unsafe {
42 Self {
43 duration: nstd_core_time_duration_new(seconds),
44 }
45 }
46 }
47}
48gen_optional!(NSTDUnixOptionalTime, NSTDUnixTime);
49
50#[inline]
57#[nstdapi]
58pub fn nstd_os_unix_time_now() -> NSTDUnixOptionalTime {
59 let mut timespec = MaybeUninit::uninit();
60 if unsafe { clock_gettime(CLOCK_REALTIME, timespec.as_mut_ptr()) } == 0 {
62 return NSTDOptional::Some(NSTDUnixTime::from(unsafe { timespec.assume_init() }));
64 }
65 NSTDOptional::None
66}
67
68#[inline]
79#[nstdapi]
80pub const fn nstd_os_unix_time_get(time: NSTDUnixTime) -> NSTDFloat64 {
81 nstd_core_time_duration_get(time.duration)
82}
83
84#[inline]
94#[nstdapi]
95pub const fn nstd_os_unix_time_seconds(time: NSTDUnixTime) -> NSTDInt64 {
96 nstd_core_time_duration_seconds(time.duration)
97}
98
99#[inline]
109#[nstdapi]
110pub fn nstd_os_unix_time_nanoseconds(time: NSTDUnixTime) -> NSTDUInt32 {
111 nstd_core_time_duration_nanoseconds(time.duration)
112}
113
114#[inline]
126#[nstdapi]
127pub fn nstd_os_unix_time_add(time: NSTDUnixTime, duration: NSTDDuration) -> NSTDUnixTime {
128 let secs = nstd_core_time_duration_get(time.duration) + nstd_core_time_duration_get(duration);
129 NSTDUnixTime {
130 duration: nstd_core_time_duration_new(secs),
131 }
132}
133
134#[inline]
146#[nstdapi]
147pub fn nstd_os_unix_time_sub(time: NSTDUnixTime, duration: NSTDDuration) -> NSTDUnixTime {
148 let secs = nstd_core_time_duration_get(time.duration) - nstd_core_time_duration_get(duration);
149 NSTDUnixTime {
150 duration: nstd_core_time_duration_new(secs),
151 }
152}