Commit 44f3ee77 authored by Jon Dufresne's avatar Jon Dufresne Committed by Tim Graham
Browse files

Fixed #9596 -- Added date transform for DateTimeField.

parent 076a63e6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -99,6 +99,12 @@ class BaseDatabaseOperations(object):
        """
        return "%s"

    def datetime_cast_date_sql(self, field_name, tzname):
        """
        Returns the SQL necessary to cast a datetime value to date value.
        """
        raise NotImplementedError('subclasses of BaseDatabaseOperations may require a datetime_cast_date() method')

    def datetime_extract_sql(self, lookup_type, field_name, tzname):
        """
        Given a lookup_type of 'year', 'month', 'day', 'hour', 'minute' or
+12 −13
Original line number Diff line number Diff line
@@ -39,27 +39,26 @@ class DatabaseOperations(BaseDatabaseOperations):
            sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
        return sql

    def datetime_extract_sql(self, lookup_type, field_name, tzname):
    def _convert_field_to_tz(self, field_name, tzname):
        if settings.USE_TZ:
            field_name = "CONVERT_TZ(%s, 'UTC', %%s)" % field_name
            params = [tzname]
        else:
            params = []
        # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
        if lookup_type == 'week_day':
            # DAYOFWEEK() returns an integer, 1-7, Sunday=1.
            # Note: WEEKDAY() returns 0-6, Monday=0.
            sql = "DAYOFWEEK(%s)" % field_name
        else:
            sql = "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
        return field_name, params

    def datetime_cast_date_sql(self, field_name, tzname):
        field_name, params = self._convert_field_to_tz(field_name, tzname)
        sql = "DATE(%s)" % field_name
        return sql, params

    def datetime_extract_sql(self, lookup_type, field_name, tzname):
        field_name, params = self._convert_field_to_tz(field_name, tzname)
        sql = self.date_extract_sql(lookup_type, field_name)
        return sql, params

    def datetime_trunc_sql(self, lookup_type, field_name, tzname):
        if settings.USE_TZ:
            field_name = "CONVERT_TZ(%s, 'UTC', %%s)" % field_name
            params = [tzname]
        else:
            params = []
        field_name, params = self._convert_field_to_tz(field_name, tzname)
        fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
        format = ('%%Y-', '%%m', '-%%d', ' %%H:', '%%i', ':%%s')  # Use double percents to escape.
        format_def = ('0000-', '01', '-01', ' 00:', '00', ':00')
+10 −10
Original line number Diff line number Diff line
@@ -114,6 +114,8 @@ WHEN (new.%(col_name)s IS NULL)
    _tzname_re = re.compile(r'^[\w/:+-]+$')

    def _convert_field_to_tz(self, field_name, tzname):
        if not settings.USE_TZ:
            return field_name
        if not self._tzname_re.match(tzname):
            raise ValueError("Invalid time zone name: %s" % tzname)
        # Convert from UTC to local time, returning TIMESTAMP WITH TIME ZONE.
@@ -127,19 +129,17 @@ WHEN (new.%(col_name)s IS NULL)
        # on DATE values, even though they actually store the time part.
        return "CAST(%s AS TIMESTAMP)" % result

    def datetime_cast_date_sql(self, field_name, tzname):
        field_name = self._convert_field_to_tz(field_name, tzname)
        sql = 'TRUNC(%s)' % field_name
        return sql, []

    def datetime_extract_sql(self, lookup_type, field_name, tzname):
        if settings.USE_TZ:
        field_name = self._convert_field_to_tz(field_name, tzname)
        if lookup_type == 'week_day':
            # TO_CHAR(field, 'D') returns an integer from 1-7, where 1=Sunday.
            sql = "TO_CHAR(%s, 'D')" % field_name
        else:
            # http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions050.htm
            sql = "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
        sql = self.date_extract_sql(lookup_type, field_name)
        return sql, []

    def datetime_trunc_sql(self, lookup_type, field_name, tzname):
        if settings.USE_TZ:
        field_name = self._convert_field_to_tz(field_name, tzname)
        # http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions230.htm#i1002084
        if lookup_type in ('year', 'month'):
