Skip to content

Commit

Permalink
Add method to create model::Timestamp from a UNIX timestamp (#1790)
Browse files Browse the repository at this point in the history
The valid range of UNIX timestamp values depends on the underlying
crate implementation (`chrono` or `time`) and the feature flags enabled
(`time` with `large-dates`).
  • Loading branch information
nickelc authored and arqunis committed Apr 18, 2022
1 parent 36eac42 commit 66f8be7
Showing 1 changed file with 46 additions and 1 deletion.
47 changes: 46 additions & 1 deletion src/model/timestamp.rs
Expand Up @@ -34,7 +34,7 @@ use std::ops::Deref;
use std::str::FromStr;

#[cfg(not(feature = "time"))]
use chrono::{DateTime, TimeZone, Utc};
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
use serde::{Deserialize, Serialize};
#[cfg(feature = "time")]
use time::format_description::well_known::Rfc3339;
Expand Down Expand Up @@ -96,6 +96,15 @@ impl Timestamp {
Self(OffsetDateTime::now_utc())
}

/// Create a new `Timestamp` from a UNIX timestamp.
///
/// Returns `Err` if the value is invalid. The valid range of the value may vary depending on
/// the feature flags enabled (`time` with `large-dates`).
pub fn from_unix_timestamp(secs: i64) -> Result<Self, InvalidTimestamp> {
let dt = OffsetDateTime::from_unix_timestamp(secs).map_err(|_| InvalidTimestamp)?;
Ok(Self(dt))
}

/// Returns the number of non-leap seconds since January 1, 1970 0:00:00 UTC
pub fn unix_timestamp(&self) -> i64 {
self.0.unix_timestamp()
Expand Down Expand Up @@ -134,6 +143,16 @@ impl Timestamp {
Self(Utc::now())
}

/// Create a new `Timestamp` from a UNIX timestamp.
///
/// # Errors
///
/// Returns `Err` if the value is invalid.
pub fn from_unix_timestamp(secs: i64) -> Result<Self, InvalidTimestamp> {
let dt = NaiveDateTime::from_timestamp_opt(secs, 0).ok_or(InvalidTimestamp)?;
Ok(Self(DateTime::from_utc(dt, Utc)))
}

/// Returns the number of non-leap seconds since January 1, 1970 0:00:00 UTC
pub fn unix_timestamp(&self) -> i64 {
self.0.timestamp()
Expand Down Expand Up @@ -161,6 +180,17 @@ impl Timestamp {
}
}

#[derive(Debug)]
pub struct InvalidTimestamp;

impl std::error::Error for InvalidTimestamp {}

impl fmt::Display for InvalidTimestamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("invalid UNIX timestamp value")
}
}

#[cfg(not(feature = "time"))]
use chrono::ParseError as InnerError;
#[cfg(feature = "time")]
Expand Down Expand Up @@ -260,3 +290,18 @@ impl From<OffsetDateTime> for Timestamp {
Self(dt)
}
}

#[cfg(test)]
mod tests {
use super::Timestamp;

#[test]
fn from_unix_timestamp() {
let timestamp = Timestamp::from_unix_timestamp(1462015105).unwrap();
assert_eq!(timestamp.unix_timestamp(), 1462015105);
#[cfg(not(feature = "time"))]
assert_eq!(timestamp.to_string(), "2016-04-30T11:18:25.000Z");
#[cfg(feature = "time")]
assert_eq!(timestamp.to_string(), "2016-04-30T11:18:25Z");
}
}

0 comments on commit 66f8be7

Please sign in to comment.