mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Fixed #30128 -- Fixed handling timedelta timezone in database functions.
This commit is contained in:
@@ -69,9 +69,20 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
else:
|
||||
return "DATE(%s)" % (field_name)
|
||||
|
||||
def _prepare_tzname_delta(self, tzname):
|
||||
if '+' in tzname:
|
||||
return tzname[tzname.find('+'):]
|
||||
elif '-' in tzname:
|
||||
return tzname[tzname.find('-'):]
|
||||
return tzname
|
||||
|
||||
def _convert_field_to_tz(self, field_name, tzname):
|
||||
if settings.USE_TZ and self.connection.timezone_name != tzname:
|
||||
field_name = "CONVERT_TZ(%s, '%s', '%s')" % (field_name, self.connection.timezone_name, tzname)
|
||||
field_name = "CONVERT_TZ(%s, '%s', '%s')" % (
|
||||
field_name,
|
||||
self.connection.timezone_name,
|
||||
self._prepare_tzname_delta(tzname),
|
||||
)
|
||||
return field_name
|
||||
|
||||
def datetime_cast_date_sql(self, field_name, tzname):
|
||||
|
||||
@@ -94,6 +94,13 @@ END;
|
||||
# This regexp matches all time zone names from the zoneinfo database.
|
||||
_tzname_re = re.compile(r'^[\w/:+-]+$')
|
||||
|
||||
def _prepare_tzname_delta(self, tzname):
|
||||
if '+' in tzname:
|
||||
return tzname[tzname.find('+'):]
|
||||
elif '-' in tzname:
|
||||
return tzname[tzname.find('-'):]
|
||||
return tzname
|
||||
|
||||
def _convert_field_to_tz(self, field_name, tzname):
|
||||
if not settings.USE_TZ:
|
||||
return field_name
|
||||
@@ -106,7 +113,7 @@ END;
|
||||
return "CAST((FROM_TZ(%s, '%s') AT TIME ZONE '%s') AS TIMESTAMP)" % (
|
||||
field_name,
|
||||
self.connection.timezone_name,
|
||||
tzname,
|
||||
self._prepare_tzname_delta(tzname),
|
||||
)
|
||||
return field_name
|
||||
|
||||
|
||||
@@ -40,9 +40,16 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
# https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
|
||||
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
|
||||
|
||||
def _prepare_tzname_delta(self, tzname):
|
||||
if '+' in tzname:
|
||||
return tzname.replace('+', '-')
|
||||
elif '-' in tzname:
|
||||
return tzname.replace('-', '+')
|
||||
return tzname
|
||||
|
||||
def _convert_field_to_tz(self, field_name, tzname):
|
||||
if settings.USE_TZ:
|
||||
field_name = "%s AT TIME ZONE '%s'" % (field_name, tzname)
|
||||
field_name = "%s AT TIME ZONE '%s'" % (field_name, self._prepare_tzname_delta(tzname))
|
||||
return field_name
|
||||
|
||||
def datetime_cast_date_sql(self, field_name, tzname):
|
||||
|
||||
@@ -408,6 +408,14 @@ def _sqlite_datetime_parse(dt, tzname=None, conn_tzname=None):
|
||||
if conn_tzname:
|
||||
dt = dt.replace(tzinfo=pytz.timezone(conn_tzname))
|
||||
if tzname is not None and tzname != conn_tzname:
|
||||
sign_index = tzname.find('+') + tzname.find('-') + 1
|
||||
if sign_index > -1:
|
||||
sign = tzname[sign_index]
|
||||
tzname, offset = tzname.split(sign)
|
||||
if offset:
|
||||
hours, minutes = offset.split(':')
|
||||
offset_delta = datetime.timedelta(hours=int(hours), minutes=int(minutes))
|
||||
dt += offset_delta if sign == '+' else -offset_delta
|
||||
dt = timezone.localtime(dt, pytz.timezone(tzname))
|
||||
return dt
|
||||
|
||||
|
||||
Reference in New Issue
Block a user