diff --git a/CHANGELOG.md b/CHANGELOG.md index 1569e7d..c103702 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 1.5.0 + +- feat: #129: Add `toYearWeek` datetime functionality + ### 1.4.0 - feat: #119 Allow query results returned in columns and deserialized to `numpy` objects diff --git a/clickhouse_backend/models/functions/datetime.py b/clickhouse_backend/models/functions/datetime.py index 9dd204a..637eca9 100644 --- a/clickhouse_backend/models/functions/datetime.py +++ b/clickhouse_backend/models/functions/datetime.py @@ -14,6 +14,7 @@ "toYYYYMM", "toYYYYMMDD", "toYYYYMMDDhhmmss", + "toYearWeek", ] @@ -77,3 +78,25 @@ class toStartOfFifteenMinutes(toStartOfMinute): class toStartOfHour(toStartOfMinute): pass + + +class toYearWeek(Func): + output_field = fields.UInt32Field() + + def __init__(self, *expressions): + arity = len(expressions) + if arity < 1 or arity > 3: + raise TypeError( + "'%s' takes between 1 and 3 arguments (%s given)" + % ( + self.__class__.__name__, + len(expressions), + ) + ) + + expressions = ( + expressions[0], + *(models.Value(expr) for expr in expressions[1:]), + ) + + super().__init__(*expressions) diff --git a/tests/clickhouse_functions/test_datetime.py b/tests/clickhouse_functions/test_datetime.py index 36e6cda..047028b 100644 --- a/tests/clickhouse_functions/test_datetime.py +++ b/tests/clickhouse_functions/test_datetime.py @@ -27,6 +27,13 @@ def setUpTestData(cls): datetime(2023, 11, 30, hour=16, minute=59, second=59), is_dst=False ), ) + cls.sarah = Author.objects.create( + name="Sarah Connor", + alias="sconnor", + birthday=pytz.utc.localize( + datetime(2023, 12, 31, hour=23, minute=30, second=00), is_dst=False + ), + ) def test_yyyymm(self): john = Author.objects.annotate(v=models.toYYYYMM("birthday")).get( @@ -177,3 +184,19 @@ def test_tostartofhour(self): elena.v, datetime(2023, 11, 30, hour=10, minute=00, second=00), ) + + def test_toyearweek(self): + sarah = Author.objects.annotate(v=models.toYearWeek("birthday")).get( + id=self.sarah.id + ) + self.assertEqual(sarah.v, 202353) + + sarah = Author.objects.annotate(v=models.toYearWeek("birthday", 1)).get( + id=self.sarah.id + ) + self.assertEqual(sarah.v, 202352) + + sarah = Author.objects.annotate( + v=models.toYearWeek("birthday", 1, "Pacific/Kiritimati") + ).get(id=self.sarah.id) + self.assertEqual(sarah.v, 202401)