@@ -10,6 +10,7 @@ use partiql_value::{
1010} ; 
1111use  regex:: { Regex ,  RegexBuilder } ; 
1212use  rust_decimal:: prelude:: FromPrimitive ; 
13+ use  rust_decimal:: RoundingStrategy ; 
1314use  std:: borrow:: { Borrow ,  Cow } ; 
1415use  std:: fmt:: Debug ; 
1516
@@ -952,10 +953,10 @@ impl EvalExpr for EvalFnExtractYear {
952953            Null  => Null , 
953954            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
954955                DateTime :: Date ( d)  => Value :: from ( d. year ( ) ) , 
955-                 DateTime :: Timestamp ( tstamp)  => Value :: from ( tstamp. year ( ) ) , 
956-                 DateTime :: TimestampWithTz ( tstamp)  => Value :: from ( tstamp. year ( ) ) , 
957-                 DateTime :: Time ( _)  => Missing , 
958-                 DateTime :: TimeWithTz ( _,  _)  => Missing , 
956+                 DateTime :: Timestamp ( tstamp,  _ )  => Value :: from ( tstamp. year ( ) ) , 
957+                 DateTime :: TimestampWithTz ( tstamp,  _ )  => Value :: from ( tstamp. year ( ) ) , 
958+                 DateTime :: Time ( _,  _ )  => Missing , 
959+                 DateTime :: TimeWithTz ( _,  _,  _ )  => Missing , 
959960            } , 
960961            _ => Missing , 
961962        } ; 
@@ -977,10 +978,10 @@ impl EvalExpr for EvalFnExtractMonth {
977978            Null  => Null , 
978979            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
979980                DateTime :: Date ( d)  => Value :: from ( d. month ( )  as  u8 ) , 
980-                 DateTime :: Timestamp ( tstamp)  => Value :: from ( tstamp. month ( )  as  u8 ) , 
981-                 DateTime :: TimestampWithTz ( tstamp)  => Value :: from ( tstamp. month ( )  as  u8 ) , 
982-                 DateTime :: Time ( _)  => Missing , 
983-                 DateTime :: TimeWithTz ( _,  _)  => Missing , 
981+                 DateTime :: Timestamp ( tstamp,  _ )  => Value :: from ( tstamp. month ( )  as  u8 ) , 
982+                 DateTime :: TimestampWithTz ( tstamp,  _ )  => Value :: from ( tstamp. month ( )  as  u8 ) , 
983+                 DateTime :: Time ( _,  _ )  => Missing , 
984+                 DateTime :: TimeWithTz ( _,  _,  _ )  => Missing , 
984985            } , 
985986            _ => Missing , 
986987        } ; 
@@ -1002,10 +1003,10 @@ impl EvalExpr for EvalFnExtractDay {
10021003            Null  => Null , 
10031004            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
10041005                DateTime :: Date ( d)  => Value :: from ( d. day ( ) ) , 
1005-                 DateTime :: Timestamp ( tstamp)  => Value :: from ( tstamp. day ( ) ) , 
1006-                 DateTime :: TimestampWithTz ( tstamp)  => Value :: from ( tstamp. day ( ) ) , 
1007-                 DateTime :: Time ( _)  => Missing , 
1008-                 DateTime :: TimeWithTz ( _,  _)  => Missing , 
1006+                 DateTime :: Timestamp ( tstamp,  _ )  => Value :: from ( tstamp. day ( ) ) , 
1007+                 DateTime :: TimestampWithTz ( tstamp,  _ )  => Value :: from ( tstamp. day ( ) ) , 
1008+                 DateTime :: Time ( _,  _ )  => Missing , 
1009+                 DateTime :: TimeWithTz ( _,  _,  _ )  => Missing , 
10091010            } , 
10101011            _ => Missing , 
10111012        } ; 
@@ -1026,10 +1027,10 @@ impl EvalExpr for EvalFnExtractHour {
10261027        let  result = match  value. borrow ( )  { 
10271028            Null  => Null , 
10281029            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
1029-                 DateTime :: Time ( t)  => Value :: from ( t. hour ( ) ) , 
1030-                 DateTime :: TimeWithTz ( t,  _)  => Value :: from ( t. hour ( ) ) , 
1031-                 DateTime :: Timestamp ( tstamp)  => Value :: from ( tstamp. hour ( ) ) , 
1032-                 DateTime :: TimestampWithTz ( tstamp)  => Value :: from ( tstamp. hour ( ) ) , 
1030+                 DateTime :: Time ( t,  _ )  => Value :: from ( t. hour ( ) ) , 
1031+                 DateTime :: TimeWithTz ( t,  _,  _ )  => Value :: from ( t. hour ( ) ) , 
1032+                 DateTime :: Timestamp ( tstamp,  _ )  => Value :: from ( tstamp. hour ( ) ) , 
1033+                 DateTime :: TimestampWithTz ( tstamp,  _ )  => Value :: from ( tstamp. hour ( ) ) , 
10331034                DateTime :: Date ( _)  => Missing , 
10341035            } , 
10351036            _ => Missing , 
@@ -1051,10 +1052,10 @@ impl EvalExpr for EvalFnExtractMinute {
10511052        let  result = match  value. borrow ( )  { 
10521053            Null  => Null , 
10531054            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
1054-                 DateTime :: Time ( t)  => Value :: from ( t. minute ( ) ) , 
1055-                 DateTime :: TimeWithTz ( t,  _)  => Value :: from ( t. minute ( ) ) , 
1056-                 DateTime :: Timestamp ( tstamp)  => Value :: from ( tstamp. minute ( ) ) , 
1057-                 DateTime :: TimestampWithTz ( tstamp)  => Value :: from ( tstamp. minute ( ) ) , 
1055+                 DateTime :: Time ( t,  _ )  => Value :: from ( t. minute ( ) ) , 
1056+                 DateTime :: TimeWithTz ( t,  _,  _ )  => Value :: from ( t. minute ( ) ) , 
1057+                 DateTime :: Timestamp ( tstamp,  _ )  => Value :: from ( tstamp. minute ( ) ) , 
1058+                 DateTime :: TimestampWithTz ( tstamp,  _ )  => Value :: from ( tstamp. minute ( ) ) , 
10581059                DateTime :: Date ( _)  => Missing , 
10591060            } , 
10601061            _ => Missing , 
@@ -1069,10 +1070,17 @@ pub(crate) struct EvalFnExtractSecond {
10691070    pub ( crate )  value :  Box < dyn  EvalExpr > , 
10701071} 
10711072
1072- fn  total_seconds ( second :  u8 ,  nanosecond :  u32 )  -> Value  { 
1073+ fn  total_seconds ( second :  u8 ,  nanosecond :  u32 ,   precision :   Option < u32 > )  -> Value  { 
10731074    let  result = rust_decimal:: Decimal :: from_f64 ( ( ( second as  f64  *  1e9 )  + nanosecond as  f64 )  / 1e9 ) 
10741075        . expect ( "time as decimal" ) ; 
1075-     Value :: from ( result) 
1076+     match  precision { 
1077+         None  => Value :: from ( result) , 
1078+         Some ( p)  => { 
1079+             // TODO: currently using `RoundingStrategy::MidpointAwayFromZero`, which follows what 
1080+             //  Kotlin does. Need to determine if this strategy is what we want or some configurability 
1081+             Value :: from ( result. round_dp_with_strategy ( p,  RoundingStrategy :: MidpointAwayFromZero ) ) 
1082+         } 
1083+     } 
10761084} 
10771085
10781086impl  EvalExpr  for  EvalFnExtractSecond  { 
@@ -1082,11 +1090,13 @@ impl EvalExpr for EvalFnExtractSecond {
10821090        let  result = match  value. borrow ( )  { 
10831091            Null  => Null , 
10841092            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
1085-                 DateTime :: Time ( t)  => total_seconds ( t. second ( ) ,  t. nanosecond ( ) ) , 
1086-                 DateTime :: TimeWithTz ( t,  _)  => total_seconds ( t. second ( ) ,  t. nanosecond ( ) ) , 
1087-                 DateTime :: Timestamp ( tstamp)  => total_seconds ( tstamp. second ( ) ,  tstamp. nanosecond ( ) ) , 
1088-                 DateTime :: TimestampWithTz ( tstamp)  => { 
1089-                     total_seconds ( tstamp. second ( ) ,  tstamp. nanosecond ( ) ) 
1093+                 DateTime :: Time ( t,  p)  => total_seconds ( t. second ( ) ,  t. nanosecond ( ) ,  * p) , 
1094+                 DateTime :: TimeWithTz ( t,  p,  _)  => total_seconds ( t. second ( ) ,  t. nanosecond ( ) ,  * p) , 
1095+                 DateTime :: Timestamp ( tstamp,  p)  => { 
1096+                     total_seconds ( tstamp. second ( ) ,  tstamp. nanosecond ( ) ,  * p) 
1097+                 } 
1098+                 DateTime :: TimestampWithTz ( tstamp,  p)  => { 
1099+                     total_seconds ( tstamp. second ( ) ,  tstamp. nanosecond ( ) ,  * p) 
10901100                } 
10911101                DateTime :: Date ( _)  => Missing , 
10921102            } , 
@@ -1109,11 +1119,11 @@ impl EvalExpr for EvalFnExtractTimezoneHour {
11091119        let  result = match  value. borrow ( )  { 
11101120            Null  => Null , 
11111121            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
1112-                 DateTime :: TimeWithTz ( _,  tz)  => Value :: from ( tz. whole_hours ( ) ) , 
1113-                 DateTime :: TimestampWithTz ( tstamp)  => Value :: from ( tstamp. offset ( ) . whole_hours ( ) ) , 
1122+                 DateTime :: TimeWithTz ( _,  _ ,   tz)  => Value :: from ( tz. whole_hours ( ) ) , 
1123+                 DateTime :: TimestampWithTz ( tstamp,  _ )  => Value :: from ( tstamp. offset ( ) . whole_hours ( ) ) , 
11141124                DateTime :: Date ( _)  => Missing , 
1115-                 DateTime :: Time ( _)  => Missing , 
1116-                 DateTime :: Timestamp ( _)  => Missing , 
1125+                 DateTime :: Time ( _,  _ )  => Missing , 
1126+                 DateTime :: Timestamp ( _,  _ )  => Missing , 
11171127            } , 
11181128            _ => Missing , 
11191129        } ; 
@@ -1134,13 +1144,13 @@ impl EvalExpr for EvalFnExtractTimezoneMinute {
11341144        let  result = match  value. borrow ( )  { 
11351145            Null  => Null , 
11361146            Value :: DateTime ( dt)  => match  dt. as_ref ( )  { 
1137-                 DateTime :: TimeWithTz ( _,  tz)  => Value :: from ( tz. minutes_past_hour ( ) ) , 
1138-                 DateTime :: TimestampWithTz ( tstamp)  => { 
1147+                 DateTime :: TimeWithTz ( _,  _ ,   tz)  => Value :: from ( tz. minutes_past_hour ( ) ) , 
1148+                 DateTime :: TimestampWithTz ( tstamp,  _ )  => { 
11391149                    Value :: from ( tstamp. offset ( ) . minutes_past_hour ( ) ) 
11401150                } 
11411151                DateTime :: Date ( _)  => Missing , 
1142-                 DateTime :: Time ( _)  => Missing , 
1143-                 DateTime :: Timestamp ( _)  => Missing , 
1152+                 DateTime :: Time ( _,  _ )  => Missing , 
1153+                 DateTime :: Timestamp ( _,  _ )  => Missing , 
11441154            } , 
11451155            _ => Missing , 
11461156        } ; 
0 commit comments