-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatetime.rs
More file actions
85 lines (70 loc) · 2.7 KB
/
datetime.rs
File metadata and controls
85 lines (70 loc) · 2.7 KB
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use binary_codec::{BinaryDeserializer, BinarySerializer};
use chrono::{DateTime, Duration, TimeZone, Utc};
use serde::{Deserialize, Serialize};
/// Plabble DateTime since epoch (01-01-2025T00:00:00Z)
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[serde(transparent)]
pub struct PlabbleDateTime(pub DateTime<Utc>);
/// Plabble Epoch
fn epoch() -> DateTime<Utc> {
Utc.with_ymd_and_hms(2025, 1, 1, 0, 0, 0).unwrap()
}
impl PlabbleDateTime {
/// Returns the number of seconds since the Plabble epoch
pub fn timestamp(&self) -> u32 {
(self.0 - epoch()).num_seconds() as u32
}
/// Creates a PlabbleDateTime from a number of seconds since the epoch
pub fn new(timestamp: u32) -> Self {
Self(epoch() + Duration::seconds(timestamp as i64))
}
/// Creates a PlabbleDateTime for a given number of seconds in the future from now
pub fn from_now(seconds: u32) -> Self {
Self(Utc::now() + Duration::seconds(seconds as i64))
}
}
impl<T: Clone> BinarySerializer<T> for PlabbleDateTime {
fn write_bytes(
&self,
stream: &mut binary_codec::BitStreamWriter,
_: Option<&mut binary_codec::SerializerConfig<T>>,
) -> Result<(), binary_codec::SerializationError> {
stream.write_fixed_int(self.timestamp());
Ok(())
}
}
impl<T: Clone> BinaryDeserializer<T> for PlabbleDateTime {
fn read_bytes(
stream: &mut binary_codec::BitStreamReader,
_: Option<&mut binary_codec::SerializerConfig<T>>,
) -> Result<Self, binary_codec::DeserializationError> {
let seconds: u32 = stream.read_fixed_int()?;
Ok(PlabbleDateTime::new(seconds))
}
}
#[cfg(test)]
mod tests {
use std::u32;
use binary_codec::{BinaryDeserializer, BinarySerializer};
use chrono::{TimeZone, Utc};
use super::PlabbleDateTime;
#[test]
fn can_convert_to_seconds_from_epoch_and_back() {
let date = Utc.with_ymd_and_hms(2025, 5, 25, 12, 30, 0).unwrap();
let expected_seconds = 12_486_600u32;
let expected_bytes = u32::to_be_bytes(expected_seconds);
let bytes = BinarySerializer::<()>::to_bytes(&PlabbleDateTime(date), None).unwrap();
assert_eq!(bytes, expected_bytes);
assert_eq!(bytes, vec![0, 190, 135, 200]);
let deserialized: PlabbleDateTime =
BinaryDeserializer::<()>::from_bytes(&bytes, None).unwrap();
assert_eq!(deserialized.0, date);
}
#[test]
fn plabble_datetime_max_value() {
let max_bytes = u32::MAX.to_be_bytes();
let max_date: PlabbleDateTime =
BinaryDeserializer::<()>::from_bytes(&max_bytes, None).unwrap();
assert_eq!("2161-02-07T06:28:15+00:00", max_date.0.to_rfc3339());
}
}