mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-17 13:30:38 +00:00
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:
@@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user