This is an automated email from the ASF dual-hosted git repository.

jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new bb087e7bc64 [Py-client] Query Timestamp type of values return readable 
format
bb087e7bc64 is described below

commit bb087e7bc6486889dfccc0b727161af3e9c336e9
Author: Haonan <[email protected]>
AuthorDate: Fri Apr 25 16:16:49 2025 +0800

    [Py-client] Query Timestamp type of values return readable format
---
 iotdb-client/client-py/README.md                   |  4 +--
 iotdb-client/client-py/iotdb/Session.py            | 18 ++++++++--
 iotdb-client/client-py/iotdb/SessionPool.py        |  4 ++-
 iotdb-client/client-py/iotdb/utils/Field.py        | 29 +++++++++++++--
 .../client-py/iotdb/utils/SessionDataSet.py        | 19 +++++++---
 .../client-py/iotdb/utils/iotdb_rpc_dataset.py     | 38 ++++++++++++--------
 iotdb-client/client-py/iotdb/utils/rpc_utils.py    | 41 ++++++++++++++++++++++
 iotdb-client/client-py/requirements.txt            |  1 +
 iotdb-client/client-py/resources/pyproject.toml    |  3 +-
 .../session_aligned_timeseries_example.py          |  4 ++-
 iotdb-client/client-py/session_example.py          |  4 +--
 iotdb-client/client-py/session_pool_example.py     |  2 +-
 iotdb-client/client-py/session_ssl_example.py      |  4 +--
 .../client-py/table_model_session_example.py       |  4 +--
 .../integration/tablet_performance_comparison.py   |  4 ++-
 .../tests/integration/test_new_data_types.py       | 12 +++----
 .../tests/integration/test_tablemodel_query.py     | 22 +++++++++++-
 17 files changed, 170 insertions(+), 43 deletions(-)

diff --git a/iotdb-client/client-py/README.md b/iotdb-client/client-py/README.md
index cf87012e036..2cdf23b5e12 100644
--- a/iotdb-client/client-py/README.md
+++ b/iotdb-client/client-py/README.md
@@ -73,7 +73,7 @@ session.close()
 * Initialize a Session
 
 ```python
-session = Session(ip, port_, username_, password_, fetch_size=1024, 
zone_id="UTC+8")
+session = Session(ip, port_, username_, password_, fetch_size=1024, 
zone_id="Asia/Shanghai")
 ```
 
 * Open a session, with a parameter to specify whether to enable RPC compression
@@ -375,7 +375,7 @@ ip = "127.0.0.1"
 port_ = "6667"
 username_ = "root"
 password_ = "root"
-conn = connect(ip, port_, username_, 
password_,fetch_size=1024,zone_id="UTC+8",sqlalchemy_mode=False)
+conn = connect(ip, port_, username_, 
password_,fetch_size=1024,zone_id="Asia/Shanghai",sqlalchemy_mode=False)
 cursor = conn.cursor()
 ```
 + simple SQL statement execution
diff --git a/iotdb-client/client-py/iotdb/Session.py 
b/iotdb-client/client-py/iotdb/Session.py
index 6bb9a5860f2..3f44bd41584 100644
--- a/iotdb-client/client-py/iotdb/Session.py
+++ b/iotdb-client/client-py/iotdb/Session.py
@@ -20,10 +20,10 @@ import logging
 import random
 import sys
 import struct
-import time
 import warnings
 from thrift.protocol import TBinaryProtocol, TCompactProtocol
 from thrift.transport import TSocket, TTransport
+from tzlocal import get_localzone_name
 
 from iotdb.utils.SessionDataSet import SessionDataSet
 from .template.Template import Template
@@ -71,7 +71,7 @@ class Session(object):
     DEFAULT_FETCH_SIZE = 5000
     DEFAULT_USER = "root"
     DEFAULT_PASSWORD = "root"
-    DEFAULT_ZONE_ID = time.strftime("%z")
+    DEFAULT_ZONE_ID = get_localzone_name()
     RETRY_NUM = 3
     SQL_DIALECT = "tree"
 
@@ -112,6 +112,7 @@ class Session(object):
         self.__use_ssl = use_ssl
         self.__ca_certs = ca_certs
         self.__connection_timeout_in_ms = connection_timeout_in_ms
+        self.__time_precision = "ms"
 
     @classmethod
     def init_from_node_urls(
@@ -206,6 +207,11 @@ class Session(object):
         try:
             open_resp = client.openSession(open_req)
             rpc_utils.verify_success(open_resp.status)
+            if open_resp.configuration is not None:
+                if "timestamp_precision" in open_resp.configuration:
+                    self.__time_precision = open_resp.configuration[
+                        "timestamp_precision"
+                    ]
 
             if self.protocol_version != open_resp.serverProtocolVersion:
                 logger.exception(
@@ -1518,6 +1524,8 @@ class Session(object):
             timeout,
             resp.moreData,
             self.__fetch_size,
+            self.__zone_id,
+            self.__time_precision,
             resp.columnIndex2TsBlockColumnIndexList,
         )
 
@@ -1587,6 +1595,8 @@ class Session(object):
                 timeout,
                 resp.moreData,
                 self.__fetch_size,
+                self.__zone_id,
+                self.__time_precision,
                 resp.columnIndex2TsBlockColumnIndexList,
             )
         else:
@@ -1748,6 +1758,8 @@ class Session(object):
             0,
             resp.moreData,
             self.__fetch_size,
+            self.__zone_id,
+            self.__time_precision,
             resp.columnIndex2TsBlockColumnIndexList,
         )
 
@@ -1793,6 +1805,8 @@ class Session(object):
             0,
             resp.moreData,
             self.__fetch_size,
+            self.__zone_id,
+            self.__time_precision,
             resp.columnIndex2TsBlockColumnIndexList,
         )
 
diff --git a/iotdb-client/client-py/iotdb/SessionPool.py 
b/iotdb-client/client-py/iotdb/SessionPool.py
index 3502cc24eac..1e34186b2e0 100644
--- a/iotdb-client/client-py/iotdb/SessionPool.py
+++ b/iotdb-client/client-py/iotdb/SessionPool.py
@@ -21,12 +21,14 @@ import time
 from queue import Queue
 from threading import Lock
 
+from tzlocal import get_localzone_name
+
 from iotdb.Session import Session
 
 DEFAULT_MULTIPIE = 5
 DEFAULT_FETCH_SIZE = 5000
 DEFAULT_MAX_RETRY = 3
-DEFAULT_TIME_ZONE = "UTC+8"
+DEFAULT_TIME_ZONE = get_localzone_name()
 SQL_DIALECT = "tree"
 logger = logging.getLogger("IoTDB")
 
diff --git a/iotdb-client/client-py/iotdb/utils/Field.py 
b/iotdb-client/client-py/iotdb/utils/Field.py
index 2b9d7af0f70..d9a0ee77776 100644
--- a/iotdb-client/client-py/iotdb/utils/Field.py
+++ b/iotdb-client/client-py/iotdb/utils/Field.py
@@ -19,17 +19,20 @@
 # for package
 from iotdb.utils.IoTDBConstants import TSDataType
 from iotdb.tsfile.utils.date_utils import parse_int_to_date
+from iotdb.utils.rpc_utils import convert_to_timestamp, isoformat
 import numpy as np
 import pandas as pd
 
 
 class Field(object):
-    def __init__(self, data_type, value=None):
+    def __init__(self, data_type, value=None, timezone=None, precision=None):
         """
         :param data_type: TSDataType
         """
         self.__data_type = data_type
         self.value = value
+        self.__timezone = timezone
+        self.__precision = precision
 
     @staticmethod
     def copy(field):
@@ -157,6 +160,17 @@ class Field(object):
             return None
         return self.value
 
+    def get_timestamp_value(self):
+        if self.__data_type is None:
+            raise Exception("Null Field Exception!")
+        if (
+            self.__data_type != TSDataType.TIMESTAMP
+            or self.value is None
+            or self.value is pd.NA
+        ):
+            return None
+        return convert_to_timestamp(self.value, self.__precision, 
self.__timezone)
+
     def get_date_value(self):
         if self.__data_type is None:
             raise Exception("Null Field Exception!")
@@ -172,11 +186,18 @@ class Field(object):
         if self.__data_type is None or self.value is None or self.value is 
pd.NA:
             return "None"
         # TEXT, STRING
-        elif self.__data_type == 5 or self.__data_type == 11:
+        if self.__data_type == 5 or self.__data_type == 11:
             return self.value.decode("utf-8")
         # BLOB
         elif self.__data_type == 10:
             return str(hex(int.from_bytes(self.value, byteorder="big")))
+        # TIMESTAMP
+        elif self.__data_type == 8:
+            return isoformat(
+                convert_to_timestamp(self.value, self.__precision, 
self.__timezone),
+                self.__precision,
+            )
+        # Others
         else:
             return str(self.get_object_value(self.__data_type))
 
@@ -193,12 +214,14 @@ class Field(object):
             return bool(self.value)
         elif data_type == 1:
             return np.int32(self.value)
-        elif data_type == 2 or data_type == 8:
+        elif data_type == 2:
             return np.int64(self.value)
         elif data_type == 3:
             return np.float32(self.value)
         elif data_type == 4:
             return np.float64(self.value)
+        elif data_type == 8:
+            return convert_to_timestamp(self.value, self.__precision, 
self.__timezone)
         elif data_type == 9:
             return parse_int_to_date(self.value)
         elif data_type == 5 or data_type == 11:
diff --git a/iotdb-client/client-py/iotdb/utils/SessionDataSet.py 
b/iotdb-client/client-py/iotdb/utils/SessionDataSet.py
index 6209d13e5f3..b079ee28c1a 100644
--- a/iotdb-client/client-py/iotdb/utils/SessionDataSet.py
+++ b/iotdb-client/client-py/iotdb/utils/SessionDataSet.py
@@ -45,13 +45,14 @@ class SessionDataSet(object):
         time_out,
         more_data,
         fetch_size,
+        zone_id,
+        time_precision,
         column_index_2_tsblock_column_index_list,
     ):
         self.iotdb_rpc_data_set = IoTDBRpcDataSet(
             sql,
             column_name_list,
             column_type_list,
-            column_name_index,
             ignore_timestamp,
             more_data,
             query_id,
@@ -61,16 +62,26 @@ class SessionDataSet(object):
             query_result,
             fetch_size,
             time_out,
+            zone_id,
+            time_precision,
             column_index_2_tsblock_column_index_list,
         )
         if ignore_timestamp:
             self.__field_list = [
-                Field(data_type)
+                (
+                    Field(data_type, timezone=zone_id, 
precision=time_precision)
+                    if data_type == 8
+                    else Field(data_type)
+                )
                 for data_type in self.iotdb_rpc_data_set.get_column_types()
             ]
         else:
             self.__field_list = [
-                Field(data_type)
+                (
+                    Field(data_type, timezone=zone_id, 
precision=time_precision)
+                    if data_type == 8
+                    else Field(data_type)
+                )
                 for data_type in self.iotdb_rpc_data_set.get_column_types()[1:]
             ]
         self.row_index = 0
@@ -155,7 +166,7 @@ def get_typed_point(field: Field, none_value=None):
         TSDataType.INT32: lambda f: f.get_int_value(),
         TSDataType.DOUBLE: lambda f: f.get_double_value(),
         TSDataType.INT64: lambda f: f.get_long_value(),
-        TSDataType.TIMESTAMP: lambda f: f.get_long_value(),
+        TSDataType.TIMESTAMP: lambda f: f.get_timestamp_value(),
         TSDataType.STRING: lambda f: f.get_string_value(),
         TSDataType.DATE: lambda f: f.get_date_value(),
         TSDataType.BLOB: lambda f: f.get_binary_value(),
diff --git a/iotdb-client/client-py/iotdb/utils/iotdb_rpc_dataset.py 
b/iotdb-client/client-py/iotdb/utils/iotdb_rpc_dataset.py
index 8530fef5c20..dc771368669 100644
--- a/iotdb-client/client-py/iotdb/utils/iotdb_rpc_dataset.py
+++ b/iotdb-client/client-py/iotdb/utils/iotdb_rpc_dataset.py
@@ -28,7 +28,7 @@ from iotdb.tsfile.utils.date_utils import parse_int_to_date
 from iotdb.tsfile.utils.tsblock_serde import deserialize
 from iotdb.utils.exception import IoTDBConnectionException
 from iotdb.utils.IoTDBConstants import TSDataType
-from iotdb.utils.rpc_utils import verify_success
+from iotdb.utils.rpc_utils import verify_success, convert_to_timestamp
 
 logger = logging.getLogger("IoTDB")
 TIMESTAMP_STR = "Time"
@@ -41,7 +41,6 @@ class IoTDBRpcDataSet(object):
         sql,
         column_name_list,
         column_type_list,
-        column_name_index,
         ignore_timestamp,
         more_data,
         query_id,
@@ -51,6 +50,8 @@ class IoTDBRpcDataSet(object):
         query_result,
         fetch_size,
         time_out,
+        zone_id,
+        time_precision,
         column_index_2_tsblock_column_index_list,
     ):
         self.__statement_id = statement_id
@@ -117,6 +118,8 @@ class IoTDBRpcDataSet(object):
         self.__empty_resultSet = False
         self.has_cached_data_frame = False
         self.data_frame = None
+        self.__zone_id = zone_id
+        self.__time_precision = time_precision
 
     def close(self):
         if self.__is_closed:
@@ -155,7 +158,7 @@ class IoTDBRpcDataSet(object):
 
     def construct_one_data_frame(self):
         if self.has_cached_data_frame or self.__query_result is None:
-            return True
+            return
         result = {}
         has_pd_series = []
         for i in range(len(self.__column_index_2_tsblock_column_index_list)):
@@ -264,8 +267,8 @@ class IoTDBRpcDataSet(object):
                     continue
                 data_type = self.__data_type_for_tsblock_column[location]
                 column_array = column_arrays[location]
-                # BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TIMESTAMP, BLOB
-                if data_type in (0, 1, 2, 3, 4, 8, 10):
+                # BOOLEAN, INT32, INT64, FLOAT, DOUBLE, BLOB
+                if data_type in (0, 1, 2, 3, 4, 10):
                     data_array = column_array
                     if (
                         data_type != 10
@@ -278,6 +281,17 @@ class IoTDBRpcDataSet(object):
                 # TEXT, STRING
                 elif data_type in (5, 11):
                     data_array = np.array([x.decode("utf-8") for x in 
column_array])
+                # TIMESTAMP
+                elif data_type == 8:
+                    data_array = pd.Series(
+                        [
+                            convert_to_timestamp(
+                                x, self.__time_precision, self.__zone_id
+                            )
+                            for x in column_array
+                        ],
+                        dtype=object,
+                    )
                 # DATE
                 elif data_type == 9:
                     data_array = 
pd.Series(column_array).apply(parse_int_to_date)
@@ -289,25 +303,21 @@ class IoTDBRpcDataSet(object):
                     data_type == 0 and null_indicator is not None
                 ):
                     tmp_array = []
-                    # BOOLEAN, INT32, INT64, TIMESTAMP
-                    if (
-                        data_type == 0
-                        or data_type == 1
-                        or data_type == 2
-                        or data_type == 8
-                    ):
+                    # BOOLEAN, INT32, INT64
+                    if data_type == 0 or data_type == 1 or data_type == 2:
                         tmp_array = np.full(array_length, pd.NA, dtype=object)
                     # FLOAT, DOUBLE
                     elif data_type == 3 or data_type == 4:
                         tmp_array = np.full(
                             array_length, np.nan, dtype=data_type.np_dtype()
                         )
-                    # TEXT, STRING, BLOB, DATE
+                    # TEXT, STRING, BLOB, DATE, TIMESTAMP
                     elif (
                         data_type == 5
                         or data_type == 11
                         or data_type == 10
                         or data_type == 9
+                        or data_type == 8
                     ):
                         tmp_array = np.full(array_length, None, dtype=object)
 
@@ -320,7 +330,7 @@ class IoTDBRpcDataSet(object):
 
                     if data_type == 1:
                         tmp_array = pd.Series(tmp_array).astype("Int32")
-                    elif data_type == 2 or data_type == 8:
+                    elif data_type == 2:
                         tmp_array = pd.Series(tmp_array).astype("Int64")
                     elif data_type == 0:
                         tmp_array = pd.Series(tmp_array).astype("boolean")
diff --git a/iotdb-client/client-py/iotdb/utils/rpc_utils.py 
b/iotdb-client/client-py/iotdb/utils/rpc_utils.py
index 6ceb39c6558..7b292737f0c 100644
--- a/iotdb-client/client-py/iotdb/utils/rpc_utils.py
+++ b/iotdb-client/client-py/iotdb/utils/rpc_utils.py
@@ -15,9 +15,17 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+import logging
+
+import pandas as pd
+from pandas._libs import OutOfBoundsDatetime
+from tzlocal import get_localzone_name
+
 from iotdb.thrift.common.ttypes import TSStatus
 from iotdb.utils.exception import RedirectException, 
StatementExecutionException
 
+logger = logging.getLogger("IoTDB")
+
 SUCCESS_STATUS = 200
 MULTIPLE_ERROR = 302
 REDIRECTION_RECOMMEND = 400
@@ -67,3 +75,36 @@ def 
verify_success_with_redirection_for_multi_devices(status: TSStatus, devices:
             if status.subStatus[i].redirectNode is not None:
                 device_to_endpoint[devices[i]] = 
status.subStatus[i].redirectNode
         raise RedirectException(device_to_endpoint)
+
+
+def convert_to_timestamp(time: int, precision: str, timezone: str):
+    try:
+        return pd.Timestamp(time, unit=precision, tz=timezone)
+    except OutOfBoundsDatetime:
+        return pd.Timestamp(time, unit=precision).tz_localize(timezone)
+    except ValueError:
+        logger.warning(
+            f"Timezone string '{timezone}' cannot be recognized by pandas. "
+            f"Falling back to local timezone: '{get_localzone_name()}'."
+        )
+        return pd.Timestamp(time, unit=precision, tz=get_localzone_name())
+
+
+unit_map = {
+    "ms": "milliseconds",
+    "us": "microseconds",
+    "ns": "nanoseconds",
+}
+
+
+def isoformat(ts: pd.Timestamp, unit: str):
+    if unit not in unit_map:
+        raise ValueError(f"Unsupported unit: {unit}")
+    try:
+        return ts.isoformat(timespec=unit_map[unit])
+    except ValueError:
+        logger.warning(
+            f"Timezone string '{unit_map[unit]}' cannot be recognized by old 
version pandas. "
+            f"Falling back to use auto timespec'."
+        )
+        return ts.isoformat()
diff --git a/iotdb-client/client-py/requirements.txt 
b/iotdb-client/client-py/requirements.txt
index 0741cf6db67..980a7442a54 100644
--- a/iotdb-client/client-py/requirements.txt
+++ b/iotdb-client/client-py/requirements.txt
@@ -23,3 +23,4 @@ thrift>=0.14.1
 # SQLAlchemy Dialect
 sqlalchemy>=1.4
 sqlalchemy-utils>=0.37.8
+tzlocal>=4.0
diff --git a/iotdb-client/client-py/resources/pyproject.toml 
b/iotdb-client/client-py/resources/pyproject.toml
index d8102161b43..2b32eefd59b 100644
--- a/iotdb-client/client-py/resources/pyproject.toml
+++ b/iotdb-client/client-py/resources/pyproject.toml
@@ -42,7 +42,8 @@ dependencies = [
     "pandas>=1.0.0",
     "numpy>=1.0.0",
     "sqlalchemy>=1.4",
-    "sqlalchemy-utils>=0.37.8"
+    "sqlalchemy-utils>=0.37.8",
+    "tzlocal>=4.0"
 ]
 
 [project.urls]
diff --git a/iotdb-client/client-py/session_aligned_timeseries_example.py 
b/iotdb-client/client-py/session_aligned_timeseries_example.py
index 99b9f16a62e..450d69f2818 100644
--- a/iotdb-client/client-py/session_aligned_timeseries_example.py
+++ b/iotdb-client/client-py/session_aligned_timeseries_example.py
@@ -27,7 +27,9 @@ ip = "127.0.0.1"
 port_ = "6667"
 username_ = "root"
 password_ = "root"
-session = Session(ip, port_, username_, password_, fetch_size=1024, 
zone_id="UTC+8")
+session = Session(
+    ip, port_, username_, password_, fetch_size=1024, zone_id="Asia/Shanghai"
+)
 session.open(False)
 
 # set and delete databases
diff --git a/iotdb-client/client-py/session_example.py 
b/iotdb-client/client-py/session_example.py
index ca610de9a0c..d0a6a3aba8e 100644
--- a/iotdb-client/client-py/session_example.py
+++ b/iotdb-client/client-py/session_example.py
@@ -30,13 +30,13 @@ ip = "127.0.0.1"
 port_ = "6667"
 username_ = "root"
 password_ = "root"
-# session = Session(ip, port_, username_, password_, fetch_size=1024, 
zone_id="UTC+8", enable_redirection=True)
+# session = Session(ip, port_, username_, password_, fetch_size=1024, 
zone_id="Asia/Shanghai", enable_redirection=True)
 session = Session.init_from_node_urls(
     node_urls=["127.0.0.1:6667", "127.0.0.1:6668", "127.0.0.1:6669"],
     user="root",
     password="root",
     fetch_size=1024,
-    zone_id="UTC+8",
+    zone_id="Asia/Shanghai",
     enable_redirection=True,
 )
 session.open(False)
diff --git a/iotdb-client/client-py/session_pool_example.py 
b/iotdb-client/client-py/session_pool_example.py
index 9230634ba6f..64a754087fa 100644
--- a/iotdb-client/client-py/session_pool_example.py
+++ b/iotdb-client/client-py/session_pool_example.py
@@ -120,7 +120,7 @@ pool_config = PoolConfig(
     user_name=username,
     password=password,
     fetch_size=1024,
-    time_zone="UTC+8",
+    time_zone="Asia/Shanghai",
     max_retry=3,
 )
 max_pool_size = 5
diff --git a/iotdb-client/client-py/session_ssl_example.py 
b/iotdb-client/client-py/session_ssl_example.py
index ea367e00f3a..2d5a557afc4 100644
--- a/iotdb-client/client-py/session_ssl_example.py
+++ b/iotdb-client/client-py/session_ssl_example.py
@@ -49,7 +49,7 @@ def get_data2():
         user_name=username_,
         password=password_,
         fetch_size=1024,
-        time_zone="UTC+8",
+        time_zone="Asia/Shanghai",
         max_retry=3,
         use_ssl=use_ssl,
         ca_certs=ca_certs,
@@ -71,7 +71,7 @@ def get_table_data():
         username=username_,
         password=password_,
         fetch_size=1024,
-        time_zone="UTC+8",
+        time_zone="Asia/Shanghai",
         use_ssl=use_ssl,
         ca_certs=ca_certs,
     )
diff --git a/iotdb-client/client-py/table_model_session_example.py 
b/iotdb-client/client-py/table_model_session_example.py
index 86aac09da2d..c9aa62b97a0 100644
--- a/iotdb-client/client-py/table_model_session_example.py
+++ b/iotdb-client/client-py/table_model_session_example.py
@@ -28,7 +28,7 @@ config = TableSessionConfig(
     node_urls=["localhost:6667"],
     username="root",
     password="root",
-    time_zone="UTC+8",
+    time_zone="Asia/Shanghai",
 )
 session = TableSession(config)
 
@@ -69,7 +69,7 @@ config = TableSessionConfig(
     username="root",
     password="root",
     database="test1",
-    time_zone="UTC+8",
+    time_zone="Asia/Shanghai",
 )
 session = TableSession(config)
 
diff --git 
a/iotdb-client/client-py/tests/integration/tablet_performance_comparison.py 
b/iotdb-client/client-py/tests/integration/tablet_performance_comparison.py
index 3626e818a85..c22124ec009 100644
--- a/iotdb-client/client-py/tests/integration/tablet_performance_comparison.py
+++ b/iotdb-client/client-py/tests/integration/tablet_performance_comparison.py
@@ -113,7 +113,9 @@ def create_open_session():
     port_ = "6667"
     username_ = "root"
     password_ = "root"
-    session = Session(ip, port_, username_, password_, fetch_size=1024, 
zone_id="UTC+8")
+    session = Session(
+        ip, port_, username_, password_, fetch_size=1024, 
zone_id="Asia/Shanghai"
+    )
     session.open(False)
     return session
 
diff --git a/iotdb-client/client-py/tests/integration/test_new_data_types.py 
b/iotdb-client/client-py/tests/integration/test_new_data_types.py
index 997831f9692..e59138fa035 100644
--- a/iotdb-client/client-py/tests/integration/test_new_data_types.py
+++ b/iotdb-client/client-py/tests/integration/test_new_data_types.py
@@ -18,6 +18,8 @@
 from datetime import date
 
 import numpy as np
+import pandas as pd
+from tzlocal import get_localzone_name
 
 from iotdb.Session import Session
 from iotdb.SessionPool import PoolConfig, create_session_pool
@@ -47,8 +49,7 @@ def session_test(use_session_pool=False):
                 "root",
                 None,
                 1024,
-                "Asia/Shanghai",
-                3,
+                max_retry=3,
             )
             session_pool = create_session_pool(pool_config, 1, 3000)
             session = session_pool.get_session()
@@ -134,10 +135,9 @@ def session_test(use_session_pool=False):
                 assert row_record.get_fields()[0].get_date_value() == date(
                     2024, 1, timestamp
                 )
-                assert (
-                    
row_record.get_fields()[1].get_object_value(TSDataType.TIMESTAMP)
-                    == timestamp
-                )
+                assert row_record.get_fields()[1].get_object_value(
+                    TSDataType.TIMESTAMP
+                ) == pd.Timestamp(timestamp, unit="ms", 
tz=get_localzone_name())
                 assert row_record.get_fields()[2].get_binary_value() == 
b"\x12\x34"
                 assert row_record.get_fields()[3].get_string_value() == 
"test0" + str(
                     timestamp
diff --git a/iotdb-client/client-py/tests/integration/test_tablemodel_query.py 
b/iotdb-client/client-py/tests/integration/test_tablemodel_query.py
index 182f4f09f77..d1ec27fbaf4 100644
--- a/iotdb-client/client-py/tests/integration/test_tablemodel_query.py
+++ b/iotdb-client/client-py/tests/integration/test_tablemodel_query.py
@@ -18,11 +18,14 @@
 import math
 
 import pandas as pd
+from tzlocal import get_localzone_name
 
 from iotdb.table_session import TableSession, TableSessionConfig
 from iotdb.utils.IoTDBConstants import TSDataType
 from iotdb.utils.Tablet import Tablet, ColumnType
 from datetime import date
+
+from iotdb.utils.rpc_utils import convert_to_timestamp
 from .iotdb_container import IoTDBContainer
 
 
@@ -352,6 +355,15 @@ def test_query_data():
                             values[row][i],
                             rel_tol=1e-6,
                         )
+                    elif data_types[i] == TSDataType.TIMESTAMP:
+                        actual = 
row_record.get_fields()[i].get_timestamp_value()
+                        expected = convert_to_timestamp(
+                            values[row][i], "ms", get_localzone_name()
+                        )
+                        if pd.isnull(actual):
+                            assert pd.isnull(expected)
+                        else:
+                            assert actual == expected
                     else:
                         assert (
                             
row_record.get_fields()[i].get_object_value(data_types[i])
@@ -372,13 +384,21 @@ def test_query_data():
             for i in range(rows):
                 for j in range(columns):
                     if pd.isna(df.iloc[i, j]):
-                        assert values[i][j] is None
+                        continue
                     elif isinstance(values[i][j], float):
                         assert math.isclose(
                             df.iloc[i, j],
                             values[i][j],
                             rel_tol=1e-6,
                         )
+                    elif isinstance(df.iloc[i, j], pd.Timestamp):
+                        actual = df.iloc[i, j]
+                        expected = pd.Series(
+                            convert_to_timestamp(
+                                values[i][j], "ms", get_localzone_name()
+                            )
+                        )[0]
+                        assert actual == expected
                     else:
                         assert df.iloc[i, j] == values[i][j]
 

Reply via email to