Skip to content

Commit c274baf

Browse files
committed
refactor: improve decode of timestamp
1 parent 8bd96c9 commit c274baf

File tree

3 files changed

+14
-38
lines changed

3 files changed

+14
-38
lines changed

sql/src/value/arrow_decoder.rs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use arrow_array::{
2222
StructArray, TimestampMicrosecondArray, UInt16Array, UInt32Array, UInt64Array, UInt8Array,
2323
};
2424
use arrow_schema::{DataType as ArrowDataType, Field as ArrowField, TimeUnit};
25-
use chrono::{DateTime, FixedOffset};
25+
use chrono::{FixedOffset, TimeZone};
2626
use chrono_tz::Tz;
2727
use databend_client::schema::{
2828
DecimalSize, ARROW_EXT_TYPE_BITMAP, ARROW_EXT_TYPE_EMPTY_ARRAY, ARROW_EXT_TYPE_EMPTY_MAP,
@@ -92,22 +92,11 @@ impl TryFrom<(&ArrowField, &Arc<dyn ArrowArray>, usize, Tz)> for Value {
9292
match array.as_any().downcast_ref::<Decimal128Array>() {
9393
Some(array) => {
9494
let v = array.value(seq);
95-
let ts = v as u64 as i64;
95+
let unix_ts = v as u64 as i64;
9696
let offset = (v >> 64) as i32;
97-
98-
let secs = ts / 1_000_000;
99-
let nanos = ((ts % 1_000_000) * 1000) as u32;
100-
let dt = match DateTime::from_timestamp(secs, nanos) {
101-
Some(t) => {
102-
let off = FixedOffset::east_opt(offset).ok_or_else(|| {
103-
Error::Parsing("invalid offset".to_string())
104-
})?;
105-
t.with_timezone(&off)
106-
}
107-
None => {
108-
return Err(ConvertError::new("Datetime", format!("{v}")).into())
109-
}
110-
};
97+
let offset = FixedOffset::east_opt(offset)
98+
.ok_or_else(|| Error::Parsing("invalid offset".to_string()))?;
99+
let dt = offset.timestamp_micros(unix_ts).single().unwrap();
111100
Ok(Value::TimestampTz(dt))
112101
}
113102
None => Err(ConvertError::new("Interval", format!("{array:?}")).into()),

sql/src/value/convert.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,10 @@ impl TryFrom<Value> for NaiveDateTime {
109109
type Error = Error;
110110
fn try_from(val: Value) -> Result<Self> {
111111
match val {
112-
Value::Timestamp(i, _tz) => {
113-
let secs = i / 1_000_000;
114-
let nanos = ((i % 1_000_000) * 1000) as u32;
115-
match DateTime::from_timestamp(secs, nanos) {
116-
Some(t) => Ok(t.naive_utc()),
117-
None => Err(ConvertError::new("NaiveDateTime", format!("{val}")).into()),
118-
}
119-
}
112+
Value::Timestamp(i, _tz) => match DateTime::from_timestamp_micros(i) {
113+
Some(t) => Ok(t.naive_utc()),
114+
None => Err(ConvertError::new("NaiveDateTime", format!("{val}")).into()),
115+
},
120116
_ => Err(ConvertError::new("NaiveDateTime", format!("{val}")).into()),
121117
}
122118
}
@@ -126,14 +122,10 @@ impl TryFrom<Value> for DateTime<Tz> {
126122
type Error = Error;
127123
fn try_from(val: Value) -> Result<Self> {
128124
match val {
129-
Value::Timestamp(i, tz) => {
130-
let secs = i / 1_000_000;
131-
let nanos = ((i % 1_000_000) * 1000) as u32;
132-
match DateTime::from_timestamp(secs, nanos) {
133-
Some(t) => Ok(tz.from_utc_datetime(&t.naive_utc())),
134-
None => Err(ConvertError::new("Datetime", format!("{val}")).into()),
135-
}
136-
}
125+
Value::Timestamp(i, tz) => match DateTime::from_timestamp_micros(i) {
126+
Some(t) => Ok(tz.from_utc_datetime(&t.naive_utc())),
127+
None => Err(ConvertError::new("Datetime", format!("{val}")).into()),
128+
},
137129
_ => Err(ConvertError::new("DateTime", format!("{val}")).into()),
138130
}
139131
}

sql/src/value/format.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,7 @@ fn encode_value(f: &mut std::fmt::Formatter<'_>, val: &Value, raw: bool) -> std:
7474
}
7575
}
7676
Value::Timestamp(micros, _tz) => {
77-
let (mut secs, mut nanos) = (*micros / 1_000_000, (*micros % 1_000_000) * 1_000);
78-
if nanos < 0 {
79-
secs -= 1;
80-
nanos += 1_000_000_000;
81-
}
82-
let t = DateTime::from_timestamp(secs, nanos as _).unwrap_or_default();
77+
let t = DateTime::from_timestamp_micros(*micros).unwrap_or_default();
8378
let t = t.naive_utc();
8479
if raw {
8580
write!(f, "{}", t.format(TIMESTAMP_FORMAT))

0 commit comments

Comments
 (0)