Created
December 11, 2017 02:39
-
-
Save Gricha/21d58b59fb65fb4eeb5f0af8640ca4a2 to your computer and use it in GitHub Desktop.
Timestamp from String
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
use std::fmt; | |
use serde::de; | |
use chrono::{DateTime, Utc, FixedOffset}; | |
use chrono::offset::{LocalResult, TimeZone}; | |
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error> | |
where D: de::Deserializer<'de> | |
{ | |
Ok(try!(d.deserialize_i64(SecondsTimestampVisitor).map(|dt| dt.with_timezone(&Utc)))) | |
} | |
struct SecondsTimestampVisitor; | |
impl<'de> de::Visitor<'de> for SecondsTimestampVisitor { | |
type Value = DateTime<FixedOffset>; | |
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result | |
{ | |
write!(formatter, "a unix timestamp in seconds") | |
} | |
/// Deserialize a timestamp in seconds since the epoch | |
fn visit_i64<E>(self, value: i64) -> Result<DateTime<FixedOffset>, E> | |
where E: de::Error | |
{ | |
from(FixedOffset::east(0).timestamp_opt(value, 0), &value) | |
} | |
/// Deserialize a timestamp in seconds since the epoch | |
fn visit_u64<E>(self, value: u64) -> Result<DateTime<FixedOffset>, E> | |
where E: de::Error | |
{ | |
from(FixedOffset::east(0).timestamp_opt(value as i64, 0), &value) | |
} | |
fn visit_str<E>(self, value: &str) -> Result<DateTime<FixedOffset>, E> | |
where E: de::Error | |
{ | |
let ts: i64 = value.parse() | |
.map_err(|e| E::custom(format!("Unable to parse timestamp as int: {}", e)))?; | |
self.visit_i64(ts) | |
} | |
} | |
// try!-like function to convert a LocalResult into a serde-ish Result | |
fn from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E> | |
where E: de::Error, | |
V: fmt::Display, | |
T: fmt::Display, | |
{ | |
match me { | |
LocalResult::None => Err(E::custom( | |
format!("value is not a legal timestamp: {}", ts))), | |
LocalResult::Ambiguous(min, max) => Err(E::custom( | |
format!("value is an ambiguous timestamp: {}, could be either of {}, {}", | |
ts, min, max))), | |
LocalResult::Single(val) => Ok(val) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment