use common_time::time::Time;
use common_time::timestamp::TimeUnit;
use paste::paste;
use serde::{Deserialize, Serialize};
use crate::prelude::{Scalar, Value, ValueRef};
use crate::scalars::ScalarRef;
use crate::types::{
TimeMicrosecondType, TimeMillisecondType, TimeNanosecondType, TimeSecondType, WrapperType,
};
use crate::vectors::{
TimeMicrosecondVector, TimeMillisecondVector, TimeNanosecondVector, TimeSecondVector,
};
macro_rules! define_time_with_unit {
($unit: ident, $native_ty: ty) => {
paste! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct [<Time $unit>](pub Time);
impl [<Time $unit>] {
pub fn new(val: i64) -> Self {
Self(Time::new(val, TimeUnit::$unit))
}
}
impl Default for [<Time $unit>] {
fn default() -> Self {
Self::new(0)
}
}
impl From<[<Time $unit>]> for Value {
fn from(t: [<Time $unit>]) -> Value {
Value::Time(t.0)
}
}
impl From<[<Time $unit>]> for serde_json::Value {
fn from(t: [<Time $unit>]) -> Self {
t.0.into()
}
}
impl From<[<Time $unit>]> for ValueRef<'static> {
fn from(t: [<Time $unit>]) -> Self {
ValueRef::Time(t.0)
}
}
impl Scalar for [<Time $unit>] {
type VectorType = [<Time $unit Vector>];
type RefType<'a> = [<Time $unit>];
fn as_scalar_ref(&self) -> Self::RefType<'_> {
*self
}
fn upcast_gat<'short, 'long: 'short>(
long: Self::RefType<'long>,
) -> Self::RefType<'short> {
long
}
}
impl<'a> ScalarRef<'a> for [<Time $unit>] {
type ScalarType = [<Time $unit>];
fn to_owned_scalar(&self) -> Self::ScalarType {
*self
}
}
impl WrapperType for [<Time $unit>] {
type LogicalType = [<Time $unit Type>];
type Native = $native_ty;
fn from_native(value: Self::Native) -> Self {
Self::new(value.into())
}
fn into_native(self) -> Self::Native {
self.0.into()
}
}
impl From<i64> for [<Time $unit>] {
fn from(val: i64) -> Self {
[<Time $unit>]::from_native(val as $native_ty)
}
}
impl From<[<Time $unit>]> for i64 {
fn from(val: [<Time $unit>]) -> Self {
val.0.value()
}
}
impl TryFrom<Value> for Option<[<Time $unit>]> {
type Error = $crate::error::Error;
#[inline]
fn try_from(from: Value) -> std::result::Result<Self, Self::Error> {
match from {
Value::Time(v) if *v.unit() == TimeUnit::$unit => {
Ok(Some([<Time $unit>](v)))
},
Value::Null => Ok(None),
_ => $crate::error::TryFromValueSnafu {
reason: format!("{:?} is not a {}", from, stringify!([<Time $unit>])),
}
.fail(),
}
}
}
}
};
}
define_time_with_unit!(Second, i32);
define_time_with_unit!(Millisecond, i32);
define_time_with_unit!(Microsecond, i64);
define_time_with_unit!(Nanosecond, i64);
#[cfg(test)]
mod tests {
use common_time::timezone::set_default_timezone;
use super::*;
#[test]
fn test_to_serde_json_value() {
set_default_timezone(Some("Asia/Shanghai")).unwrap();
let time = TimeSecond::new(123);
let val = serde_json::Value::from(time);
match val {
serde_json::Value::String(s) => {
assert_eq!("08:02:03+0800", s);
}
_ => unreachable!(),
}
}
#[test]
fn test_time_scalar() {
let time = TimeSecond::new(123);
assert_eq!(time, time.as_scalar_ref());
assert_eq!(time, time.to_owned_scalar());
assert_eq!(123, time.into_native());
let time = TimeMillisecond::new(123);
assert_eq!(time, time.as_scalar_ref());
assert_eq!(time, time.to_owned_scalar());
assert_eq!(123, time.into_native());
let time = TimeMicrosecond::new(123);
assert_eq!(time, time.as_scalar_ref());
assert_eq!(time, time.to_owned_scalar());
assert_eq!(123, time.into_native());
let time = TimeNanosecond::new(123);
assert_eq!(time, time.as_scalar_ref());
assert_eq!(time, time.to_owned_scalar());
assert_eq!(123, time.into_native());
}
}