datatypes/types/
date_type.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use arrow::datatypes::{DataType as ArrowDataType, Date32Type};
16use common_time::Date;
17use serde::{Deserialize, Serialize};
18use snafu::OptionExt;
19
20use crate::data_type::{ConcreteDataType, DataType};
21use crate::error::{self, Result};
22use crate::scalars::ScalarVectorBuilder;
23use crate::type_id::LogicalTypeId;
24use crate::types::LogicalPrimitiveType;
25use crate::value::{Value, ValueRef};
26use crate::vectors::{DateVector, DateVectorBuilder, MutableVector, Vector};
27
28/// Data type for Date (YYYY-MM-DD).
29#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
30pub struct DateType;
31
32impl DataType for DateType {
33    fn name(&self) -> String {
34        "Date".to_string()
35    }
36
37    fn logical_type_id(&self) -> LogicalTypeId {
38        LogicalTypeId::Date
39    }
40
41    fn default_value(&self) -> Value {
42        Value::Date(Default::default())
43    }
44
45    fn as_arrow_type(&self) -> ArrowDataType {
46        ArrowDataType::Date32
47    }
48
49    fn create_mutable_vector(&self, capacity: usize) -> Box<dyn MutableVector> {
50        Box::new(DateVectorBuilder::with_capacity(capacity))
51    }
52
53    fn try_cast(&self, from: Value) -> Option<Value> {
54        match from {
55            Value::Int32(v) => Some(Value::Date(Date::from(v))),
56            Value::String(v) => Date::from_str_utc(v.as_utf8()).map(Value::Date).ok(),
57            Value::Timestamp(v) => v.to_chrono_date().map(|date| Value::Date(date.into())),
58            _ => None,
59        }
60    }
61}
62
63impl LogicalPrimitiveType for DateType {
64    type ArrowPrimitive = Date32Type;
65    type Native = i32;
66    type Wrapper = Date;
67    type LargestType = Self;
68
69    fn build_data_type() -> ConcreteDataType {
70        ConcreteDataType::date_datatype()
71    }
72
73    fn type_name() -> &'static str {
74        "Date"
75    }
76
77    fn cast_vector(vector: &dyn Vector) -> Result<&DateVector> {
78        vector
79            .as_any()
80            .downcast_ref::<DateVector>()
81            .with_context(|| error::CastTypeSnafu {
82                msg: format!("Failed to cast {} to DateVector", vector.vector_type_name(),),
83            })
84    }
85
86    fn cast_value_ref(value: ValueRef) -> Result<Option<Date>> {
87        match value {
88            ValueRef::Null => Ok(None),
89            ValueRef::Date(v) => Ok(Some(v)),
90            other => error::CastTypeSnafu {
91                msg: format!("Failed to cast value {other:?} to Date"),
92            }
93            .fail(),
94        }
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use common_base::bytes::StringBytes;
101    use common_time::timezone::set_default_timezone;
102    use common_time::Timestamp;
103
104    use super::*;
105
106    // $TZ doesn't take effort
107    #[test]
108    fn test_date_cast() {
109        set_default_timezone(Some("Asia/Shanghai")).unwrap();
110        // timestamp -> date
111        let ts = Value::Timestamp(Timestamp::from_str_utc("2000-01-01 08:00:01").unwrap());
112        let date = ConcreteDataType::date_datatype().try_cast(ts).unwrap();
113        assert_eq!(date, Value::Date(Date::from_str_utc("2000-01-01").unwrap()));
114
115        // this case bind with Zulu timezone.
116        let ts = Value::Timestamp(Timestamp::from_str_utc("2000-01-02 07:59:59").unwrap());
117        let date = ConcreteDataType::date_datatype().try_cast(ts).unwrap();
118        assert_eq!(date, Value::Date(Date::from_str_utc("2000-01-02").unwrap()));
119
120        // while this case is offsetted to Asia/Shanghai.
121        let ts = Value::Timestamp(Timestamp::from_str_utc("2000-01-02 07:59:59+08:00").unwrap());
122        let date = ConcreteDataType::date_datatype().try_cast(ts).unwrap();
123        assert_eq!(date, Value::Date(Date::from_str_utc("2000-01-01").unwrap()));
124
125        // Int32 -> date
126        let val = Value::Int32(0);
127        let date = ConcreteDataType::date_datatype().try_cast(val).unwrap();
128        assert_eq!(date, Value::Date(Date::from_str_utc("1970-01-01").unwrap()));
129
130        let val = Value::Int32(19614);
131        let date = ConcreteDataType::date_datatype().try_cast(val).unwrap();
132        assert_eq!(date, Value::Date(Date::from_str_utc("2023-09-14").unwrap()));
133
134        // String -> date
135        let s = Value::String(StringBytes::from("1970-02-12"));
136        let date = ConcreteDataType::date_datatype().try_cast(s).unwrap();
137        assert_eq!(date, Value::Date(Date::from_str_utc("1970-02-12").unwrap()));
138    }
139}