diff --git a/django/db/models/functions/datetime.py b/django/db/models/functions/datetime.py index 7a582aa4043..665e0b931d8 100644 --- a/django/db/models/functions/datetime.py +++ b/django/db/models/functions/datetime.py @@ -73,6 +73,14 @@ class Extract(TimezoneMixin, Transform): raise ValueError( "Cannot extract time component '%s' from DateField '%s'. " % (copy.lookup_name, field.name) ) + if ( + isinstance(field, DurationField) and + copy.lookup_name in ('year', 'iso_year', 'month', 'week', 'week_day', 'quarter') + ): + raise ValueError( + "Cannot extract component '%s' from DurationField '%s'." + % (copy.lookup_name, field.name) + ) return copy diff --git a/tests/db_functions/datetime/test_extract_trunc.py b/tests/db_functions/datetime/test_extract_trunc.py index 2b7ee5befd7..f2f75ee620b 100644 --- a/tests/db_functions/datetime/test_extract_trunc.py +++ b/tests/db_functions/datetime/test_extract_trunc.py @@ -273,6 +273,13 @@ class DateFunctionTests(TestCase): with self.assertRaisesMessage(ValueError, msg): list(DTModel.objects.annotate(extracted=Extract('duration', 'second'))) + def test_extract_duration_unsupported_lookups(self): + msg = "Cannot extract component '%s' from DurationField 'duration'." + for lookup in ('year', 'iso_year', 'month', 'week', 'week_day', 'quarter'): + with self.subTest(lookup): + with self.assertRaisesMessage(ValueError, msg % lookup): + DTModel.objects.annotate(extracted=Extract('duration', lookup)) + def test_extract_year_func(self): start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123)