+12 −12
Original line number Diff line number Diff line
@@ -32,26 +32,26 @@ class DatabaseOperations(BaseDatabaseOperations):
        # http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
        return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)

    def datetime_extract_sql(self, lookup_type, field_name, tzname):
    def _convert_field_to_tz(self, field_name, tzname):
        if settings.USE_TZ:
            field_name = "%s AT TIME ZONE %%s" % field_name
            params = [tzname]
        else:
            params = []
        # http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
        if lookup_type == 'week_day':
            # For consistency across backends, we return Sunday=1, Saturday=7.
            sql = "EXTRACT('dow' FROM %s) + 1" % field_name
        else:
            sql = "EXTRACT('%s' FROM %s)" % (lookup_type, field_name)
        return field_name, params

    def datetime_cast_date_sql(self, field_name, tzname):
        field_name, params = self._convert_field_to_tz(field_name, tzname)
        sql = '(%s)::date' % field_name
        return sql, params

    def datetime_extract_sql(self, lookup_type, field_name, tzname):
        field_name, params = self._convert_field_to_tz(field_name, tzname)
        sql = self.date_extract_sql(lookup_type, field_name)
        return sql, params

    def datetime_trunc_sql(self, lookup_type, field_name, tzname):
        if settings.USE_TZ:
            field_name = "%s AT TIME ZONE %%s" % field_name
            params = [tzname]
        else:
            params = []
        field_name, params = self._convert_field_to_tz(field_name, tzname)
        # http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
        sql = "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
        return sql, params
+18 −6
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
        conn = Database.connect(**conn_params)
        conn.create_function("django_date_extract", 2, _sqlite_date_extract)
        conn.create_function("django_date_trunc", 2, _sqlite_date_trunc)
        conn.create_function("django_datetime_cast_date", 2, _sqlite_datetime_cast_date)
        conn.create_function("django_datetime_extract", 3, _sqlite_datetime_extract)
        conn.create_function("django_datetime_trunc", 3, _sqlite_datetime_trunc)
        conn.create_function("regexp", 2, _sqlite_regexp)
@@ -354,7 +355,7 @@ def _sqlite_date_trunc(lookup_type, dt):
        return "%i-%02i-%02i" % (dt.year, dt.month, dt.day)


def _sqlite_datetime_extract(lookup_type, dt, tzname):
def _sqlite_datetime_parse(dt, tzname):
    if dt is None:
        return None
    try:
@@ -363,6 +364,20 @@ def _sqlite_datetime_extract(lookup_type, dt, tzname):
        return None
    if tzname is not None:
        dt = timezone.localtime(dt, pytz.timezone(tzname))
    return dt


def _sqlite_datetime_cast_date(dt, tzname):
    dt = _sqlite_datetime_parse(dt, tzname)
    if dt is None:
        return None
    return dt.date().isoformat()


def _sqlite_datetime_extract(lookup_type, dt, tzname):
    dt = _sqlite_datetime_parse(dt, tzname)
    if dt is None:
        return None
    if lookup_type == 'week_day':
        return (dt.isoweekday() % 7) + 1
    else:
@@ -370,12 +385,9 @@ def _sqlite_datetime_extract(lookup_type, dt, tzname):


def _sqlite_datetime_trunc(lookup_type, dt, tzname):
    try:
        dt = backend_utils.typecast_timestamp(dt)
    except (ValueError, TypeError):
    dt = _sqlite_datetime_parse(dt, tzname)
    if dt is None:
        return None
    if tzname is not None:
        dt = timezone.localtime(dt, pytz.timezone(tzname))
    if lookup_type == 'year':
        return "%i-01-01 00:00:00" % dt.year
    elif lookup_type == 'month':
Loading