Skip to content

Commit a987d70

Browse files
authored
Added TimeField (#1090)
* feat: Added `TimeField`. (#1054) * fix: test cases * fix: MySQL `TimeField` * fix: test_concurrent_get_or_create * style: fix black
1 parent 9709355 commit a987d70

File tree

11 files changed

+167
-55
lines changed

11 files changed

+167
-55
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,18 @@ Added
1616
- Added a new unified and robust connection management interface to access DB connections which includes support for
1717
lazy connection creation and much more. For more details,
1818
check out this `PR <https://github.com/tortoise/tortoise-orm/pull/1001>`_
19+
- Added `TimeField`. (#1054)
1920
Fixed
2021
^^^^^
2122
- Fix `bulk_create` doesn't work correctly with more than 1 update_fields. (#1046)
2223
- Fix `bulk_update` errors when setting null for a smallint column on postgres. (#1086)
2324
Deprecated
24-
^^^^^
25+
^^^^^^^^^^
2526
- Existing connection management interface and related public APIs which are deprecated:
2627
- `Tortoise.get_connection`
2728
- `Tortoise.close_connections`
2829
Changed
29-
^^^^^
30+
^^^^^^^
3031
- Refactored `tortoise.transactions.get_connection` method to `tortoise.transactions._get_connection`.
3132
Note that this method has now been marked **private to this module and is not part of the public API**
3233

docs/timezone.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ The design of timezone is inspired by `Django` but also has differences. There a
1111
use_tz
1212
------
1313
When set `use_tz = True`, `tortoise` will always store `UTC` time in database no matter what `timezone` set. And `MySQL` use field type `DATETIME(6)`, `PostgreSQL` use `TIMESTAMPTZ`, `SQLite` use `TIMESTAMP` when generate schema.
14+
For `TimeField`, `MySQL` use `TIME(6)`, `PostgreSQL` use `TIMETZ` and `SQLite` use `TIME`.
1415

1516
timezone
1617
--------
17-
The `timezone` determine what `timezone` is when select datetime field from database, no matter what `timezone` your database is. And you should use `tortoise.timezone.now()` get aware time instead of native time `datetime.datetime.now()`.
18+
The `timezone` determine what `timezone` is when select `DateTimeField` and `TimeField` from database, no matter what `timezone` your database is. And you should use `tortoise.timezone.now()` get aware time instead of native time `datetime.datetime.now()`.
1819

1920
Reference
2021
=========
2122

2223
.. automodule:: tortoise.timezone
2324
:members:
2425
:undoc-members:
25-

poetry.lock

Lines changed: 34 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ classifiers = [
3535

3636
[tool.poetry.dependencies]
3737
python = "^3.7"
38-
pypika-tortoise = "^0.1.3"
38+
pypika-tortoise = { git = "https://github.com/tortoise/pypika-tortoise.git", branch = "main" }
3939
iso8601 = "^1.0.2"
4040
aiosqlite = ">=0.16.0, <0.18.0"
4141
pytz = "*"
@@ -44,8 +44,8 @@ uvloop = { version = "*", markers = "sys_platform != 'win32' and implementation_
4444
orjson = { version = "*", optional = true }
4545
asyncpg = { version = "*", optional = true }
4646
aiomysql = { version = "*", optional = true }
47-
asyncmy = { version = "*", optional = true }
48-
psycopg = {extras = ["pool", "binary"], version = "*", optional = true }
47+
asyncmy = { git = "https://github.com/long2ice/asyncmy.git", branch = "dev" }
48+
psycopg = { extras = ["pool", "binary"], version = "*", optional = true }
4949

5050
[tool.poetry.dev-dependencies]
5151
# Linter tools

tests/fields/test_time.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from datetime import date, datetime, timedelta
2+
from datetime import date, datetime, time, timedelta
33
from time import sleep
44

55
import pytz
@@ -148,6 +148,35 @@ async def test_timezone(self):
148148
os.environ["USE_TZ"] = old_use_tz
149149

150150

151+
class TestTimeFields(test.TestCase):
152+
async def test_create(self):
153+
now = timezone.now().timetz()
154+
obj = await testmodels.TimeFields.create(time=now)
155+
self.assertEqual(obj.time, now)
156+
157+
async def test_cast(self):
158+
obj = await testmodels.TimeFields.create(time="21:00+00:00")
159+
self.assertEqual(obj.time, time.fromisoformat("21:00+00:00"))
160+
161+
async def test_values(self):
162+
now = timezone.now().timetz()
163+
obj0 = await testmodels.TimeFields.create(time=now)
164+
values = await testmodels.TimeFields.get(id=obj0.id).values("time")
165+
self.assertEqual(values["time"], now)
166+
167+
async def test_values_list(self):
168+
now = timezone.now().timetz()
169+
obj0 = await testmodels.TimeFields.create(time=now)
170+
values = await testmodels.TimeFields.get(id=obj0.id).values_list("time", flat=True)
171+
self.assertEqual(values, now)
172+
173+
async def test_get(self):
174+
now = timezone.now().timetz()
175+
await testmodels.TimeFields.create(time=now)
176+
obj = await testmodels.TimeFields.get(time=now)
177+
self.assertEqual(obj.time, now)
178+
179+
151180
class TestDateFields(test.TestCase):
152181
async def test_empty(self):
153182
with self.assertRaises(IntegrityError):

tests/testmodels.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,12 @@ class DateFields(Model):
254254
date_null = fields.DateField(null=True)
255255

256256

257+
class TimeFields(Model):
258+
id = fields.IntField(pk=True)
259+
time = fields.TimeField()
260+
time_null = fields.TimeField(null=True)
261+
262+
257263
class FloatFields(Model):
258264
id = fields.IntField(pk=True)
259265
floatnum = fields.FloatField()

tortoise/backends/sqlite/executor.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
DecimalField,
1515
IntField,
1616
SmallIntField,
17+
TimeField,
1718
)
1819

1920

@@ -54,11 +55,30 @@ def to_db_datetime(
5455
return None
5556

5657

58+
def to_db_time(
59+
self: TimeField, value: Optional[datetime.time], instance: Union[Type[Model], Model]
60+
) -> Optional[str]:
61+
if hasattr(instance, "_saved_in_db") and (
62+
self.auto_now
63+
or (self.auto_now_add and getattr(instance, self.model_field_name, None) is None)
64+
):
65+
if timezone.get_use_tz():
66+
value = datetime.datetime.now(tz=pytz.utc).time()
67+
else:
68+
value = datetime.datetime.now(tz=timezone.get_default_timezone()).time()
69+
setattr(instance, self.model_field_name, value)
70+
return value.isoformat()
71+
if isinstance(value, datetime.time):
72+
return value.isoformat()
73+
return None
74+
75+
5776
class SqliteExecutor(BaseExecutor):
5877
TO_DB_OVERRIDE = {
5978
fields.BooleanField: to_db_bool,
6079
fields.DecimalField: to_db_decimal,
6180
fields.DatetimeField: to_db_datetime,
81+
fields.TimeField: to_db_time,
6282
}
6383
EXPLAIN_PREFIX = "EXPLAIN QUERY PLAN"
6484
DB_NATIVE = {bytes, str, int, float}

tortoise/fields/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
SmallIntField,
1616
TextField,
1717
TimeDeltaField,
18+
TimeField,
1819
UUIDField,
1920
)
2021
from tortoise.fields.relational import (
@@ -44,6 +45,7 @@
4445
"CharField",
4546
"DateField",
4647
"DatetimeField",
48+
"TimeField",
4749
"DecimalField",
4850
"FloatField",
4951
"IntEnumField",

0 commit comments

Comments
 (0)