ttf_view/types/
longdatetime.rs1use chrono::{DateTime, NaiveDate, NaiveDateTime, TimeDelta, Utc};
2use std::fmt;
3
4#[derive(Copy, Hash)]
5#[derive_const(Clone, PartialEq, Eq)]
6#[repr(transparent)]
7pub struct LongDateTime([u8; 8]);
8
9const EPOCH_NAIVE: NaiveDateTime =
10 NaiveDate::from_ymd_opt(1904, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
11
12impl LongDateTime {
13 pub const EPOCH: DateTime<Utc> = EPOCH_NAIVE.and_utc();
14
15 pub const fn new(datetime: DateTime<Utc>) -> Self {
16 let delta = datetime.naive_utc().signed_duration_since(EPOCH_NAIVE);
17 Self::from_epoch_seconds(delta.num_seconds())
18 }
19 pub const fn datetime(&self) -> Option<DateTime<Utc>> {
20 let delta = TimeDelta::try_seconds(self.epoch_seconds())?;
21 Some(EPOCH_NAIVE.checked_add_signed(delta)?.and_utc())
22 }
23
24 pub const fn from_epoch_seconds(secs: i64) -> Self {
25 Self(i64::to_be_bytes(secs))
26 }
27 pub const fn epoch_seconds(&self) -> i64 {
28 i64::from_be_bytes(self.0)
29 }
30
31 pub const fn from_be_bytes(bytes: [u8; 8]) -> Self {
32 Self(bytes)
33 }
34 pub const fn to_be_bytes(self) -> [u8; 8] {
35 self.0
36 }
37}
38
39#[allow(clippy::derivable_impls)]
41const impl Default for LongDateTime {
42 fn default() -> Self {
43 Self([0; 8])
44 }
45}
46const impl PartialOrd for LongDateTime {
48 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
49 Some(self.cmp(other))
50 }
51}
52const impl Ord for LongDateTime {
53 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
54 self.epoch_seconds().cmp(&other.epoch_seconds())
55 }
56}
57
58impl fmt::Debug for LongDateTime {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 match self.datetime() {
61 Some(datetime) => datetime.fmt(f),
62 None => write!(f, "{:#010X}", self.epoch_seconds()),
64 }
65 }
66}
67
68const impl From<DateTime<Utc>> for LongDateTime {
69 fn from(value: DateTime<Utc>) -> Self {
70 Self::new(value)
71 }
72}
73const impl TryFrom<LongDateTime> for DateTime<Utc> {
74 type Error = ();
75 fn try_from(value: LongDateTime) -> Result<Self, Self::Error> {
76 value.datetime().ok_or(())
77 }
78}