-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a DateTime32 type for 32-bit serialized times (#2210)
* Add a DateTime32 type for 32-bit serialized times * Use DateTime32 for MetaAddr.last_seen * Create and use a `DateTime32::now` method
- Loading branch information
Showing
9 changed files
with
153 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
//! DateTime types with specific serialization invariants. | ||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; | ||
use chrono::{TimeZone, Utc}; | ||
|
||
use std::{ | ||
convert::{TryFrom, TryInto}, | ||
fmt, | ||
num::TryFromIntError, | ||
}; | ||
|
||
use super::{SerializationError, ZcashDeserialize, ZcashSerialize}; | ||
|
||
/// A date and time, represented by a 32-bit number of seconds since the UNIX epoch. | ||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] | ||
pub struct DateTime32 { | ||
timestamp: u32, | ||
} | ||
|
||
impl DateTime32 { | ||
/// Returns the number of seconds since the UNIX epoch. | ||
pub fn timestamp(&self) -> u32 { | ||
self.timestamp | ||
} | ||
|
||
/// Returns the equivalent [`chrono::DateTime`]. | ||
pub fn to_chrono(self) -> chrono::DateTime<Utc> { | ||
self.into() | ||
} | ||
|
||
/// Returns the current time | ||
pub fn now() -> DateTime32 { | ||
Utc::now() | ||
.try_into() | ||
.expect("unexpected out of range chrono::DateTime") | ||
} | ||
} | ||
|
||
impl fmt::Debug for DateTime32 { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("DateTime32") | ||
.field("timestamp", &self.timestamp) | ||
.field("calendar", &chrono::DateTime::<Utc>::from(*self)) | ||
.finish() | ||
} | ||
} | ||
|
||
impl From<u32> for DateTime32 { | ||
fn from(value: u32) -> Self { | ||
DateTime32 { timestamp: value } | ||
} | ||
} | ||
|
||
impl From<&u32> for DateTime32 { | ||
fn from(value: &u32) -> Self { | ||
(*value).into() | ||
} | ||
} | ||
|
||
impl From<DateTime32> for chrono::DateTime<Utc> { | ||
fn from(value: DateTime32) -> Self { | ||
// chrono::DateTime is guaranteed to hold 32-bit values | ||
Utc.timestamp(value.timestamp.into(), 0) | ||
} | ||
} | ||
|
||
impl From<&DateTime32> for chrono::DateTime<Utc> { | ||
fn from(value: &DateTime32) -> Self { | ||
(*value).into() | ||
} | ||
} | ||
|
||
impl TryFrom<chrono::DateTime<Utc>> for DateTime32 { | ||
type Error = TryFromIntError; | ||
|
||
/// Convert from a [`chrono::DateTime`] to a [`DateTime32`], discarding any nanoseconds. | ||
/// | ||
/// Conversion fails if the number of seconds is outside the `u32` range. | ||
fn try_from(value: chrono::DateTime<Utc>) -> Result<Self, Self::Error> { | ||
Ok(Self { | ||
timestamp: value.timestamp().try_into()?, | ||
}) | ||
} | ||
} | ||
|
||
impl TryFrom<&chrono::DateTime<Utc>> for DateTime32 { | ||
type Error = TryFromIntError; | ||
|
||
/// Convert from a [`chrono::DateTime`] to a [`DateTime32`], discarding any nanoseconds. | ||
/// | ||
/// Conversion fails if the number of seconds is outside the `u32` range. | ||
fn try_from(value: &chrono::DateTime<Utc>) -> Result<Self, Self::Error> { | ||
(*value).try_into() | ||
} | ||
} | ||
|
||
impl ZcashSerialize for DateTime32 { | ||
fn zcash_serialize<W: std::io::Write>(&self, mut writer: W) -> Result<(), std::io::Error> { | ||
writer.write_u32::<LittleEndian>(self.timestamp) | ||
} | ||
} | ||
|
||
impl ZcashDeserialize for DateTime32 { | ||
fn zcash_deserialize<R: std::io::Read>(mut reader: R) -> Result<Self, SerializationError> { | ||
Ok(DateTime32 { | ||
timestamp: reader.read_u32::<LittleEndian>()?, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters