git_bug/replica/entity/
timestamp.rs

1// git-bug-rs - A rust library for interfacing with git-bug repositories
2//
3// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
4// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
7// This file is part of git-bug-rs/git-gub.
8//
9// You should have received a copy of the License along with this program.
10// If not, see <https://www.gnu.org/licenses/agpl.txt>.
11
12//! Handling of UNIX time stamps.
13
14use std::fmt::Display;
15
16use chrono::DateTime;
17use serde::{Deserialize, Serialize};
18
19/// An UNIX time stamp.
20///
21/// These should only ever be used for human-display, because timestamps are
22/// unreliably in a distributed system.
23/// Because of this reason, there is no `value()` function.
24// As explained in the toplevel doc comment, this Derive is only a implementation detail.
25#[allow(clippy::unsafe_derive_deserialize)]
26#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize)]
27pub struct TimeStamp {
28    value: u64,
29}
30impl From<u64> for TimeStamp {
31    fn from(value: u64) -> Self {
32        Self { value }
33    }
34}
35impl Display for TimeStamp {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        let date =
38            DateTime::from_timestamp(i64::try_from(self.value).expect("Should not wrap?"), 0)
39                .expect("This timestamp should be vaild");
40
41        let newdate = date.format("%Y-%m-%d %H:%M:%S");
42        f.write_str(newdate.to_string().as_str())
43    }
44}
45
46/// An UNIX time stamp.
47///
48/// These should only ever be used for human-display, because timestamps are
49/// unreliably in a distributed system.
50///
51/// This one allows underlying access to it's value and is only obtainable via
52/// `unsafe` code. The reason behind this is, that you might need to access this
53/// to improve the display for humans (i.e., sorting by date).
54#[derive(Debug, Default, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
55pub struct UnsafeTimeStamp {
56    /// The seconds since the UNIX epoch.
57    pub value: u64,
58}
59impl TimeStamp {
60    /// Turn this time stamp into one that exposes it's numerical value.
61    ///
62    /// # Safety
63    /// This is not really unsafe, but there is just no way your can trust a
64    /// time stamp in a distributed system. As such access to the raw value
65    /// could lead to bugs.
66    #[must_use]
67    pub unsafe fn to_unsafe(self) -> UnsafeTimeStamp {
68        UnsafeTimeStamp { value: self.value }
69    }
70}