Skip to content

Commit c50c607

Browse files
committed
encode mysql time as python datetime.timedelta
1 parent 2864417 commit c50c607

File tree

2 files changed

+52
-16
lines changed

2 files changed

+52
-16
lines changed

pymysqlreplication/row_event.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ def __add_fsp_to_time(self, time, column):
177177
For more details about new date format:
178178
http://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html
179179
"""
180+
microsecond = self.__read_fsp(column)
181+
if microsecond > 0:
182+
time = time.replace(microsecond=microsecond)
183+
return time
184+
185+
def __read_fsp(self, column):
180186
read = 0
181187
if column.fsp == 1 or column.fsp == 2:
182188
read = 1
@@ -187,10 +193,11 @@ def __add_fsp_to_time(self, time, column):
187193
if read > 0:
188194
microsecond = self.packet.read_int_be_by_size(read)
189195
if column.fsp % 2:
190-
time = time.replace(microsecond=int(microsecond / 10))
196+
return int(microsecond / 10)
191197
else:
192-
time = time.replace(microsecond=microsecond)
193-
return time
198+
return microsecond
199+
200+
return 0
194201

195202
def __read_string(self, size, column):
196203
string = self.packet.read_length_coded_pascal_string(size)
@@ -223,10 +230,10 @@ def __read_bit(self, column):
223230

224231
def __read_time(self):
225232
time = self.packet.read_uint24()
226-
date = datetime.time(
227-
hour=int(time / 10000),
228-
minute=int((time % 10000) / 100),
229-
second=int(time % 100))
233+
date = datetime.timedelta(
234+
hours=int(time / 10000),
235+
minutes=int((time % 10000) / 100),
236+
seconds=int(time % 100))
230237
return date
231238

232239
def __read_time2(self, column):
@@ -241,11 +248,20 @@ def __read_time2(self, column):
241248
24 bits = 3 bytes
242249
"""
243250
data = self.packet.read_int_be_by_size(3)
244-
t = datetime.time(
245-
hour=self.__read_binary_slice(data, 2, 10, 24),
246-
minute=self.__read_binary_slice(data, 12, 6, 24),
247-
second=self.__read_binary_slice(data, 18, 6, 24))
248-
return self.__add_fsp_to_time(t, column)
251+
252+
sign = 1 if self.__read_binary_slice(data, 0, 1, 24) else -1
253+
if sign == -1:
254+
# negative integers are stored as 2's compliment
255+
# hence take 2's compliment again to get the right value.
256+
data = ~data + 1
257+
258+
t = datetime.timedelta(
259+
hours=sign*self.__read_binary_slice(data, 2, 10, 24),
260+
minutes=self.__read_binary_slice(data, 12, 6, 24),
261+
seconds=self.__read_binary_slice(data, 18, 6, 24),
262+
microseconds=self.__read_fsp(column)
263+
)
264+
return t
249265

250266
def __read_date(self):
251267
time = self.packet.read_uint24()

pymysqlreplication/tests/test_data_type.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,36 @@ def test_zero_day(self):
266266
self.assertEqual(event.rows[0]["values"]["test2"], None)
267267

268268
def test_time(self):
269-
create_query = "CREATE TABLE test (test TIME);"
270-
insert_query = "INSERT INTO test VALUES('12:33:18')"
269+
create_query = "CREATE TABLE test (test1 TIME, test2 TIME);"
270+
insert_query = "INSERT INTO test VALUES('838:59:59', '-838:59:59')"
271271
event = self.create_and_insert_value(create_query, insert_query)
272-
self.assertEqual(event.rows[0]["values"]["test"], datetime.time(12, 33, 18))
272+
self.assertEqual(event.rows[0]["values"]["test1"], datetime.timedelta(
273+
microseconds=(((838*60) + 59)*60 + 59)*1000000
274+
))
275+
self.assertEqual(event.rows[0]["values"]["test2"], datetime.timedelta(
276+
microseconds=(((-838*60) + 59)*60 + 59)*1000000
277+
))
278+
279+
def test_time2(self):
280+
if not self.isMySQL56AndMore():
281+
self.skipTest("Not supported in this version of MySQL")
282+
create_query = "CREATE TABLE test (test1 TIME(6), test2 TIME(6));"
283+
insert_query = """
284+
INSERT INTO test VALUES('838:59:59.000000', '-838:59:59.000000');
285+
"""
286+
event = self.create_and_insert_value(create_query, insert_query)
287+
self.assertEqual(event.rows[0]["values"]["test1"], datetime.timedelta(
288+
microseconds=(((838*60) + 59)*60 + 59)*1000000 + 0
289+
))
290+
self.assertEqual(event.rows[0]["values"]["test2"], datetime.timedelta(
291+
microseconds=(((-838*60) + 59)*60 + 59)*1000000 + 0
292+
))
273293

274294
def test_zero_time(self):
275295
create_query = "CREATE TABLE test (id INTEGER, test TIME NOT NULL DEFAULT 0);"
276296
insert_query = "INSERT INTO test (id) VALUES(1)"
277297
event = self.create_and_insert_value(create_query, insert_query)
278-
self.assertEqual(event.rows[0]["values"]["test"], datetime.time(0,0))
298+
self.assertEqual(event.rows[0]["values"]["test"], datetime.timedelta(seconds=0))
279299

280300
def test_datetime(self):
281301
create_query = "CREATE TABLE test (test DATETIME);"

0 commit comments

Comments
 (0)