Skip to content

Commit

Permalink
Refactor timeslot into round function
Browse files Browse the repository at this point in the history
  • Loading branch information
sundy-li committed Sep 7, 2021
1 parent d24c007 commit 88862b7
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 166 deletions.
36 changes: 34 additions & 2 deletions common/functions/src/scalars/dates/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use common_exception::Result;

use super::now::NowFunction;
use super::timeslot::TimeSlotFunction;
use super::RoundFunction;
use super::ToYYYYMMFunction;
use super::TodayFunction;
use super::TomorrowFunction;
Expand All @@ -32,9 +32,41 @@ impl DateFunction {
map.insert("yesterday".into(), YesterdayFunction::try_create);
map.insert("tomorrow".into(), TomorrowFunction::try_create);
map.insert("now".into(), NowFunction::try_create);
map.insert("timeSlot".into(), TimeSlotFunction::try_create);
map.insert("toYYYYMM".into(), ToYYYYMMFunction::try_create);

// rounders
{
map.insert("toStartOfSecond".into(), |display_name| {
RoundFunction::try_create(display_name, 1)
});

map.insert("toStartOfMinute".into(), |display_name| {
RoundFunction::try_create(display_name, 60)
});

map.insert("toStartOfFiveMinutes".into(), |display_name| {
RoundFunction::try_create(display_name, 5 * 60)
});

map.insert("toStartOfTenMinutes".into(), |display_name| {
RoundFunction::try_create(display_name, 10 * 60)
});

map.insert("toStartOfFifteenMinutes".into(), |display_name| {
RoundFunction::try_create(display_name, 15 * 60)
});

map.insert("timeSlot".into(), |display_name| {
RoundFunction::try_create(display_name, 30 * 60)
});
map.insert("toStartOfHour".into(), |display_name| {
RoundFunction::try_create(display_name, 60 * 60)
});
map.insert("toStartOfDay".into(), |display_name| {
RoundFunction::try_create(display_name, 60 * 60 * 24)
});
}

Ok(())
}
}
81 changes: 17 additions & 64 deletions common/functions/src/scalars/dates/date_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use common_datavalues::chrono::DateTime;
use common_datavalues::chrono::Timelike;
use common_datavalues::chrono::Utc;
use common_datavalues::prelude::*;
use common_exception::Result;
use pretty_assertions::assert_eq;

use super::timeslot::TimeSlotFunction;
use super::RoundFunction;
use crate::scalars::*;

#[allow(dead_code)]
Expand All @@ -33,65 +30,29 @@ struct Test {
}

#[test]
fn test_date_function() -> Result<()> {
let tests = vec![Test {
name: "test-timeSlot-now",
display: "timeSlot",
nullable: false,
columns: vec![Series::new(vec![1630812366u32, 1630839682u32]).into()],
func: TimeSlotFunction::try_create("timeSlot"),
expect: Series::new(vec![1630810806u32, 1630839622u32]),
error: "",
}];
for t in tests {
do_test(t);
}

Ok(())
}

