Refs #33517 -- Prevented __second lookup from returning fractional seconds on PostgreSQL.

This commit is contained in:
nabil-rady 2022-02-21 03:28:19 +02:00 committed by Mariusz Felisiak
parent 659d2421c7
commit b7f263551c
3 changed files with 31 additions and 0 deletions

View File

@ -86,6 +86,12 @@ class DatabaseFeatures(BaseDatabaseFeatures):
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests." "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests."
"test_trunc_week_before_1000", "test_trunc_week_before_1000",
}, },
"Oracle extracts seconds including fractional seconds (#33517).": {
"db_functions.datetime.test_extract_trunc.DateFunctionTests."
"test_extract_second_func_no_fractional",
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests."
"test_extract_second_func_no_fractional",
},
"Oracle doesn't support bitwise XOR.": { "Oracle doesn't support bitwise XOR.": {
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor", "expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor",
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null", "expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null",

View File

@ -77,6 +77,9 @@ class DatabaseOperations(BaseDatabaseOperations):
def datetime_extract_sql(self, lookup_type, field_name, tzname): def datetime_extract_sql(self, lookup_type, field_name, tzname):
field_name = self._convert_field_to_tz(field_name, tzname) field_name = self._convert_field_to_tz(field_name, tzname)
if lookup_type == "second":
# Truncate fractional seconds.
return f"EXTRACT('second' FROM DATE_TRUNC('second', {field_name}))"
return self.date_extract_sql(lookup_type, field_name) return self.date_extract_sql(lookup_type, field_name)
def datetime_trunc_sql(self, lookup_type, field_name, tzname): def datetime_trunc_sql(self, lookup_type, field_name, tzname):
@ -84,6 +87,12 @@ class DatabaseOperations(BaseDatabaseOperations):
# https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC # https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name) return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
def time_extract_sql(self, lookup_type, field_name):
if lookup_type == "second":
# Truncate fractional seconds.
return f"EXTRACT('second' FROM DATE_TRUNC('second', {field_name}))"
return self.date_extract_sql(lookup_type, field_name)
def time_trunc_sql(self, lookup_type, field_name, tzname=None): def time_trunc_sql(self, lookup_type, field_name, tzname=None):
field_name = self._convert_field_to_tz(field_name, tzname) field_name = self._convert_field_to_tz(field_name, tzname)
return "DATE_TRUNC('%s', %s)::time" % (lookup_type, field_name) return "DATE_TRUNC('%s', %s)::time" % (lookup_type, field_name)

View File

@ -899,6 +899,22 @@ class DateFunctionTests(TestCase):
2, 2,
) )
def test_extract_second_func_no_fractional(self):
start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321)
end_datetime = datetime(2016, 6, 15, 14, 30, 50, 783)
if settings.USE_TZ:
start_datetime = timezone.make_aware(start_datetime)
end_datetime = timezone.make_aware(end_datetime)
obj = self.create_model(start_datetime, end_datetime)
self.assertSequenceEqual(
DTModel.objects.filter(start_datetime__second=F("end_datetime__second")),
[obj],
)
self.assertSequenceEqual(
DTModel.objects.filter(start_time__second=F("end_time__second")),
[obj],
)
def test_trunc_func(self): def test_trunc_func(self):
start_datetime = datetime(999, 6, 15, 14, 30, 50, 321) start_datetime = datetime(999, 6, 15, 14, 30, 50, 321)
end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123)