refactor: datetime time unit (#2469)

* refactor: datetime time unit

* Update src/common/time/src/datetime.rs

Co-authored-by: Yingwen <realevenyag@gmail.com>

* chore: cr.

---------

Co-authored-by: Yingwen <realevenyag@gmail.com>
This commit is contained in:
Wei
2023-09-25 18:00:56 +08:00
committed by GitHub
parent 7ecfaa240f
commit 54e506a494
3 changed files with 39 additions and 20 deletions

View File

@@ -20,11 +20,12 @@ use serde::{Deserialize, Serialize};
use crate::error::{Error, InvalidDateStrSnafu, Result};
use crate::util::{format_utc_datetime, local_datetime_to_utc};
use crate::Date;
const DATETIME_FORMAT: &str = "%F %T";
const DATETIME_FORMAT_WITH_TZ: &str = "%F %T%z";
/// [DateTime] represents the **seconds elapsed since "1970-01-01 00:00:00 UTC" (UNIX Epoch)**.
/// [DateTime] represents the **milliseconds elapsed since "1970-01-01 00:00:00 UTC" (UNIX Epoch)**.
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
)]
@@ -32,7 +33,7 @@ pub struct DateTime(i64);
impl Display for DateTime {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if let Some(abs_time) = NaiveDateTime::from_timestamp_opt(self.0, 0) {
if let Some(abs_time) = NaiveDateTime::from_timestamp_millis(self.0) {
write!(
f,
"{}",
@@ -52,7 +53,7 @@ impl From<DateTime> for serde_json::Value {
impl From<NaiveDateTime> for DateTime {
fn from(value: NaiveDateTime) -> Self {
DateTime::from(value.timestamp())
DateTime::from(value.timestamp_millis())
}
}
@@ -61,20 +62,20 @@ impl FromStr for DateTime {
fn from_str(s: &str) -> Result<Self> {
let s = s.trim();
let timestamp = if let Ok(d) = NaiveDateTime::parse_from_str(s, DATETIME_FORMAT) {
let timestamp_millis = if let Ok(d) = NaiveDateTime::parse_from_str(s, DATETIME_FORMAT) {
match local_datetime_to_utc(&d) {
LocalResult::None => {
return InvalidDateStrSnafu { raw: s }.fail();
}
LocalResult::Single(d) | LocalResult::Ambiguous(d, _) => d.timestamp(),
LocalResult::Single(d) | LocalResult::Ambiguous(d, _) => d.timestamp_millis(),
}
} else if let Ok(v) = chrono::DateTime::parse_from_str(s, DATETIME_FORMAT_WITH_TZ) {
v.timestamp()
v.timestamp_millis()
} else {
return InvalidDateStrSnafu { raw: s }.fail();
};
Ok(Self(timestamp))
Ok(Self(timestamp_millis))
}
}
@@ -84,6 +85,13 @@ impl From<i64> for DateTime {
}
}
impl From<Date> for DateTime {
fn from(value: Date) -> Self {
// It's safe, i32 * 86400000 won't be overflow
Self(value.to_secs() * 1000)
}
}
impl DateTime {
pub fn new(val: i64) -> Self {
Self(val)
@@ -96,6 +104,10 @@ impl DateTime {
pub fn to_chrono_datetime(&self) -> Option<NaiveDateTime> {
NaiveDateTime::from_timestamp_opt(self.0, 0)
}
pub fn to_date(&self) -> Option<Date> {
self.to_chrono_datetime().map(|d| Date::from(d.date()))
}
}
#[cfg(test)]
@@ -106,8 +118,8 @@ mod tests {
pub fn test_new_date_time() {
std::env::set_var("TZ", "Asia/Shanghai");
assert_eq!("1970-01-01 08:00:00+0800", DateTime::new(0).to_string());
assert_eq!("1970-01-01 08:00:01+0800", DateTime::new(1).to_string());
assert_eq!("1970-01-01 07:59:59+0800", DateTime::new(-1).to_string());
assert_eq!("1970-01-01 08:00:01+0800", DateTime::new(1000).to_string());
assert_eq!("1970-01-01 07:59:59+0800", DateTime::new(-1000).to_string());
}
#[test]
@@ -130,7 +142,7 @@ mod tests {
fn test_parse_local_date_time() {
std::env::set_var("TZ", "Asia/Shanghai");
assert_eq!(
-28800,
-28800000,
DateTime::from_str("1970-01-01 00:00:00").unwrap().val()
);
assert_eq!(0, DateTime::from_str("1970-01-01 08:00:00").unwrap().val());
@@ -141,6 +153,13 @@ mod tests {
let ts = DateTime::from_str("1970-01-01 08:00:00+0000")
.unwrap()
.val();
assert_eq!(28800, ts);
assert_eq!(28800000, ts);
}
#[test]
fn test_from_max_date() {
let date = Date::new(i32::MAX);
let datetime = DateTime::from(date);
assert_eq!(datetime.val(), 185542587100800000);
}
}

View File

@@ -122,7 +122,7 @@ mod tests {
);
// cast from Timestamp
let val = Value::Timestamp(Timestamp::from_str("2020-09-08 21:42:29.042+0800").unwrap());
let val = Value::Timestamp(Timestamp::from_str("2020-09-08 21:42:29+0800").unwrap());
let dt = ConcreteDataType::datetime_datatype().try_cast(val).unwrap();
assert_eq!(
dt,

View File

@@ -38,7 +38,7 @@ mod tests {
#[test]
fn test_datetime_vector() {
std::env::set_var("TZ", "Asia/Shanghai");
let v = DateTimeVector::new(PrimitiveArray::from(vec![1, 2, 3]));
let v = DateTimeVector::new(PrimitiveArray::from(vec![1000, 2000, 3000]));
assert_eq!(ConcreteDataType::datetime_datatype(), v.data_type());
assert_eq!(3, v.len());
assert_eq!("DateTimeVector", v.vector_type_name());
@@ -47,19 +47,19 @@ mod tests {
v.to_arrow_array().data_type()
);
assert_eq!(Some(DateTime::new(1)), v.get_data(0));
assert_eq!(Value::DateTime(DateTime::new(1)), v.get(0));
assert_eq!(ValueRef::DateTime(DateTime::new(1)), v.get_ref(0));
assert_eq!(Some(DateTime::new(1000)), v.get_data(0));
assert_eq!(Value::DateTime(DateTime::new(1000)), v.get(0));
assert_eq!(ValueRef::DateTime(DateTime::new(1000)), v.get_ref(0));
let mut iter = v.iter_data();
assert_eq!(Some(DateTime::new(1)), iter.next().unwrap());
assert_eq!(Some(DateTime::new(2)), iter.next().unwrap());
assert_eq!(Some(DateTime::new(3)), iter.next().unwrap());
assert_eq!(Some(DateTime::new(1000)), iter.next().unwrap());
assert_eq!(Some(DateTime::new(2000)), iter.next().unwrap());
assert_eq!(Some(DateTime::new(3000)), iter.next().unwrap());
assert!(!v.is_null(0));
assert_eq!(24, v.memory_size());
if let Value::DateTime(d) = v.get(0) {
assert_eq!(1, d.val());
assert_eq!(1000, d.val());
} else {
unreachable!()
}