feat!: do not get TZ info from server local env (#2905)

* feat: do not get TZ info from server local env

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* add sqlness case

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* add empty line

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* fix typo

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

---------

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
This commit is contained in:
Ruihang Xia
2023-12-12 20:41:05 +08:00
committed by GitHub
parent 34635558d2
commit 0ce2b50676
5 changed files with 63 additions and 83 deletions

View File

@@ -21,15 +21,14 @@ use std::time::Duration;
use arrow::datatypes::TimeUnit as ArrowTimeUnit;
use chrono::{
DateTime, Days, LocalResult, Months, NaiveDate, NaiveDateTime, NaiveTime,
TimeZone as ChronoTimeZone, Utc,
DateTime, Days, Months, NaiveDate, NaiveDateTime, NaiveTime, TimeZone as ChronoTimeZone, Utc,
};
use serde::{Deserialize, Serialize};
use snafu::{OptionExt, ResultExt};
use crate::error::{ArithmeticOverflowSnafu, Error, ParseTimestampSnafu, TimestampOverflowSnafu};
use crate::timezone::TimeZone;
use crate::util::{div_ceil, format_utc_datetime, local_datetime_to_utc};
use crate::util::{div_ceil, format_utc_datetime};
use crate::{error, Interval};
/// Timestamp represents the value of units(seconds/milliseconds/microseconds/nanoseconds) elapsed
@@ -364,11 +363,11 @@ impl FromStr for Timestamp {
/// Supported format:
/// - `2022-09-20T14:16:43.012345Z` (Zulu timezone)
/// - `2022-09-20T14:16:43.012345+08:00` (Explicit offset)
/// - `2022-09-20T14:16:43.012345` (local timezone, with T)
/// - `2022-09-20T14:16:43` (local timezone, no fractional seconds, with T)
/// - `2022-09-20T14:16:43.012345` (Zulu timezone, with T)
/// - `2022-09-20T14:16:43` (Zulu timezone, no fractional seconds, with T)
/// - `2022-09-20 14:16:43.012345Z` (Zulu timezone, without T)
/// - `2022-09-20 14:16:43` (local timezone, without T)
/// - `2022-09-20 14:16:43.012345` (local timezone, without T)
/// - `2022-09-20 14:16:43` (Zulu timezone, without T)
/// - `2022-09-20 14:16:43.012345` (Zulu timezone, without T)
#[allow(deprecated)]
fn from_str(s: &str) -> Result<Self, Self::Err> {
// RFC3339 timestamp (with a T)
@@ -407,18 +406,13 @@ impl FromStr for Timestamp {
}
/// Converts the naive datetime (which has no specific timezone) to a
/// nanosecond epoch timestamp relative to UTC.
/// This code is copied from [arrow-datafusion](https://github.com/apache/arrow-datafusion/blob/arrow2/datafusion-physical-expr/src/arrow_temporal_util.rs#L137).
/// nanosecond epoch timestamp in UTC.
fn naive_datetime_to_timestamp(
s: &str,
datetime: NaiveDateTime,
) -> crate::error::Result<Timestamp> {
match local_datetime_to_utc(&datetime) {
LocalResult::None => ParseTimestampSnafu { raw: s }.fail(),
LocalResult::Single(utc) | LocalResult::Ambiguous(utc, _) => {
Timestamp::from_chrono_datetime(utc).context(ParseTimestampSnafu { raw: s })
}
}
Timestamp::from_chrono_datetime(Utc.from_utc_datetime(&datetime).naive_utc())
.context(ParseTimestampSnafu { raw: s })
}
impl From<i64> for Timestamp {
@@ -562,7 +556,6 @@ impl Hash for Timestamp {
mod tests {
use std::collections::hash_map::DefaultHasher;
use chrono::{Local, Offset};
use rand::Rng;
use serde_json::Value;
@@ -783,71 +776,11 @@ mod tests {
check_from_str("2020-09-08 13:42:29Z", "2020-09-08 13:42:29");
check_from_str("2020-09-08T13:42:29+08:00", "2020-09-08 05:42:29");
check_from_str(
"2020-09-08 13:42:29",
&NaiveDateTime::from_timestamp_opt(
1599572549
- Local
.timestamp_opt(0, 0)
.unwrap()
.offset()
.fix()
.local_minus_utc() as i64,
0,
)
.unwrap()
.to_string(),
);
check_from_str("2020-09-08 13:42:29", "2020-09-08 13:42:29");
check_from_str(
"2020-09-08T13:42:29",
&NaiveDateTime::from_timestamp_opt(
1599572549
- Local
.timestamp_opt(0, 0)
.unwrap()
.offset()
.fix()
.local_minus_utc() as i64,
0,
)
.unwrap()
.to_string(),
);
check_from_str(
"2020-09-08 13:42:29.042",
&NaiveDateTime::from_timestamp_opt(
1599572549
- Local
.timestamp_opt(0, 0)
.unwrap()
.offset()
.fix()
.local_minus_utc() as i64,
42000000,
)
.unwrap()
.to_string(),
);
check_from_str("2020-09-08 13:42:29.042Z", "2020-09-08 13:42:29.042");
check_from_str("2020-09-08 13:42:29.042+08:00", "2020-09-08 05:42:29.042");
check_from_str(
"2020-09-08T13:42:29.042",
&NaiveDateTime::from_timestamp_opt(
1599572549
- Local
.timestamp_opt(0, 0)
.unwrap()
.offset()
.fix()
.local_minus_utc() as i64,
42000000,
)
.unwrap()
.to_string(),
);
check_from_str("2020-09-08T13:42:29+08:00", "2020-09-08 05:42:29");
check_from_str(
"2020-09-08T13:42:29.0042+08:00",
"2020-09-08 05:42:29.004200",
@@ -1119,21 +1052,22 @@ mod tests {
assert_eq!(TimeUnit::Second, res.unit);
}
// $TZ doesn't take effort.
#[test]
fn test_parse_in_time_zone() {
std::env::set_var("TZ", "Asia/Shanghai");
assert_eq!(
Timestamp::new(0, TimeUnit::Nanosecond),
Timestamp::new(28800, TimeUnit::Second),
Timestamp::from_str("1970-01-01 08:00:00.000").unwrap()
);
assert_eq!(
Timestamp::new(0, TimeUnit::Second),
Timestamp::new(28800, TimeUnit::Second),
Timestamp::from_str("1970-01-01 08:00:00").unwrap()
);
assert_eq!(
Timestamp::new(0, TimeUnit::Second),
Timestamp::new(28800, TimeUnit::Second),
Timestamp::from_str(" 1970-01-01 08:00:00 ").unwrap()
);
}

View File

@@ -105,6 +105,7 @@ mod tests {
use super::*;
// $TZ doesn't take effort
#[test]
fn test_date_cast() {
std::env::set_var("TZ", "Asia/Shanghai");
@@ -113,9 +114,14 @@ mod tests {
let date = ConcreteDataType::date_datatype().try_cast(ts).unwrap();
assert_eq!(date, Value::Date(Date::from_str("2000-01-01").unwrap()));
// this case bind with local timezone.
// this case bind with Zulu timezone.
let ts = Value::Timestamp(Timestamp::from_str("2000-01-02 07:59:59").unwrap());
let date = ConcreteDataType::date_datatype().try_cast(ts).unwrap();
assert_eq!(date, Value::Date(Date::from_str("2000-01-02").unwrap()));
// while this case is offsetted to Asia/Shanghai.
let ts = Value::Timestamp(Timestamp::from_str("2000-01-02 07:59:59+08:00").unwrap());
let date = ConcreteDataType::date_datatype().try_cast(ts).unwrap();
assert_eq!(date, Value::Date(Date::from_str("2000-01-01").unwrap()));
// Int32 -> date

View File

@@ -227,6 +227,7 @@ mod tests {
);
}
// $TZ doesn't take effort
#[test]
fn test_timestamp_cast() {
std::env::set_var("TZ", "Asia/Shanghai");
@@ -235,7 +236,8 @@ mod tests {
let ts = ConcreteDataType::timestamp_second_datatype()
.try_cast(s)
.unwrap();
assert_eq!(ts, Value::Timestamp(Timestamp::new_second(1609434123)));
// 1609462923 is 2021-01-01T01:02:03Z
assert_eq!(ts, Value::Timestamp(Timestamp::new_second(1609462923)));
// String cast failed
let s = Value::String("12345".to_string().into());
let ts = ConcreteDataType::timestamp_second_datatype().try_cast(s);

View File

@@ -82,3 +82,31 @@ DROP TABLE timestamp_with_precision;
Affected Rows: 0
CREATE TABLE plain_timestamp (ts TIMESTAMP TIME INDEX);
Affected Rows: 0
INSERT INTO plain_timestamp VALUES (1);
Affected Rows: 1
SELECT * FROM plain_timestamp;
+-------------------------+
| ts |
+-------------------------+
| 1970-01-01T00:00:00.001 |
+-------------------------+
SELECT * FROM plain_timestamp where ts = '1970-01-01 00:00:00.001000';
+-------------------------+
| ts |
+-------------------------+
| 1970-01-01T00:00:00.001 |
+-------------------------+
DROP TABLE plain_timestamp;
Affected Rows: 0

View File

@@ -29,3 +29,13 @@ INSERT INTO timestamp_with_precision(ts,cnt) VALUES ('2262-04-11 23:47:16.854775
SELECT * FROM timestamp_with_precision ORDER BY ts ASC;
DROP TABLE timestamp_with_precision;
CREATE TABLE plain_timestamp (ts TIMESTAMP TIME INDEX);
INSERT INTO plain_timestamp VALUES (1);
SELECT * FROM plain_timestamp;
SELECT * FROM plain_timestamp where ts = '1970-01-01 00:00:00.001000';
DROP TABLE plain_timestamp;