Skip to content

Commit bb087e7

Browse files
authored
[Py-client] Query Timestamp type of values return readable format
1 parent a17ec67 commit bb087e7

17 files changed

+170
-43
lines changed

iotdb-client/client-py/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ session.close()
7373
* Initialize a Session
7474

7575
```python
76-
session = Session(ip, port_, username_, password_, fetch_size=1024, zone_id="UTC+8")
76+
session = Session(ip, port_, username_, password_, fetch_size=1024, zone_id="Asia/Shanghai")
7777
```
7878

7979
* Open a session, with a parameter to specify whether to enable RPC compression
@@ -375,7 +375,7 @@ ip = "127.0.0.1"
375375
port_ = "6667"
376376
username_ = "root"
377377
password_ = "root"
378-
conn = connect(ip, port_, username_, password_,fetch_size=1024,zone_id="UTC+8",sqlalchemy_mode=False)
378+
conn = connect(ip, port_, username_, password_,fetch_size=1024,zone_id="Asia/Shanghai",sqlalchemy_mode=False)
379379
cursor = conn.cursor()
380380
```
381381
+ simple SQL statement execution

iotdb-client/client-py/iotdb/Session.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
import random
2121
import sys
2222
import struct
23-
import time
2423
import warnings
2524
from thrift.protocol import TBinaryProtocol, TCompactProtocol
2625
from thrift.transport import TSocket, TTransport
26+
from tzlocal import get_localzone_name
2727

2828
from iotdb.utils.SessionDataSet import SessionDataSet
2929
from .template.Template import Template
@@ -71,7 +71,7 @@ class Session(object):
7171
DEFAULT_FETCH_SIZE = 5000
7272
DEFAULT_USER = "root"
7373
DEFAULT_PASSWORD = "root"
74-
DEFAULT_ZONE_ID = time.strftime("%z")
74+
DEFAULT_ZONE_ID = get_localzone_name()
7575
RETRY_NUM = 3
7676
SQL_DIALECT = "tree"
7777

@@ -112,6 +112,7 @@ def __init__(
112112
self.__use_ssl = use_ssl
113113
self.__ca_certs = ca_certs
114114
self.__connection_timeout_in_ms = connection_timeout_in_ms
115+
self.__time_precision = "ms"
115116

116117
@classmethod
117118
def init_from_node_urls(
@@ -206,6 +207,11 @@ def init_connection(self, endpoint):
206207
try:
207208
open_resp = client.openSession(open_req)
208209
rpc_utils.verify_success(open_resp.status)
210+
if open_resp.configuration is not None:
211+
if "timestamp_precision" in open_resp.configuration:
212+
self.__time_precision = open_resp.configuration[
213+
"timestamp_precision"
214+
]
209215

210216
if self.protocol_version != open_resp.serverProtocolVersion:
211217
logger.exception(
@@ -1518,6 +1524,8 @@ def execute_query_statement(self, sql, timeout=0):
15181524
timeout,
15191525
resp.moreData,
15201526
self.__fetch_size,
1527+
self.__zone_id,
1528+
self.__time_precision,
15211529
resp.columnIndex2TsBlockColumnIndexList,
15221530
)
15231531

@@ -1587,6 +1595,8 @@ def execute_statement(self, sql: str, timeout=0):
15871595
timeout,
15881596
resp.moreData,
15891597
self.__fetch_size,
1598+
self.__zone_id,
1599+
self.__time_precision,
15901600
resp.columnIndex2TsBlockColumnIndexList,
15911601
)
15921602
else:
@@ -1748,6 +1758,8 @@ def execute_raw_data_query(
17481758
0,
17491759
resp.moreData,
17501760
self.__fetch_size,
1761+
self.__zone_id,
1762+
self.__time_precision,
17511763
resp.columnIndex2TsBlockColumnIndexList,
17521764
)
17531765

@@ -1793,6 +1805,8 @@ def execute_last_data_query(self, paths: list, last_time: int) -> SessionDataSet
17931805
0,
17941806
resp.moreData,
17951807
self.__fetch_size,
1808+
self.__zone_id,
1809+
self.__time_precision,
17961810
resp.columnIndex2TsBlockColumnIndexList,
17971811
)
17981812

iotdb-client/client-py/iotdb/SessionPool.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
from queue import Queue
2222
from threading import Lock
2323

24+
from tzlocal import get_localzone_name
25+
2426
from iotdb.Session import Session
2527

2628
DEFAULT_MULTIPIE = 5
2729
DEFAULT_FETCH_SIZE = 5000
2830
DEFAULT_MAX_RETRY = 3
29-
DEFAULT_TIME_ZONE = "UTC+8"
31+
DEFAULT_TIME_ZONE = get_localzone_name()
3032
SQL_DIALECT = "tree"
3133
logger = logging.getLogger("IoTDB")
3234

iotdb-client/client-py/iotdb/utils/Field.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@
1919
# for package
2020
from iotdb.utils.IoTDBConstants import TSDataType
2121
from iotdb.tsfile.utils.date_utils import parse_int_to_date
22+
from iotdb.utils.rpc_utils import convert_to_timestamp, isoformat
2223
import numpy as np
2324
import pandas as pd
2425

2526

2627
class Field(object):
27-
def __init__(self, data_type, value=None):
28+
def __init__(self, data_type, value=None, timezone=None, precision=None):
2829
"""
2930
:param data_type: TSDataType
3031
"""
3132
self.__data_type = data_type
3233
self.value = value
34+
self.__timezone = timezone
35+
self.__precision = precision
3336

3437
@staticmethod
3538
def copy(field):
@@ -157,6 +160,17 @@ def get_binary_value(self):
157160
return None
158161
return self.value
159162

163+
def get_timestamp_value(self):
164+
if self.__data_type is None:
165+
raise Exception("Null Field Exception!")
166+
if (
167+
self.__data_type != TSDataType.TIMESTAMP
168+
or self.value is None
169+
or self.value is pd.NA
170+
):
171+
return None
172+
return convert_to_timestamp(self.value, self.__precision, self.__timezone)
173+
160174
def get_date_value(self):
161175
if self.__data_type is None:
162176
raise Exception("Null Field Exception!")
@@ -172,11 +186,18 @@ def get_string_value(self):
172186
if self.__data_type is None or self.value is None or self.value is pd.NA:
173187
return "None"
174188
# TEXT, STRING
175-
elif self.__data_type == 5 or self.__data_type == 11:
189+
if self.__data_type == 5 or self.__data_type == 11:
176190
return self.value.decode("utf-8")
177191
# BLOB
178192
elif self.__data_type == 10:
179193
return str(hex(int.from_bytes(self.value, byteorder="big")))
194+
# TIMESTAMP
195+
elif self.__data_type == 8:
196+
return isoformat(
197+
convert_to_timestamp(self.value, self.__precision, self.__timezone),
198+
self.__precision,
199+
)
200+
# Others
180201
else:
181202
return str(self.get_object_value(self.__data_type))
182203

@@ -193,12 +214,14 @@ def get_object_value(self, data_type):
193214
return bool(self.value)
194215
elif data_type == 1:
195216
return np.int32(self.value)
196-
elif data_type == 2 or data_type == 8:
217+
elif data_type == 2:
197218
return np.int64(self.value)
198219
elif data_type == 3:
199220
return np.float32(self.value)
200221
elif data_type == 4:
201222
return np.float64(self.value)
223+
elif data_type == 8:
224+
return convert_to_timestamp(self.value, self.__precision, self.__timezone)
202225
elif data_type == 9:
203226
return parse_int_to_date(self.value)
204227
elif data_type == 5 or data_type == 11:

iotdb-client/client-py/iotdb/utils/SessionDataSet.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ def __init__(
4545
time_out,
4646
more_data,
4747
fetch_size,
48+
zone_id,
49+
time_precision,
4850
column_index_2_tsblock_column_index_list,
4951
):
5052
self.iotdb_rpc_data_set = IoTDBRpcDataSet(
5153
sql,
5254
column_name_list,
5355
column_type_list,
54-
column_name_index,
5556
ignore_timestamp,
5657
more_data,
5758
query_id,
@@ -61,16 +62,26 @@ def __init__(
6162
query_result,
6263
fetch_size,
6364
time_out,
65+
zone_id,
66+
time_precision,
6467
column_index_2_tsblock_column_index_list,
6568
)
6669
if ignore_timestamp:
6770
self.__field_list = [
68-
Field(data_type)
71+
(
72+
Field(data_type, timezone=zone_id, precision=time_precision)
73+
if data_type == 8
74+
else Field(data_type)
75+
)
6976
for data_type in self.iotdb_rpc_data_set.get_column_types()
7077
]
7178
else:
7279
self.__field_list = [
73-
Field(data_type)
80+
(
81+
Field(data_type, timezone=zone_id, precision=time_precision)
82+
if data_type == 8
83+
else Field(data_type)
84+
)
7485
for data_type in self.iotdb_rpc_data_set.get_column_types()[1:]
7586
]
7687
self.row_index = 0
@@ -155,7 +166,7 @@ def get_typed_point(field: Field, none_value=None):
155166
TSDataType.INT32: lambda f: f.get_int_value(),
156167
TSDataType.DOUBLE: lambda f: f.get_double_value(),
157168
TSDataType.INT64: lambda f: f.get_long_value(),
158-
TSDataType.TIMESTAMP: lambda f: f.get_long_value(),
169+
TSDataType.TIMESTAMP: lambda f: f.get_timestamp_value(),
159170
TSDataType.STRING: lambda f: f.get_string_value(),
160171
TSDataType.DATE: lambda f: f.get_date_value(),
161172
TSDataType.BLOB: lambda f: f.get_binary_value(),

iotdb-client/client-py/iotdb/utils/iotdb_rpc_dataset.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from iotdb.tsfile.utils.tsblock_serde import deserialize
2929
from iotdb.utils.exception import IoTDBConnectionException
3030
from iotdb.utils.IoTDBConstants import TSDataType
31-
from iotdb.utils.rpc_utils import verify_success
31+
from iotdb.utils.rpc_utils import verify_success, convert_to_timestamp
3232

3333
logger = logging.getLogger("IoTDB")
3434
TIMESTAMP_STR = "Time"
@@ -41,7 +41,6 @@ def __init__(
4141
sql,
4242
column_name_list,
4343
column_type_list,
44-
column_name_index,
4544
ignore_timestamp,
4645
more_data,
4746
query_id,
@@ -51,6 +50,8 @@ def __init__(
5150
query_result,
5251
fetch_size,
5352
time_out,
53+
zone_id,
54+
time_precision,
5455
column_index_2_tsblock_column_index_list,
5556
):
5657
self.__statement_id = statement_id
@@ -117,6 +118,8 @@ def __init__(
117118
self.__empty_resultSet = False
118119
self.has_cached_data_frame = False
119120
self.data_frame = None
121+
self.__zone_id = zone_id
122+
self.__time_precision = time_precision
120123

121124
def close(self):
122125
if self.__is_closed:
@@ -155,7 +158,7 @@ def next(self):
155158

156159
def construct_one_data_frame(self):
157160
if self.has_cached_data_frame or self.__query_result is None:
158-
return True
161+
return
159162
result = {}
160163
has_pd_series = []
161164
for i in range(len(self.__column_index_2_tsblock_column_index_list)):
@@ -264,8 +267,8 @@ def result_set_to_pandas(self):
264267
continue
265268
data_type = self.__data_type_for_tsblock_column[location]
266269
column_array = column_arrays[location]
267-
# BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TIMESTAMP, BLOB
268-
if data_type in (0, 1, 2, 3, 4, 8, 10):
270+
# BOOLEAN, INT32, INT64, FLOAT, DOUBLE, BLOB
271+
if data_type in (0, 1, 2, 3, 4, 10):
269272
data_array = column_array
270273
if (
271274
data_type != 10
@@ -278,6 +281,17 @@ def result_set_to_pandas(self):
278281
# TEXT, STRING
279282
elif data_type in (5, 11):
280283
data_array = np.array([x.decode("utf-8") for x in column_array])
284+
# TIMESTAMP
285+
elif data_type == 8:
286+
data_array = pd.Series(
287+
[
288+
convert_to_timestamp(
289+
x, self.__time_precision, self.__zone_id
290+
)
291+
for x in column_array
292+
],
293+
dtype=object,
294+
)
281295
# DATE
282296
elif data_type == 9:
283297
data_array = pd.Series(column_array).apply(parse_int_to_date)
@@ -289,25 +303,21 @@ def result_set_to_pandas(self):
289303
data_type == 0 and null_indicator is not None
290304
):
291305
tmp_array = []
292-
# BOOLEAN, INT32, INT64, TIMESTAMP
293-
if (
294-
data_type == 0
295-
or data_type == 1
296-
or data_type == 2
297-
or data_type == 8
298-
):
306+
# BOOLEAN, INT32, INT64
307+
if data_type == 0 or data_type == 1 or data_type == 2:
299308
tmp_array = np.full(array_length, pd.NA, dtype=object)
300309
# FLOAT, DOUBLE
301310
elif data_type == 3 or data_type == 4:
302311
tmp_array = np.full(
303312
array_length, np.nan, dtype=data_type.np_dtype()
304313
)
305-
# TEXT, STRING, BLOB, DATE
314+
# TEXT, STRING, BLOB, DATE, TIMESTAMP
306315
elif (
307316
data_type == 5
308317
or data_type == 11
309318
or data_type == 10
310319
or data_type == 9
320+
or data_type == 8
311321
):
312322
tmp_array = np.full(array_length, None, dtype=object)
313323

@@ -320,7 +330,7 @@ def result_set_to_pandas(self):
320330

321331
if data_type == 1:
322332
tmp_array = pd.Series(tmp_array).astype("Int32")
323-
elif data_type == 2 or data_type == 8:
333+
elif data_type == 2:
324334
tmp_array = pd.Series(tmp_array).astype("Int64")
325335
elif data_type == 0:
326336
tmp_array = pd.Series(tmp_array).astype("boolean")

0 commit comments

Comments
 (0)