`time_bucket(interval, timestamp)` — truncate a millisecond timestamp to the start of the given interval bucket. Accepts two argument orders (both common in SQL): - `time_bucket('1 hour', timestamp_col)` — interval first - `time_bucket(timestamp_col, '1 hour')` — timestamp first The interval is a string like `'1h'`, `'5m'`, `'1 hour'`, `'30 seconds'`. The timestamp is an integer (epoch milliseco
(args: &[Value])
| 188 | /// The interval is a string like `'1h'`, `'5m'`, `'1 hour'`, `'30 seconds'`. |
| 189 | /// The timestamp is an integer (epoch milliseconds). |
| 190 | fn eval_time_bucket(args: &[Value]) -> Value { |
| 191 | if args.len() < 2 { |
| 192 | return Value::Null; |
| 193 | } |
| 194 | |
| 195 | // Detect which arg is the interval string and which is the timestamp. |
| 196 | let (interval_ms, timestamp_ms) = match (&args[0], &args[1]) { |
| 197 | // time_bucket('1 hour', timestamp) |
| 198 | (Value::String(s), ts_val) => { |
| 199 | let interval = parse_interval_to_ms(s); |
| 200 | let ts = value_to_timestamp_ms(ts_val); |
| 201 | (interval, ts) |
| 202 | } |
| 203 | // time_bucket(timestamp, '1 hour') |
| 204 | (ts_val, Value::String(s)) => { |
| 205 | let interval = parse_interval_to_ms(s); |
| 206 | let ts = value_to_timestamp_ms(ts_val); |
| 207 | (interval, ts) |
| 208 | } |
| 209 | // time_bucket(3600, timestamp) — interval as integer seconds |
| 210 | (Value::Integer(interval_secs), ts_val) => { |
| 211 | let ts = value_to_timestamp_ms(ts_val); |
| 212 | (Some((*interval_secs) * 1000), ts) |
| 213 | } |
| 214 | _ => return Value::Null, |
| 215 | }; |
| 216 | |
| 217 | match (interval_ms, timestamp_ms) { |
| 218 | (Some(i), Some(ts)) if i > 0 => Value::Integer((ts / i) * i), |
| 219 | _ => Value::Null, |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | fn value_to_timestamp_ms(v: &Value) -> Option<i64> { |
| 224 | match v { |
no test coverage detected