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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#![cfg_attr(docsrs, doc(cfg(feature = "rustc-serialize")))]
use super::DateTime;
#[cfg(feature = "clock")]
use crate::offset::Local;
use crate::offset::{FixedOffset, LocalResult, TimeZone, Utc};
use core::fmt;
use core::ops::Deref;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
impl<Tz: TimeZone> Encodable for DateTime<Tz> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
format!("{:?}", self).encode(s)
}
}
// lik? function to convert a LocalResult into a serde-ish Result
fn from<T, D>(me: LocalResult<T>, d: &mut D) -> Result<T, D::Error>
where
D: Decoder,
T: fmt::Display,
{
match me {
LocalResult::None => Err(d.error("value is not a legal timestamp")),
LocalResult::Ambiguous(..) => Err(d.error("value is an ambiguous timestamp")),
LocalResult::Single(val) => Ok(val),
}
}
impl Decodable for DateTime<FixedOffset> {
fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<FixedOffset>, D::Error> {
d.read_str()?.parse::<DateTime<FixedOffset>>().map_err(|_| d.error("invalid date and time"))
}
}
#[allow(deprecated)]
impl Decodable for TsSeconds<FixedOffset> {
#[allow(deprecated)]
fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<FixedOffset>, D::Error> {
from(FixedOffset::east_opt(0).unwrap().timestamp_opt(d.read_i64()?, 0), d).map(TsSeconds)
}
}
impl Decodable for DateTime<Utc> {
fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<Utc>, D::Error> {
d.read_str()?
.parse::<DateTime<FixedOffset>>()
.map(|dt| dt.with_timezone(&Utc))
.map_err(|_| d.error("invalid date and time"))
}
}
/// A [`DateTime`] that can be deserialized from a timestamp
///
/// A timestamp here is seconds since the epoch
#[derive(Debug)]
pub struct TsSeconds<Tz: TimeZone>(DateTime<Tz>);
#[allow(deprecated)]
impl<Tz: TimeZone> From<TsSeconds<Tz>> for DateTime<Tz> {
/// Pull the inner `DateTime<Tz>` out
#[allow(deprecated)]
fn from(obj: TsSeconds<Tz>) -> DateTime<Tz> {
obj.0
}
}
#[allow(deprecated)]
impl<Tz: TimeZone> Deref for TsSeconds<Tz> {
type Target = DateTime<Tz>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[allow(deprecated)]
impl Decodable for TsSeconds<Utc> {
fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Utc>, D::Error> {
from(Utc.timestamp_opt(d.read_i64()?, 0), d).map(TsSeconds)
}
}
#[cfg(feature = "clock")]
#[cfg_attr(docsrs, doc(cfg(feature = "clock")))]
impl Decodable for DateTime<Local> {
fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<Local>, D::Error> {
match d.read_str()?.parse::<DateTime<FixedOffset>>() {
Ok(dt) => Ok(dt.with_timezone(&Local)),
Err(_) => Err(d.error("invalid date and time")),
}
}
}
#[cfg(feature = "clock")]
#[cfg_attr(docsrs, doc(cfg(feature = "clock")))]
#[allow(deprecated)]
impl Decodable for TsSeconds<Local> {
#[allow(deprecated)]
fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Local>, D::Error> {
from(Utc.timestamp_opt(d.read_i64()?, 0), d).map(|dt| TsSeconds(dt.with_timezone(&Local)))
}
}
#[cfg(test)]
use rustc_serialize::json;
#[test]
fn test_encodable() {
super::test_encodable_json(json::encode, json::encode);
}
#[cfg(feature = "clock")]
#[test]
fn test_decodable() {
super::test_decodable_json(json::decode, json::decode, json::decode);
}
#[cfg(feature = "clock")]
#[test]
fn test_decodable_timestamps() {
super::test_decodable_json_timestamps(json::decode, json::decode, json::decode);
}
|