diff --git a/Cargo.lock b/Cargo.lock index f82a692..7a992f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,21 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "anyhow" version = "1.0.86" @@ -126,12 +111,6 @@ dependencies = [ "bytes", ] -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - [[package]] name = "bytes" version = "1.6.1" @@ -159,13 +138,8 @@ version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", "num-traits", "serde", - "wasm-bindgen", - "windows-targets 0.52.6", ] [[package]] @@ -174,12 +148,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6" -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - [[package]] name = "fbthrift-git" version = "0.0.7+b377f46" @@ -360,44 +328,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "libc" version = "0.2.155" @@ -414,12 +350,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - [[package]] name = "memchr" version = "2.7.4" @@ -850,69 +780,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.71", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index bb62a1b..f5287cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,9 @@ serde = { version = "1", default-features = false, features = [ bytes = { version = "1", default-features = false } async-trait = { version = "0.1", default-features = false } +chrono = { version = "0.4", features = [ + "serde", +], default-features = false, optional = true } nebula-fbthrift-graph-v3 = { version = "^0.3", default-features = false, optional = true } nebula-fbthrift-meta-v3 = { version = "^0.3", default-features = false, optional = true } @@ -33,7 +36,6 @@ nebula-fbthrift-storage-v3 = { version = "^0.3", default-features = false, optio bb8 = "0.8.5" [dev-dependencies] -chrono = { version = "0.4", features = ["serde"] } serde_repr = { version = "0.1" } float-cmp = { version = "0.9" } diff --git a/src/graph/single_conn_session/mod.rs b/src/graph/single_conn_session/mod.rs index 64463cb..fd7cb24 100644 --- a/src/graph/single_conn_session/mod.rs +++ b/src/graph/single_conn_session/mod.rs @@ -53,7 +53,7 @@ where connection, session_id, close_required: false, - timezone_info: TimezoneInfo {}, + timezone_info: TimezoneInfo::default(), } } diff --git a/src/lib.rs b/src/lib.rs index 80a1d28..1648ddc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,4 +45,19 @@ impl HostAddress { } #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)] -pub struct TimezoneInfo {} +pub struct TimezoneInfo { + offset: i32, + name: String, +} + +impl Default for TimezoneInfo { + fn default() -> Self { + Self::new(0, "UTC".to_string()) + } +} + +impl TimezoneInfo { + fn new(offset: i32, name: String) -> Self { + Self { offset, name } + } +} diff --git a/src/storage/client.rs b/src/storage/client.rs index 8b5b978..366e2cb 100644 --- a/src/storage/client.rs +++ b/src/storage/client.rs @@ -113,7 +113,7 @@ where Self { connection_map: HashMap::new(), mclient, - timezone_info: TimezoneInfo {}, + timezone_info: TimezoneInfo::default(), } } diff --git a/src/value_wrapper/datetime.rs b/src/value_wrapper/datetime.rs index 10ee789..905fe5c 100644 --- a/src/value_wrapper/datetime.rs +++ b/src/value_wrapper/datetime.rs @@ -1,124 +1,56 @@ -// /* -// datetime.rs 文件中定义了一些日期和时间相关的数据类型以及它们与 chrono 库的集成。以下是文件中定义的主要内容: -// 类型别名定义:在文件的开头,定义了一系列类型别名,如 Year、Month、Day 等,它们都是整数类型的别名,用于表示日期和时间的各个部分。 -// 结构体 Timestamp:表示一个时间戳,它包含一个 i64 类型的字段,用于存储时间戳的值。此结构体实现了 Deserialize trait,以支持从数据格式中反序列化时间戳。 -// 结构体 YearMonth:表示年份和月份的组合,包含了 Year 和 Month 两个字段。同样,它也实现了 Deserialize trait,以支持从数据格式中反序列化年份和月份。 -// 结构体 Date:表示日期,包含了 Year、Month 和 Day 三个字段。同样,它也实现了 Deserialize trait,以支持从数据格式中反序列化日期。 -// 结构体 Time:表示时间,包含了 Hour、Minute、Second 和 Millisec 四个字段。同样,它也实现了 Deserialize trait,以支持从数据格式中反序列化时间。 -// 结构体 DateTime:表示日期和时间的组合,包含了年、月、日、时、分、秒、毫秒和微秒八个字段。同样,它也实现了 Deserialize trait,以支持从数据格式中反序列化日期和时间。 -// 测试模块:在文件的末尾,包含了一些测试函数,用于测试日期和时间类型的反序列化是否正常工作。这些测试函数使用了 chrono 库来验证反序列化的结果是否与预期一致。 - -// 总之,datetime.rs 文件定义了一些日期和时间相关的数据结构,并提供了与 chrono 库的集成,以便在 Rust 项目中方便地处理日期和时间数据。这对于与时间相关的应用程序非常有用。 - -// */ -// pub type Year = i16; -// pub type Month = i8; -// pub type Day = i8; -// pub type Hour = i8; -// pub type Minute = i8; -// pub type Second = i8; -// pub type Millisec = i16; -// pub type Microsec = i16; - -// use serde::Deserialize; - -// // -// #[derive(Deserialize, PartialEq, Debug)] -// pub struct Timestamp(pub i64); - -// impl Timestamp { -// #[cfg(feature = "chrono")] -// pub fn to_naive_date_time(&self) -> chrono::NaiveDateTime { -// chrono::NaiveDateTime::from_timestamp_opt(self.0, 0) -// .expect("chrono::NaiveDateTime::from_timestamp_opt") -// } -// } - -// // v1 -// #[derive(Deserialize, PartialEq, Debug)] -// pub struct YearMonth(pub Year, pub Month); - -// impl YearMonth { -// #[cfg(feature = "chrono")] -// pub fn to_naive_date(&self) -> chrono::NaiveDate { -// chrono::NaiveDate::from_ymd_opt(self.0 as i32, self.1 as u32, 1) -// .expect("chrono::NaiveDate::from_ymd_opt") -// } -// } - -// // v3 v2 v1 -// #[derive(Deserialize, PartialEq, Debug)] -// pub struct Date(pub Year, pub Month, pub Day); - -// impl Date { -// #[cfg(feature = "chrono")] -// pub fn to_naive_date(&self) -> chrono::NaiveDate { -// chrono::NaiveDate::from_ymd_opt(self.0 as i32, self.1 as u32, self.2 as u32) -// .expect("chrono::NaiveDate::from_ymd_opt") -// } -// } - -// // v3 v2 v1 -// #[derive(Deserialize, PartialEq, Debug)] -// pub struct Time(pub Hour, pub Minute, pub Second, pub Millisec); - -// impl Time { -// #[cfg(feature = "chrono")] -// pub fn to_naive_date_time(&self) -> chrono::NaiveDateTime { -// let d = -// chrono::NaiveDate::from_ymd_opt(1970, 1, 1).expect("chrono::NaiveDate::from_ymd_opt"); -// let t = chrono::NaiveTime::from_hms_milli_opt( -// self.0 as u32, -// self.1 as u32, -// self.2 as u32, -// self.3 as u32, -// ) -// .expect("chrono::NaiveTime::from_hms_milli_opt"); -// chrono::NaiveDateTime::new(d, t) -// } -// } - -// // v3 v2 v1 -// #[derive(Deserialize, PartialEq, Debug)] -// pub struct DateTime( -// pub Year, -// pub Month, -// pub Day, -// pub Hour, -// pub Minute, -// pub Second, -// pub Millisec, -// pub Microsec, -// ); - -// impl DateTime { -// #[cfg(feature = "chrono")] -// pub fn to_naive_date_time(&self) -> chrono::NaiveDateTime { -// let d = chrono::NaiveDate::from_ymd_opt(self.0 as i32, self.1 as u32, self.2 as u32) -// .expect("chrono::NaiveDate::from_ymd_opt"); -// let t = chrono::NaiveTime::from_hms_milli_opt( -// self.3 as u32, -// self.4 as u32, -// self.5 as u32, -// self.6 as u32, -// ) -// .expect("chrono::NaiveTime::from_hms_milli_opt"); -// chrono::NaiveDateTime::new(d, t) -// } -// } - -use crate::common::{Date, DateTime, Time}; +use crate::common::{Date, DateTime, Duration, Time}; +#[cfg(feature = "chrono")] +use chrono::{NaiveDate, NaiveDateTime}; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub struct DurationWrapper<'a> { + duration: &'a Duration, +} + +impl<'a> DurationWrapper<'a> { + pub fn new(duration: &'a Duration) -> Self { + Self { duration } + } + pub fn get_months(&self) -> i32 { + self.duration.months + } + pub fn get_seconds(&self) -> i64 { + self.duration.seconds + } + pub fn get_microseconds(&self) -> i32 { + self.duration.microseconds + } + pub fn get_raw_duration(&self) -> &Duration { + self.duration + } + + #[cfg(feature = "chrono")] + pub fn to_chrono_duration(&self) -> chrono::Duration { + let months = self.get_months(); + let seconds = self.get_seconds(); + let microseconds = self.get_microseconds(); + + let total_seconds = months as i64 * 30 * 24 * 60 * 60 + seconds; + let total_microseconds = total_seconds * 1_000_000 + microseconds as i64; + + chrono::Duration::microseconds(total_microseconds) + } +} use crate::TimezoneInfo; #[derive(PartialEq, Eq, PartialOrd, Ord)] pub struct DateWrapper<'a> { - pub date: &'a Date, + date: &'a Date, + timezone_info: &'a TimezoneInfo, } impl<'a> DateWrapper<'a> { - pub fn new(date: &'a Date) -> Self { - Self { date } + pub fn new(date: &'a Date, timezone_info: &'a TimezoneInfo) -> Self { + Self { + date, + timezone_info, + } } pub fn get_year(&self) -> i16 { self.date.year @@ -130,7 +62,17 @@ impl<'a> DateWrapper<'a> { self.date.day } pub fn get_raw_date(&self) -> &Date { - &self.date + self.date + } + + #[cfg(feature = "chrono")] + pub fn to_naive_date(&self) -> NaiveDate { + NaiveDate::from_ymd_opt( + self.get_year() as i32, + self.get_month() as u32, + self.get_day() as u32, + ) + .expect("chrono::NaiveDate::from_ymd_opt") } } @@ -160,74 +102,155 @@ impl<'a> TimeWrapper<'a> { self.time.microsec } pub fn get_raw_time(&self) -> &Time { - &self.time + self.time + } + + #[cfg(feature = "chrono")] + pub fn to_naive_date_time(&self) -> chrono::NaiveDateTime { + let d = + chrono::NaiveDate::from_ymd_opt(1970, 1, 1).expect("chrono::NaiveDate::from_ymd_opt"); + let t = chrono::NaiveTime::from_hms_micro_opt( + self.get_hour() as u32, + self.get_minute() as u32, + self.get_second() as u32, + self.get_microsec() as u32, + ) + .expect("chrono::NaiveTime::from_hms_micro_opt"); + NaiveDateTime::new(d, t) } } #[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct DataTimeWrapper { - date_time: DateTime, - timezone_info: TimezoneInfo, +pub struct DateTimeWrapper<'a> { + date_time: &'a DateTime, + timezone_info: &'a TimezoneInfo, +} + +impl<'a> DateTimeWrapper<'a> { + pub fn new(date_time: &'a DateTime, timezone_info: &'a TimezoneInfo) -> Self { + Self { + date_time, + timezone_info, + } + } + pub fn get_year(&self) -> i16 { + self.date_time.year + } + pub fn get_month(&self) -> i8 { + self.date_time.month + } + pub fn get_day(&self) -> i8 { + self.date_time.day + } + pub fn get_hour(&self) -> i8 { + self.date_time.hour + } + pub fn get_minute(&self) -> i8 { + self.date_time.minute + } + pub fn get_second(&self) -> i8 { + self.date_time.sec + } + pub fn get_microsec(&self) -> i32 { + self.date_time.microsec + } + pub fn get_raw_date(&self) -> &DateTime { + self.date_time + } + + #[cfg(feature = "chrono")] + pub fn to_naive_date_time(&self) -> chrono::NaiveDateTime { + let d = chrono::NaiveDate::from_ymd_opt( + self.get_year() as i32, + self.get_month() as u32, + self.get_day() as u32, + ) + .expect("chrono::NaiveDate::from_ymd_opt"); + let t = chrono::NaiveTime::from_hms_micro_opt( + self.get_hour() as u32, + self.get_minute() as u32, + self.get_second() as u32, + self.get_microsec() as u32, + ) + .expect("chrono::NaiveTime::from_hms_micro_opt"); + chrono::NaiveDateTime::new(d, t) + } } #[cfg(test)] mod tests { - #[cfg(feature = "chrono")] use super::*; #[cfg(feature = "chrono")] - use chrono::{NaiveDate, NaiveDateTime, NaiveTime}; + use chrono::NaiveTime; #[test] - fn chrono_for_timestamp() { - #[cfg(feature = "chrono")] - assert_eq!( - Timestamp(1577836800).to_naive_date_time(), - NaiveDateTime::new( - NaiveDate::from_ymd_opt(2020, 1, 1).unwrap(), - NaiveTime::from_hms_opt(0, 0, 0).unwrap() - ) - ); - } - - #[test] - fn chrono_for_year_month() { - #[cfg(feature = "chrono")] + #[cfg(feature = "chrono")] + fn chrono_for_duration() { + let duration = Duration { + months: 1, + seconds: 2, + microseconds: 3, + ..Default::default() + }; assert_eq!( - YearMonth(2020, 1).to_naive_date(), - NaiveDate::from_ymd_opt(2020, 1, 1).unwrap() + DurationWrapper::new(&duration).to_chrono_duration(), + chrono::Duration::new(1 * 30 * 24 * 60 * 60 + 2, 3 * 1000).unwrap() ); } #[test] + #[cfg(feature = "chrono")] fn chrono_for_date() { - #[cfg(feature = "chrono")] + let date = Date { + year: 2020, + month: 1, + day: 2, + ..Default::default() + }; assert_eq!( - Date(2020, 1, 2).to_naive_date(), + DateWrapper::new(&date, &TimezoneInfo::default()).to_naive_date(), NaiveDate::from_ymd_opt(2020, 1, 2).unwrap() ); } #[test] + #[cfg(feature = "chrono")] fn chrono_for_time() { - #[cfg(feature = "chrono")] + let time = Time { + hour: 1, + minute: 2, + sec: 3, + microsec: 4, + ..Default::default() + }; assert_eq!( - Time(1, 2, 3, 4).to_naive_date_time(), + TimeWrapper::new(&time, &TimezoneInfo::default()).to_naive_date_time(), NaiveDateTime::new( NaiveDate::default(), - NaiveTime::from_hms_milli_opt(1, 2, 3, 4).unwrap(), + NaiveTime::from_hms_micro_opt(1, 2, 3, 4).unwrap(), ) ); } #[test] + #[cfg(feature = "chrono")] fn chrono_for_datetime() { - #[cfg(feature = "chrono")] + let date_time = DateTime { + year: 2020, + month: 1, + day: 2, + hour: 3, + minute: 4, + sec: 5, + microsec: 6, + ..Default::default() + }; assert_eq!( - DateTime(2020, 1, 2, 3, 4, 5, 6, 7).to_naive_date_time(), + DateTimeWrapper::new(&date_time, &TimezoneInfo::default()).to_naive_date_time(), NaiveDateTime::new( NaiveDate::from_ymd_opt(2020, 1, 2).unwrap(), - NaiveTime::from_hms_milli_opt(3, 4, 5, 6).unwrap(), + NaiveTime::from_hms_micro_opt(3, 4, 5, 6).unwrap(), ) ); } diff --git a/src/value_wrapper/mod.rs b/src/value_wrapper/mod.rs index e65c39a..a01146d 100644 --- a/src/value_wrapper/mod.rs +++ b/src/value_wrapper/mod.rs @@ -1,11 +1,11 @@ use std::collections::HashMap; use crate::common::types::Value; -use crate::common::{Duration, Geography, NullType, Row}; +use crate::common::{Geography, NullType, Row}; use crate::data_deserializer::{DataDeserializeError, DataDeserializeErrorKind}; use crate::{DataSetError, TimezoneInfo}; -use datetime::{DataTimeWrapper, DateWrapper, TimeWrapper}; +use datetime::{DateTimeWrapper, DateWrapper, DurationWrapper, TimeWrapper}; use relationship::{Node, PathWrapper, Relationship}; pub mod datetime; @@ -21,7 +21,6 @@ fn new_conversion_error(from_type: String, to_type: String) -> DataSetError { #[derive(Debug)] pub struct ValueWrapper<'a> { value: &'a Value, - #[allow(dead_code)] timezone_info: &'a TimezoneInfo, } @@ -168,15 +167,36 @@ impl<'a> ValueWrapper<'a> { } pub fn as_time(&self) -> Result { - todo!("Implement conversion to TimeWrapper") + if let Value::tVal(v) = self.value { + Ok(TimeWrapper::new(v, self.timezone_info)) + } else { + Err(new_conversion_error( + self.get_type().to_string(), + "time".to_string(), + )) + } } pub fn as_date(&self) -> Result { - todo!("Implement conversion to DateWrapper") + if let Value::dVal(v) = self.value { + Ok(DateWrapper::new(v, self.timezone_info)) + } else { + Err(new_conversion_error( + self.get_type().to_string(), + "date".to_string(), + )) + } } - pub fn as_date_time(&self) -> Result { - todo!("Implement conversion to DateTimeWrapper") + pub fn as_date_time(&self) -> Result { + if let Value::dtVal(v) = self.value { + Ok(DateTimeWrapper::new(v, self.timezone_info)) + } else { + Err(new_conversion_error( + self.get_type().to_string(), + "datetime".to_string(), + )) + } } pub fn as_list(&self) -> Result, DataSetError> { @@ -208,8 +228,15 @@ impl<'a> ValueWrapper<'a> { todo!("Implement conversion to nebula::Geography") } - pub fn as_duration(&self) -> Result { - todo!("Implement conversion to nebula::Duration") + pub fn as_duration(&self) -> Result { + if let Value::duVal(v) = self.value { + Ok(DurationWrapper::new(v)) + } else { + Err(new_conversion_error( + self.get_type().to_string(), + "datetime".to_string(), + )) + } } }