@@ -10,6 +10,7 @@ use partiql_value::{
10
10
} ;
11
11
use regex:: { Regex , RegexBuilder } ;
12
12
use rust_decimal:: prelude:: FromPrimitive ;
13
+ use rust_decimal:: RoundingStrategy ;
13
14
use std:: borrow:: { Borrow , Cow } ;
14
15
use std:: fmt:: Debug ;
15
16
@@ -952,10 +953,10 @@ impl EvalExpr for EvalFnExtractYear {
952
953
Null => Null ,
953
954
Value :: DateTime ( dt) => match dt. as_ref ( ) {
954
955
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 ,
959
960
} ,
960
961
_ => Missing ,
961
962
} ;
@@ -977,10 +978,10 @@ impl EvalExpr for EvalFnExtractMonth {
977
978
Null => Null ,
978
979
Value :: DateTime ( dt) => match dt. as_ref ( ) {
979
980
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 ,
984
985
} ,
985
986
_ => Missing ,
986
987
} ;
@@ -1002,10 +1003,10 @@ impl EvalExpr for EvalFnExtractDay {
1002
1003
Null => Null ,
1003
1004
Value :: DateTime ( dt) => match dt. as_ref ( ) {
1004
1005
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 ,
1009
1010
} ,
1010
1011
_ => Missing ,
1011
1012
} ;
@@ -1026,10 +1027,10 @@ impl EvalExpr for EvalFnExtractHour {
1026
1027
let result = match value. borrow ( ) {
1027
1028
Null => Null ,
1028
1029
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 ( ) ) ,
1033
1034
DateTime :: Date ( _) => Missing ,
1034
1035
} ,
1035
1036
_ => Missing ,
@@ -1051,10 +1052,10 @@ impl EvalExpr for EvalFnExtractMinute {
1051
1052
let result = match value. borrow ( ) {
1052
1053
Null => Null ,
1053
1054
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 ( ) ) ,
1058
1059
DateTime :: Date ( _) => Missing ,
1059
1060
} ,
1060
1061
_ => Missing ,
@@ -1069,10 +1070,17 @@ pub(crate) struct EvalFnExtractSecond {
1069
1070
pub ( crate ) value : Box < dyn EvalExpr > ,
1070
1071
}
1071
1072
1072
- fn total_seconds ( second : u8 , nanosecond : u32 ) -> Value {
1073
+ fn total_seconds ( second : u8 , nanosecond : u32 , precision : Option < u32 > ) -> Value {
1073
1074
let result = rust_decimal:: Decimal :: from_f64 ( ( ( second as f64 * 1e9 ) + nanosecond as f64 ) / 1e9 )
1074
1075
. 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
+ }
1076
1084
}
1077
1085
1078
1086
impl EvalExpr for EvalFnExtractSecond {
@@ -1082,11 +1090,13 @@ impl EvalExpr for EvalFnExtractSecond {
1082
1090
let result = match value. borrow ( ) {
1083
1091
Null => Null ,
1084
1092
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)
1090
1100
}
1091
1101
DateTime :: Date ( _) => Missing ,
1092
1102
} ,
@@ -1109,11 +1119,11 @@ impl EvalExpr for EvalFnExtractTimezoneHour {
1109
1119
let result = match value. borrow ( ) {
1110
1120
Null => Null ,
1111
1121
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 ( ) ) ,
1114
1124
DateTime :: Date ( _) => Missing ,
1115
- DateTime :: Time ( _) => Missing ,
1116
- DateTime :: Timestamp ( _) => Missing ,
1125
+ DateTime :: Time ( _, _ ) => Missing ,
1126
+ DateTime :: Timestamp ( _, _ ) => Missing ,
1117
1127
} ,
1118
1128
_ => Missing ,
1119
1129
} ;
@@ -1134,13 +1144,13 @@ impl EvalExpr for EvalFnExtractTimezoneMinute {
1134
1144
let result = match value. borrow ( ) {
1135
1145
Null => Null ,
1136
1146
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, _ ) => {
1139
1149
Value :: from ( tstamp. offset ( ) . minutes_past_hour ( ) )
1140
1150
}
1141
1151
DateTime :: Date ( _) => Missing ,
1142
- DateTime :: Time ( _) => Missing ,
1143
- DateTime :: Timestamp ( _) => Missing ,
1152
+ DateTime :: Time ( _, _ ) => Missing ,
1153
+ DateTime :: Timestamp ( _, _ ) => Missing ,
1144
1154
} ,
1145
1155
_ => Missing ,
1146
1156
} ;
0 commit comments