summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorSigurd Ljødal <sigurd@ljodal.no>2017-09-28 22:28:48 +0200
committerTim Graham <timograham@gmail.com>2018-08-18 13:09:15 -0400
commit3e09b37f80ab34cf57e245e1fcdabb3d4ff92a38 (patch)
tree7b56c5caeb4d6ebe6b5075c711c36a0572419c6f /django
parentc832885a3e8659d4a704bf103d523b610c24e4ec (diff)
Fixed #28649 -- Added ExtractIsoYear database function and iso_year lookup.
Diffstat (limited to 'django')
-rw-r--r--django/db/backends/mysql/operations.py4
-rw-r--r--django/db/backends/oracle/operations.py2
-rw-r--r--django/db/backends/postgresql/operations.py2
-rw-r--r--django/db/backends/sqlite3/base.py4
-rw-r--r--django/db/models/functions/__init__.py11
-rw-r--r--django/db/models/functions/datetime.py12
6 files changed, 30 insertions, 5 deletions
diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py
index babf522e45..877c32b6a7 100644
--- a/django/db/backends/mysql/operations.py
+++ b/django/db/backends/mysql/operations.py
@@ -42,6 +42,10 @@ class DatabaseOperations(BaseDatabaseOperations):
# other database backends.
# Mode 3: Monday, 1-53, with 4 or more days this year.
return "WEEK(%s, 3)" % field_name
+ elif lookup_type == 'iso_year':
+ # Get the year part from the YEARWEEK function, which returns a
+ # number as year * 100 + week.
+ return "TRUNCATE(YEARWEEK(%s, 3), -2) / 100" % field_name
else:
# EXTRACT returns 1-53 based on ISO-8601 for the week number.
return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py
index 62830476bf..7018123cfa 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -69,6 +69,8 @@ END;
return "TO_CHAR(%s, 'IW')" % field_name
elif lookup_type == 'quarter':
return "TO_CHAR(%s, 'Q')" % field_name
+ elif lookup_type == 'iso_year':
+ return "TO_CHAR(%s, 'IYYY')" % field_name
else:
# https://docs.oracle.com/database/121/SQLRF/functions067.htm#SQLRF00639
return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py
index f4e9571f81..b1b83861c1 100644
--- a/django/db/backends/postgresql/operations.py
+++ b/django/db/backends/postgresql/operations.py
@@ -31,6 +31,8 @@ class DatabaseOperations(BaseDatabaseOperations):
if lookup_type == 'week_day':
# For consistency across backends, we return Sunday=1, Saturday=7.
return "EXTRACT('dow' FROM %s) + 1" % field_name
+ elif lookup_type == 'iso_year':
+ return "EXTRACT('isoyear' FROM %s)" % field_name
else:
return "EXTRACT('%s' FROM %s)" % (lookup_type, field_name)
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index 20905c83b8..d124fcd47b 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -338,6 +338,8 @@ def _sqlite_date_extract(lookup_type, dt):
return dt.isocalendar()[1]
elif lookup_type == 'quarter':
return math.ceil(dt.month / 3)
+ elif lookup_type == 'iso_year':
+ return dt.isocalendar()[0]
else:
return getattr(dt, lookup_type)
@@ -410,6 +412,8 @@ def _sqlite_datetime_extract(lookup_type, dt, tzname):
return dt.isocalendar()[1]
elif lookup_type == 'quarter':
return math.ceil(dt.month / 3)
+ elif lookup_type == 'iso_year':
+ return dt.isocalendar()[0]
else:
return getattr(dt, lookup_type)
diff --git a/django/db/models/functions/__init__.py b/django/db/models/functions/__init__.py
index 5f5a8bd1dc..f005546eb0 100644
--- a/django/db/models/functions/__init__.py
+++ b/django/db/models/functions/__init__.py
@@ -1,9 +1,9 @@
from .comparison import Cast, Coalesce, Greatest, Least
from .datetime import (
- Extract, ExtractDay, ExtractHour, ExtractMinute, ExtractMonth,
- ExtractQuarter, ExtractSecond, ExtractWeek, ExtractWeekDay, ExtractYear,
- Now, Trunc, TruncDate, TruncDay, TruncHour, TruncMinute, TruncMonth,
- TruncQuarter, TruncSecond, TruncTime, TruncWeek, TruncYear,
+ Extract, ExtractDay, ExtractHour, ExtractIsoYear, ExtractMinute,
+ ExtractMonth, ExtractQuarter, ExtractSecond, ExtractWeek, ExtractWeekDay,
+ ExtractYear, Now, Trunc, TruncDate, TruncDay, TruncHour, TruncMinute,
+ TruncMonth, TruncQuarter, TruncSecond, TruncTime, TruncWeek, TruncYear,
)
from .math import (
Abs, ACos, ASin, ATan, ATan2, Ceil, Cos, Cot, Degrees, Exp, Floor, Ln, Log,
@@ -24,7 +24,8 @@ __all__ = [
# datetime
'Extract', 'ExtractDay', 'ExtractHour', 'ExtractMinute', 'ExtractMonth',
'ExtractQuarter', 'ExtractSecond', 'ExtractWeek', 'ExtractWeekDay',
- 'ExtractYear', 'Now', 'Trunc', 'TruncDate', 'TruncDay', 'TruncHour',
+ 'ExtractIsoYear', 'ExtractYear', 'Now', 'Trunc', 'TruncDate', 'TruncDay',
+ 'TruncHour', 'TruncMinute', 'TruncMonth', 'TruncQuarter', 'TruncSecond',
'TruncMinute', 'TruncMonth', 'TruncQuarter', 'TruncSecond', 'TruncTime',
'TruncWeek', 'TruncYear',
# math
diff --git a/django/db/models/functions/datetime.py b/django/db/models/functions/datetime.py
index 1876aa7d5c..4d24d2a694 100644
--- a/django/db/models/functions/datetime.py
+++ b/django/db/models/functions/datetime.py
@@ -80,6 +80,11 @@ class ExtractYear(Extract):
lookup_name = 'year'
+class ExtractIsoYear(Extract):
+ """Return the ISO-8601 week-numbering year."""
+ lookup_name = 'iso_year'
+
+
class ExtractMonth(Extract):
lookup_name = 'month'
@@ -126,6 +131,7 @@ DateField.register_lookup(ExtractMonth)
DateField.register_lookup(ExtractDay)
DateField.register_lookup(ExtractWeekDay)
DateField.register_lookup(ExtractWeek)
+DateField.register_lookup(ExtractIsoYear)
DateField.register_lookup(ExtractQuarter)
TimeField.register_lookup(ExtractHour)
@@ -142,6 +148,12 @@ ExtractYear.register_lookup(YearGte)
ExtractYear.register_lookup(YearLt)
ExtractYear.register_lookup(YearLte)
+ExtractIsoYear.register_lookup(YearExact)
+ExtractIsoYear.register_lookup(YearGt)
+ExtractIsoYear.register_lookup(YearGte)
+ExtractIsoYear.register_lookup(YearLt)
+ExtractIsoYear.register_lookup(YearLte)
+
class Now(Func):
template = 'CURRENT_TIMESTAMP'