#[test]
fn test_timeslot_now_function() -> Result<()> {
let now = Utc::now();
let now_timestamp = now.timestamp_millis() / 1000;
let mut minute = 0;
if now.minute() > 30 {
minute = 30;
}
let new_date = now.with_minute(minute).unwrap();
let check_timestamp = new_date.timestamp_millis() / 1000;
let empty: Vec<u32> = Vec::new();
fn test_round_function() -> Result<()> {
let mut tests = vec![];

let tests = vec![
Test {
name: "test-timeSlot",
display: "timeSlot",
nullable: false,
columns: vec![Series::new(vec![now_timestamp as u32]).into()],
func: TimeSlotFunction::try_create("timeSlot"),
expect: Series::new(vec![check_timestamp]),
error: "",
},
Test {
for r in &[1, 60, 60 * 10, 60 * 15, 60 * 30, 60 * 60, 60 * 60 * 24] {
tests.push(Test {
name: "test-timeSlot-now",
display: "timeSlot",
display: "toStartOfCustom",
nullable: false,
columns: vec![Series::new(empty).into()],
func: TimeSlotFunction::try_create("timeSlot"),
expect: Series::new(vec![check_timestamp]),
columns: vec![Series::new(vec![1630812366u32, 1630839682u32]).into()],
func: RoundFunction::try_create("toStartOfCustom", *r),
expect: Series::new(vec![1630812366u32 / r * r, 1630839682u32 / r * r]),
error: "",
},
];
})
}

for t in tests {
do_test(t);
do_test(t)?;
}

Ok(())
}

fn do_test(t: Test) -> Result<()> {
let dummy = DataField::new("dummy", DataType::DateTime32, false);
let dummy = DataField::new("dummy", DataType::DateTime32(None), false);
let rows = t.columns[0].len();
let columns: Vec<DataColumnWithField> = t
.columns
Expand All @@ -113,17 +74,9 @@ fn do_test(t: Test) -> Result<()> {
let actual_null = func.nullable(&DataSchema::empty())?;
assert_eq!(expect_null, actual_null);

let ref v = func.eval(&columns, rows)?;
let mut eval_result = v.to_values()?;
let c: DataColumn = t.expect.into();
let check_result = c.to_values()?;
// assert_eq!(v.len(), c.len());
for i in 0..v.len() {
let eval_val = eval_result.get(i).unwrap();
let check_val = check_result.get(i).unwrap();
let eval_str = format!("{}", eval_val);
let check_str = format!("{}", check_val);
assert_eq!(eval_str, check_str);
}
let v = func.eval(&columns, rows)?;
let expect: DataColumn = t.expect.into();

assert_eq!(&expect, &v);
Ok(())
}
3 changes: 2 additions & 1 deletion common/functions/src/scalars/dates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ mod date_function_test;
mod date_test;
mod now;
mod number_function;
mod round_function;
mod simple_date;
mod timeslot;

pub use date::DateFunction;
pub use number_function::ToYYYYMMFunction;
pub use round_function::RoundFunction;
pub use simple_date::TodayFunction;
pub use simple_date::TomorrowFunction;
pub use simple_date::YesterdayFunction;
89 changes: 89 additions & 0 deletions common/functions/src/scalars/dates/round_function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2020 Datafuse Labs.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt;

use common_datavalues::prelude::*;
use common_exception::Result;

use crate::scalars::Function;

#[derive(Clone)]
pub struct RoundFunction {
display_name: String,
round: u32,
}

impl RoundFunction {
pub fn try_create(display_name: &str, round: u32) -> Result<Box<dyn Function>> {
let s = Self {
display_name: display_name.to_owned(),
round,
};

Ok(Box::new(s))
}

// TODO: (sundy-li)
// Consider about the timezones/offsets
// Currently: assuming timezone offset is a multiple of round.
#[inline]
fn execute(&self, time: u32) -> u32 {
time / self.round * self.round
}
}

impl Function for RoundFunction {
fn name(&self) -> &str {
self.display_name.as_str()
}

fn return_type(&self, _args: &[DataType]) -> Result<DataType> {
Ok(DataType::DateTime32(None))
}

fn nullable(&self, _input_schema: &DataSchema) -> Result<bool> {
Ok(false)
}

fn eval(&self, columns: &DataColumnsWithField, _input_rows: usize) -> Result<DataColumn> {
match columns[0].column() {
DataColumn::Array(array) => {
let array = array.u32()?;
let arr = array.apply(|x| self.execute(x));
Ok(DataColumn::Array(arr.into_series()))
}
DataColumn::Constant(v, rows) => {
if v.is_null() {
return Ok(DataColumn::Constant(DataValue::UInt32(None), *rows));
}
let value = v.as_u64()?;
Ok(DataColumn::Constant(
DataValue::UInt32(Some(self.execute(value as u32))),
*rows,
))
}
}
}

fn num_arguments(&self) -> usize {
1
}
}

impl fmt::Display for RoundFunction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.display_name)
}
}
88 changes: 0 additions & 88 deletions common/functions/src/scalars/dates/timeslot.rs

This file was deleted.

14 changes: 9 additions & 5 deletions tests/suites/0_stateless/02_0012_function_datetimes.result
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ true
true
true
true
2021-08-30 10:30:42
2021-09-05 02:30:41
2021-09-05 02:00:04
true
true
202109
202109
true
true
===round===
2021-08-30 10:30:00
2021-08-30 10:00:00
2021-08-30 10:45:00
2021-08-30 10:47:00
2021-08-30 10:45:00
2021-08-30 10:40:00
true
===round-end===
Loading

0 comments on commit 88862b7

Please sign in to comment.