@@ -4,19 +4,21 @@ extern crate chrono;
44
55use std:: error:: Error ;
66use std:: io:: Write ;
7- use self :: chrono:: { Duration , NaiveDateTime , NaiveDate } ;
7+ use self :: chrono:: { Duration , NaiveDateTime , NaiveDate , NaiveTime } ;
88
99use expression:: AsExpression ;
1010use expression:: bound:: Bound ;
1111use 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
1515expression_impls ! {
16+ Time -> NaiveTime ,
1617 Timestamp -> NaiveDateTime ,
1718}
1819
1920queryable_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) ]
4973mod 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}
0 commit comments