Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
### 1.5.0

- feat: #125 Add database functions `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes` and `toStartofHour`


### 1.4.0

- feat: #119 Allow query results returned in columns and deserialized to `numpy` objects
Expand Down
38 changes: 38 additions & 0 deletions clickhouse_backend/models/functions/datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
from .base import Func

__all__ = [
"toStartOfMinute",
"toStartOfFiveMinutes",
"toStartOfTenMinutes",
"toStartOfFifteenMinutes",
"toStartOfHour",
"toYYYYMM",
"toYYYYMMDD",
"toYYYYMMDDhhmmss",
Expand Down Expand Up @@ -39,3 +44,36 @@ class toYYYYMMDD(toYYYYMM):

class toYYYYMMDDhhmmss(toYYYYMM):
output_field = fields.UInt64Field()


class toStartOfMinute(Func):
output_field = models.fields.DateTimeField()

def __init__(self, *expressions):
arity = len(expressions)
if arity < 1 or arity > 1:
raise TypeError(
"'%s' takes 1 argument (%s given)"
% (
self.__class__.__name__,
len(expressions),
)
)

super().__init__(*expressions)


class toStartOfFiveMinutes(toStartOfMinute):
pass


class toStartOfTenMinutes(toStartOfMinute):
pass


class toStartOfFifteenMinutes(toStartOfMinute):
pass


class toStartOfHour(toStartOfMinute):
pass
130 changes: 126 additions & 4 deletions tests/clickhouse_functions/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ def setUpTestData(cls):
alias="smithj",
# https://stackoverflow.com/a/18862958
birthday=pytz.timezone(get_timezone()).localize(
datetime(2023, 11, 30, 16), is_dst=False
datetime(2023, 11, 30, hour=16, minute=12, second=15), is_dst=False
),
)
cls.elena = Author.objects.create(
name="Élena Jordan",
alias="elena",
birthday=pytz.utc.localize(datetime(2023, 11, 30, 16), is_dst=False),
birthday=pytz.utc.localize(
datetime(2023, 11, 30, hour=16, minute=59, second=59), is_dst=False
),
)

def test_yyyymm(self):
Expand All @@ -50,8 +52,128 @@ def test_yyyymmddhhmmss(self):
john = Author.objects.annotate(v=models.toYYYYMMDDhhmmss("birthday")).get(
id=self.john.id
)
self.assertEqual(john.v, 20231130160000)
self.assertEqual(john.v, 20231130161215)
elena = Author.objects.annotate(
v=models.toYYYYMMDDhhmmss("birthday", "Asia/Shanghai")
).get(id=self.elena.id)
self.assertEqual(elena.v, 20231201000000)
self.assertEqual(elena.v, 20231201005959)

def test_tostartofminute(self):
john = Author.objects.annotate(v=models.toStartOfMinute("birthday")).get(
id=self.john.id
)
self.assertEqual(
john.v,
datetime(
2023,
11,
30,
hour=16,
minute=12,
second=00,
),
)

elena = Author.objects.annotate(v=models.toStartOfMinute("birthday")).get(
id=self.elena.id
)
self.assertEqual(
elena.v,
datetime(2023, 11, 30, hour=10, minute=59, second=00),
)

def test_tostartoffiveminutes(self):
john = Author.objects.annotate(v=models.toStartOfFiveMinutes("birthday")).get(
id=self.john.id
)
self.assertEqual(
john.v,
datetime(
2023,
11,
30,
hour=16,
minute=10,
second=00,
),
)

elena = Author.objects.annotate(v=models.toStartOfFiveMinutes("birthday")).get(
id=self.elena.id
)
self.assertEqual(
elena.v,
datetime(2023, 11, 30, hour=10, minute=55, second=00),
)

def test_tostartoftenminutes(self):
john = Author.objects.annotate(v=models.toStartOfTenMinutes("birthday")).get(
id=self.john.id
)
self.assertEqual(
john.v,
datetime(
2023,
11,
30,
hour=16,
minute=10,
second=00,
),
)

elena = Author.objects.annotate(v=models.toStartOfTenMinutes("birthday")).get(
id=self.elena.id
)
self.assertEqual(
elena.v,
datetime(2023, 11, 30, hour=10, minute=50, second=00),
)

def test_tostartoffifteenminutes(self):
john = Author.objects.annotate(
v=models.toStartOfFifteenMinutes("birthday")
).get(id=self.john.id)
self.assertEqual(
john.v,
datetime(
2023,
11,
30,
hour=16,
minute=00,
second=00,
),
)

elena = Author.objects.annotate(
v=models.toStartOfFifteenMinutes("birthday")
).get(id=self.elena.id)
self.assertEqual(
elena.v,
datetime(2023, 11, 30, hour=10, minute=45, second=00),
)

def test_tostartofhour(self):
john = Author.objects.annotate(v=models.toStartOfHour("birthday")).get(
id=self.john.id
)
self.assertEqual(
john.v,
datetime(
2023,
11,
30,
hour=16,
minute=00,
second=00,
),
)

elena = Author.objects.annotate(v=models.toStartOfHour("birthday")).get(
id=self.elena.id
)
self.assertEqual(
elena.v,
datetime(2023, 11, 30, hour=10, minute=00, second=00),
)
Loading