use crate::sys;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[derive(Clone, Copy, Default)]
#[repr(transparent)]
pub struct Timestamp(pub(crate) sys::sCP56Time2a);
impl Timestamp {
pub fn from_ms(timestamp_ms: u64) -> Self {
let mut time = sys::sCP56Time2a::default();
unsafe {
sys::CP56Time2a_setFromMsTimestamp(&mut time, timestamp_ms);
}
Self(time)
}
pub fn now() -> Self {
let ms = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or(Duration::ZERO)
.as_millis() as u64;
Self::from_ms(ms)
}
pub fn as_ms(&self) -> u64 {
unsafe { sys::CP56Time2a_toMsTimestamp(&self.0 as *const _ as *mut _) }
}
pub fn millisecond(&self) -> u16 {
unsafe { sys::CP56Time2a_getMillisecond(&self.0 as *const _ as *mut _) as u16 }
}
pub fn second(&self) -> u8 {
unsafe { sys::CP56Time2a_getSecond(&self.0 as *const _ as *mut _) as u8 }
}
pub fn minute(&self) -> u8 {
unsafe { sys::CP56Time2a_getMinute(&self.0 as *const _ as *mut _) as u8 }
}
pub fn hour(&self) -> u8 {
unsafe { sys::CP56Time2a_getHour(&self.0 as *const _ as *mut _) as u8 }
}
pub fn day(&self) -> u8 {
unsafe { sys::CP56Time2a_getDayOfMonth(&self.0 as *const _ as *mut _) as u8 }
}
pub fn month(&self) -> u8 {
unsafe { sys::CP56Time2a_getMonth(&self.0 as *const _ as *mut _) as u8 }
}
pub fn year(&self) -> u16 {
let raw = unsafe { sys::CP56Time2a_getYear(&self.0 as *const _ as *mut _) as u16 };
2000 + raw
}
pub fn is_invalid(&self) -> bool {
unsafe { sys::CP56Time2a_isInvalid(&self.0 as *const _ as *mut _) }
}
pub fn is_substituted(&self) -> bool {
unsafe { sys::CP56Time2a_isSubstituted(&self.0 as *const _ as *mut _) }
}
pub fn is_summer_time(&self) -> bool {
unsafe { sys::CP56Time2a_isSummerTime(&self.0 as *const _ as *mut _) }
}
pub fn as_raw(&self) -> &sys::sCP56Time2a {
&self.0
}
pub fn as_raw_mut(&mut self) -> &mut sys::sCP56Time2a {
&mut self.0
}
}
impl std::fmt::Debug for Timestamp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}",
self.year(),
self.month(),
self.day(),
self.hour(),
self.minute(),
self.second(),
self.millisecond()
)
}
}
impl std::fmt::Display for Timestamp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
impl From<u64> for Timestamp {
fn from(ms: u64) -> Self {
Self::from_ms(ms)
}
}
impl From<Timestamp> for u64 {
fn from(ts: Timestamp) -> u64 {
ts.as_ms()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_timestamp_roundtrip() {
let original_ms: u64 = 1701705600000; let ts = Timestamp::from_ms(original_ms);
let recovered = ts.as_ms();
assert!((original_ms as i64 - recovered as i64).abs() < 1000);
}
#[test]
fn test_timestamp_now() {
let ts = Timestamp::now();
assert!(ts.year() >= 2024);
}
}