Skip to content

Commit 8a3f442

Browse files
authored
timedelta: support microseconds and negative values (#795)
ref: PyMySQL/PyMySQL#1262
1 parent aa1df8b commit 8a3f442

2 files changed

Lines changed: 22 additions & 5 deletions

File tree

src/MySQLdb/times.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,20 @@ def TimestampFromTicks(ticks):
3838

3939

4040
def format_TIMEDELTA(v):
41-
seconds = int(v.seconds) % 60
42-
minutes = int(v.seconds // 60) % 60
43-
hours = int(v.seconds // 3600) % 24
44-
return "%d %d:%d:%d" % (v.days, hours, minutes, seconds)
41+
# Negative timedeltas store the sign in days and keep seconds positive.
42+
# Format the absolute value so the sign is not applied twice by MySQL.
43+
sign = ""
44+
if v.days < 0:
45+
sign = "-"
46+
v = abs(v)
47+
48+
micros = v.microseconds
49+
minutes, seconds = divmod(v.seconds, 60)
50+
hours, minutes = divmod(minutes, 60)
51+
52+
if micros:
53+
return f"{sign}{v.days} {hours}:{minutes}:{seconds}.{micros:06d}"
54+
return f"{sign}{v.days} {hours}:{minutes}:{seconds}"
4555

4656

4757
def format_TIMESTAMP(d):

tests/test_MySQLdb_times.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ def test_datetime_to_literal(self):
120120
def test_datetimedelta_to_literal(self):
121121
d = datetime(2015, 12, 13, 1, 2, 3) - datetime(2015, 12, 13, 1, 2, 2)
122122
assert times.DateTimeDelta2literal(d, "") == b"'0 0:0:1'"
123+
assert times.DateTimeDelta2literal(-timedelta(minutes=30), "") == b"'-0 0:30:0'"
123124

124125

125126
class TestFormat(unittest.TestCase):
@@ -131,7 +132,13 @@ def test_format_timedelta(self):
131132
assert times.format_TIMEDELTA(d) == "0 2:2:2"
132133

133134
d = datetime(2015, 1, 1, 10, 11, 12) - datetime(2015, 1, 1, 11, 12, 13)
134-
assert times.format_TIMEDELTA(d) == "-1 22:58:59"
135+
assert times.format_TIMEDELTA(d) == "-0 1:1:1"
136+
137+
assert times.format_TIMEDELTA(-timedelta(minutes=30)) == "-0 0:30:0"
138+
assert times.format_TIMEDELTA(-timedelta(days=1, hours=2)) == "-1 2:0:0"
139+
d = timedelta(seconds=83579, microseconds=51000)
140+
assert times.format_TIMEDELTA(d) == "0 23:12:59.051000"
141+
assert times.format_TIMEDELTA(-d) == "-0 23:12:59.051000"
135142

136143
def test_format_timestamp(self):
137144
assert times.format_TIMESTAMP(datetime(2015, 2, 3)) == "2015-02-03 00:00:00"

0 commit comments

Comments
 (0)