Skip to content

Commit 04d1fc8

Browse files
Joe DuranEmpty2k12
Joe Duran
authored andcommitted
Chrono types for Timestamp (#41)
1 parent 208e81f commit 04d1fc8

File tree

6 files changed

+158
-6
lines changed

6 files changed

+158
-6
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,5 @@ matrix:
5353
script: |
5454
export RUST_BACKTRACE=1 &&
5555
cargo build &&
56-
cargo test &&
56+
cargo test --all-features &&
5757
cargo doc --no-deps

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ tokio = "0.1.20"
2020
failure = "0.1.5"
2121
serde = { version = "1.0.92", optional = true }
2222
serde_json = { version = "1.0", optional = true }
23+
chrono = { version = "0.4.9", optional = true }
2324

2425
[features]
2526
use-serde = ["serde", "serde_json"]
27+
chrono_timestamps = ["chrono"]
2628
default = ["use-serde"]

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Pull requests are always welcome. See [Contributing](https://github.com/Empty2k1
3636
- Optional Serde Support for Deserialization
3737
- Running multiple queries in one request (e.g. `SELECT * FROM weather_berlin; SELECT * FROM weather_london`)
3838
- Authenticated and Unauthenticated Connections
39-
39+
- Optional conversion between `Timestamp` and `Chrono::DateTime<Utc>` via `chrono_timestamps` compilation feature
4040
### Planned Features
4141

4242
- Read Query Builder instead of supplying raw queries

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! - Optional Serde Support for Deserialization
1111
//! - Running multiple queries in one request (e.g. `SELECT * FROM weather_berlin; SELECT * FROM weather_london`)
1212
//! - Authenticated and Unauthenticated Connections
13-
//!
13+
//! - Optional conversion between `Timestamp` and `Chrono::DateTime<Utc>` via `chrono_timestamps` compilation feature
1414
//! ## Planned Features
1515
//!
1616
//! - Read Query Builder instead of supplying raw queries

src/query/consts.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub const MINUTES_PER_HOUR: usize = 60;
2+
pub const SECONDS_PER_MINUTE: usize = 60;
3+
pub const MILLIS_PER_SECOND: usize = 1000;
4+
pub const NANOS_PER_MILLI: usize = 1_000_000;
5+
6+
#[cfg(test)]
7+
pub const MICROS_PER_NANO: usize = 1000;

src/query/mod.rs

+146-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,26 @@
1919
//! assert!(read_query.is_ok());
2020
//! ```
2121
22+
#[cfg(feature = "chrono_timestamps")]
23+
extern crate chrono;
24+
25+
#[cfg(feature = "chrono_timestamps")]
26+
use chrono::prelude::{DateTime, TimeZone, Utc};
27+
#[cfg(feature = "chrono_timestamps")]
28+
use std::convert::TryInto;
29+
30+
#[cfg(feature = "chrono_timestamps")]
31+
pub mod consts;
2232
pub mod read_query;
2333
pub mod write_query;
24-
2534
use std::fmt;
2635

2736
use crate::{Error, ReadQuery, WriteQuery};
2837

29-
#[derive(PartialEq)]
38+
#[cfg(feature = "chrono_timestamps")]
39+
use consts::{MILLIS_PER_SECOND, MINUTES_PER_HOUR, NANOS_PER_MILLI, SECONDS_PER_MINUTE};
40+
41+
#[derive(PartialEq, Debug, Copy, Clone)]
3042
pub enum Timestamp {
3143
Now,
3244
Nanoseconds(usize),
@@ -48,6 +60,47 @@ impl fmt::Display for Timestamp {
4860
}
4961
}
5062

63+
#[cfg(feature = "chrono_timestamps")]
64+
impl Into<DateTime<Utc>> for Timestamp {
65+
fn into(self) -> DateTime<Utc> {
66+
match self {
67+
Timestamp::Now => Utc::now(),
68+
Timestamp::Hours(h) => {
69+
let nanos =
70+
h * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI;
71+
Utc.timestamp_nanos(nanos.try_into().unwrap())
72+
}
73+
Timestamp::Minutes(m) => {
74+
let nanos = m * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI;
75+
Utc.timestamp_nanos(nanos.try_into().unwrap())
76+
}
77+
Timestamp::Seconds(s) => {
78+
let nanos = s * MILLIS_PER_SECOND * NANOS_PER_MILLI;
79+
Utc.timestamp_nanos(nanos.try_into().unwrap())
80+
}
81+
Timestamp::Milliseconds(millis) => {
82+
let nanos = millis * NANOS_PER_MILLI;
83+
Utc.timestamp_nanos(nanos.try_into().unwrap())
84+
}
85+
Timestamp::Nanoseconds(nanos) => Utc.timestamp_nanos(nanos.try_into().unwrap()),
86+
Timestamp::Microseconds(mis) => {
87+
let nanos = mis / 10000;
88+
Utc.timestamp_nanos(nanos.try_into().unwrap())
89+
}
90+
}
91+
}
92+
}
93+
94+
#[cfg(feature = "chrono_timestamps")]
95+
impl<T> From<DateTime<T>> for Timestamp
96+
where
97+
T: TimeZone,
98+
{
99+
fn from(date_time: DateTime<T>) -> Self {
100+
Timestamp::Nanoseconds(date_time.timestamp_nanos() as usize)
101+
}
102+
}
103+
51104
/// Internal enum used to represent either type of query.
52105
pub enum QueryTypes<'a> {
53106
Read(&'a ReadQuery),
@@ -157,8 +210,17 @@ pub enum QueryType {
157210

158211
#[cfg(test)]
159212
mod tests {
213+
#[cfg(feature = "chrono_timestamps")]
214+
use std::convert::TryInto;
215+
#[cfg(feature = "chrono_timestamps")]
216+
extern crate chrono;
217+
#[cfg(feature = "chrono_timestamps")]
218+
use super::consts::{
219+
MICROS_PER_NANO, MILLIS_PER_SECOND, MINUTES_PER_HOUR, NANOS_PER_MILLI, SECONDS_PER_MINUTE,
220+
};
160221
use crate::query::{Timestamp, ValidQuery};
161-
222+
#[cfg(feature = "chrono_timestamps")]
223+
use chrono::prelude::{DateTime, TimeZone, Utc};
162224
#[test]
163225
fn test_equality_str() {
164226
assert_eq!(ValidQuery::from("hello"), "hello");
@@ -181,4 +243,85 @@ mod tests {
181243
fn test_format_for_timestamp_else() {
182244
assert!(format!("{}", Timestamp::Nanoseconds(100)) == "100");
183245
}
246+
247+
#[cfg(feature = "chrono_timestamps")]
248+
#[test]
249+
fn test_chrono_datetime_from_timestamp_now() {
250+
let datetime_from_timestamp: DateTime<Utc> = Timestamp::Now.into();
251+
assert_eq!(Utc::now().date(), datetime_from_timestamp.date())
252+
}
253+
#[cfg(feature = "chrono_timestamps")]
254+
#[test]
255+
fn test_chrono_datetime_from_timestamp_hours() {
256+
let datetime_from_timestamp: DateTime<Utc> = Timestamp::Hours(2).into();
257+
assert_eq!(
258+
Utc.timestamp_nanos(
259+
(2 * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI)
260+
.try_into()
261+
.unwrap()
262+
),
263+
datetime_from_timestamp
264+
)
265+
}
266+
#[cfg(feature = "chrono_timestamps")]
267+
#[test]
268+
fn test_chrono_datetime_from_timestamp_minutes() {
269+
let datetime_from_timestamp: DateTime<Utc> = Timestamp::Minutes(2).into();
270+
assert_eq!(
271+
Utc.timestamp_nanos(
272+
(2 * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI)
273+
.try_into()
274+
.unwrap()
275+
),
276+
datetime_from_timestamp
277+
)
278+
}
279+
#[cfg(feature = "chrono_timestamps")]
280+
#[test]
281+
fn test_chrono_datetime_from_timestamp_seconds() {
282+
let datetime_from_timestamp: DateTime<Utc> = Timestamp::Seconds(2).into();
283+
assert_eq!(
284+
Utc.timestamp_nanos(
285+
(2 * MILLIS_PER_SECOND * NANOS_PER_MILLI)
286+
.try_into()
287+
.unwrap()
288+
),
289+
datetime_from_timestamp
290+
)
291+
}
292+
#[cfg(feature = "chrono_timestamps")]
293+
#[test]
294+
fn test_chrono_datetime_from_timestamp_millis() {
295+
let datetime_from_timestamp: DateTime<Utc> = Timestamp::Milliseconds(2).into();
296+
assert_eq!(
297+
Utc.timestamp_nanos((2 * NANOS_PER_MILLI).try_into().unwrap()),
298+
datetime_from_timestamp
299+
)
300+
}
301+
302+
#[cfg(feature = "chrono_timestamps")]
303+
#[test]
304+
fn test_chrono_datetime_from_timestamp_nanos() {
305+
let datetime_from_timestamp: DateTime<Utc> = Timestamp::Nanoseconds(1).into();
306+
assert_eq!(Utc.timestamp_nanos(1), datetime_from_timestamp)
307+
}
308+
#[cfg(feature = "chrono_timestamps")]
309+
#[test]
310+
fn test_chrono_datetime_from_timestamp_micros() {
311+
let datetime_from_timestamp: DateTime<Utc> = Timestamp::Microseconds(1).into();
312+
assert_eq!(
313+
Utc.timestamp_nanos((1 / MICROS_PER_NANO).try_into().unwrap()),
314+
datetime_from_timestamp
315+
)
316+
}
317+
318+
#[cfg(feature = "chrono_timestamps")]
319+
#[test]
320+
fn test_timestamp_from_chrono_date() {
321+
let timestamp_from_datetime: Timestamp = Utc.ymd(1970, 1, 1).and_hms(0, 0, 1).into();
322+
assert_eq!(
323+
Timestamp::Nanoseconds(MILLIS_PER_SECOND * NANOS_PER_MILLI),
324+
timestamp_from_datetime
325+
)
326+
}
184327
}

0 commit comments

Comments
 (0)