Skip to content

Commit e7e4988

Browse files
committed
Merge pull request diesel-rs#101 from tohou/chrono-time
Implement FromSql and ToSql for `chrono::NaiveTime`
2 parents c26d299 + 6ac1099 commit e7e4988

2 files changed

Lines changed: 67 additions & 5 deletions

File tree

diesel/src/types/impls/date_and_time/chrono.rs

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ extern crate chrono;
44

55
use std::error::Error;
66
use std::io::Write;
7-
use self::chrono::{Duration, NaiveDateTime, NaiveDate};
7+
use self::chrono::{Duration, NaiveDateTime, NaiveDate, NaiveTime};
88

99
use expression::AsExpression;
1010
use expression::bound::Bound;
1111
use query_source::Queryable;
12-
use super::PgTimestamp;
13-
use types::{self, FromSql, IsNull, Timestamp, ToSql};
12+
use super::{PgTime, PgTimestamp};
13+
use types::{self, FromSql, IsNull, Time, Timestamp, ToSql};
1414

1515
expression_impls! {
16+
Time -> NaiveTime,
1617
Timestamp -> NaiveDateTime,
1718
}
1819

1920
queryable_impls! {
21+
Time -> NaiveTime,
2022
Timestamp -> NaiveDateTime,
2123
}
2224

@@ -45,6 +47,28 @@ impl ToSql<Timestamp> for NaiveDateTime {
4547
}
4648
}
4749

50+
fn midnight() -> NaiveTime {
51+
NaiveTime::from_hms(0, 0, 0)
52+
}
53+
54+
impl ToSql<Time> for NaiveTime {
55+
fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error>> {
56+
let duration = *self - midnight();
57+
match duration.num_microseconds() {
58+
Some(offset) => ToSql::<Time>::to_sql(&PgTime(offset), out),
59+
None => unreachable!()
60+
}
61+
}
62+
}
63+
64+
impl FromSql<Time> for NaiveTime {
65+
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
66+
let PgTime(offset) = try!(FromSql::<Time>::from_sql(bytes));
67+
let duration = Duration::microseconds(offset);
68+
Ok(midnight() + duration)
69+
}
70+
}
71+
4872
#[cfg(test)]
4973
mod tests {
5074
extern crate dotenv;
@@ -57,7 +81,7 @@ mod tests {
5781
use connection::Connection;
5882
use expression::dsl::{sql, now};
5983
use prelude::*;
60-
use types::Timestamp;
84+
use types::{Time, Timestamp};
6185

6286
fn connection() -> Connection {
6387
dotenv().ok();
@@ -95,4 +119,37 @@ mod tests {
95119
let query = select(now.at_time_zone("utc").gt(time));
96120
assert!(query.get_result::<bool>(&connection).unwrap());
97121
}
122+
123+
#[test]
124+
fn times_of_day_encode_correctly() {
125+
let connection = connection();
126+
127+
let midnight = NaiveTime::from_hms(0, 0, 0);
128+
let query = select(sql::<Time>("'00:00:00'::time").eq(midnight));
129+
assert!(query.get_result::<bool>(&connection).unwrap());
130+
131+
let noon = NaiveTime::from_hms(12, 0, 0);
132+
let query = select(sql::<Time>("'12:00:00'::time").eq(noon));
133+
assert!(query.get_result::<bool>(&connection).unwrap());
134+
135+
let roughly_half_past_eleven = NaiveTime::from_hms_micro(23, 37, 04, 2200);
136+
let query = select(sql::<Time>("'23:37:04.002200'::time").eq(roughly_half_past_eleven));
137+
assert!(query.get_result::<bool>(&connection).unwrap());
138+
}
139+
140+
#[test]
141+
fn times_of_day_decode_correctly() {
142+
let connection = connection();
143+
let midnight = NaiveTime::from_hms(0, 0, 0);
144+
let query = select(sql::<Time>("'00:00:00'::time"));
145+
assert_eq!(Ok(midnight), query.get_result::<NaiveTime>(&connection));
146+
147+
let noon = NaiveTime::from_hms(12, 0, 0);
148+
let query = select(sql::<Time>("'12:00:00'::time"));
149+
assert_eq!(Ok(noon), query.get_result::<NaiveTime>(&connection));
150+
151+
let roughly_half_past_eleven = NaiveTime::from_hms_micro(23, 37, 04, 2200);
152+
let query = select(sql::<Time>("'23:37:04.002200'::time"));
153+
assert_eq!(Ok(roughly_half_past_eleven), query.get_result::<NaiveTime>(&connection));
154+
}
98155
}

diesel_tests/tests/types_roundtrip.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate chrono;
22

33
pub use quickcheck::quickcheck;
4-
use self::chrono::NaiveDateTime;
4+
use self::chrono::{NaiveDateTime, NaiveTime};
55

66
pub use schema::connection;
77
pub use diesel::*;
@@ -80,11 +80,16 @@ test_round_trip!(timestamp_roundtrips, Timestamp, PgTimestamp);
8080
test_round_trip!(interval_roundtrips, Interval, PgInterval);
8181
test_round_trip!(numeric_roundtrips, Numeric, PgNumeric);
8282
test_round_trip!(naive_datetime_roundtrips, Timestamp, (i64, u32), mk_naive_datetime);
83+
test_round_trip!(naive_time_roundtrips, Time, (u32, u32), mk_naive_time);
8384

8485
fn mk_naive_datetime(data: (i64, u32)) -> NaiveDateTime {
8586
NaiveDateTime::from_timestamp(data.0, data.1 / 1000)
8687
}
8788

89+
fn mk_naive_time(data: (u32, u32)) -> NaiveTime {
90+
NaiveTime::from_num_seconds_from_midnight(data.0, data.1 / 1000)
91+
}
92+
8893
#[cfg(feature = "unstable")]
8994
mod unstable_types {
9095
use super::*;

0 commit comments

Comments
 (0)