Source code for django.db.models.functions.datetime

fromdatetimeimportdatetimefromdjango.confimportsettingsfromdjango.db.modelsimport(DateField,DateTimeField,DurationField,Field,IntegerField,TimeField,Transform,)fromdjango.db.models.lookupsimport(YearExact,YearGt,YearGte,YearLt,YearLte,)fromdjango.utilsimporttimezoneclassTimezoneMixin:tzinfo=Nonedefget_tzname(self):# Timezone conversions must happen to the input datetime *before*# applying a function. 2015-12-31 23:00:00 -02:00 is stored in the# database as 2016-01-01 01:00:00 +00:00. Any results should be# based on the input datetime not the stored datetime.tzname=Noneifsettings.USE_TZ:ifself.tzinfoisNone:tzname=timezone.get_current_timezone_name()else:tzname=timezone._get_timezone_name(self.tzinfo)returntzname

[docs]classExtract(TimezoneMixin,Transform):lookup_name=Noneoutput_field=IntegerField()def__init__(self,expression,lookup_name=None,tzinfo=None,**extra):ifself.lookup_nameisNone:self.lookup_name=lookup_nameifself.lookup_nameisNone:raiseValueError('lookup_name must be provided')self.tzinfo=tzinfosuper().__init__(expression,**extra)defas_sql(self,compiler,connection):sql,params=compiler.compile(self.lhs)lhs_output_field=self.lhs.output_fieldifisinstance(lhs_output_field,DateTimeField):tzname=self.get_tzname()sql=connection.ops.datetime_extract_sql(self.lookup_name,sql,tzname)elifisinstance(lhs_output_field,DateField):sql=connection.ops.date_extract_sql(self.lookup_name,sql)elifisinstance(lhs_output_field,TimeField):sql=connection.ops.time_extract_sql(self.lookup_name,sql)elifisinstance(lhs_output_field,DurationField):ifnotconnection.features.has_native_duration_field:raiseValueError('Extract requires native DurationField database support.')sql=connection.ops.time_extract_sql(self.lookup_name,sql)else:# resolve_expression has already validated the output_field so this# assert should never be hit.assertFalse,"Tried to Extract from an invalid type."returnsql,paramsdefresolve_expression(self,query=None,allow_joins=True,reuse=None,summarize=False,for_save=False):copy=super().resolve_expression(query,allow_joins,reuse,summarize,for_save)field=copy.lhs.output_fieldifnotisinstance(field,(DateField,DateTimeField,TimeField,DurationField)):raiseValueError('Extract input expression must be DateField, DateTimeField, ''TimeField, or DurationField.')# Passing dates to functions expecting datetimes is most likely a mistake.iftype(field)==DateFieldandcopy.lookup_namein('hour','minute','second'):raiseValueError("Cannot extract time component '%s' from DateField '%s'. "%(copy.lookup_name,field.name))

lookup_name='second'DateField.register_lookup(ExtractYear)DateField.register_lookup(ExtractMonth)DateField.register_lookup(ExtractDay)DateField.register_lookup(ExtractWeekDay)DateField.register_lookup(ExtractWeek)DateField.register_lookup(ExtractQuarter)TimeField.register_lookup(ExtractHour)TimeField.register_lookup(ExtractMinute)TimeField.register_lookup(ExtractSecond)DateTimeField.register_lookup(ExtractHour)DateTimeField.register_lookup(ExtractMinute)DateTimeField.register_lookup(ExtractSecond)ExtractYear.register_lookup(YearExact)ExtractYear.register_lookup(YearGt)ExtractYear.register_lookup(YearGte)ExtractYear.register_lookup(YearLt)ExtractYear.register_lookup(YearLte)classTruncBase(TimezoneMixin,Transform):kind=Nonetzinfo=Nonedef__init__(self,expression,output_field=None,tzinfo=None,**extra):self.tzinfo=tzinfosuper().__init__(expression,output_field=output_field,**extra)defas_sql(self,compiler,connection):inner_sql,inner_params=compiler.compile(self.lhs)# Escape any params because trunc_sql will format the string.inner_sql=inner_sql.replace('%s','%%s')ifisinstance(self.output_field,DateTimeField):tzname=self.get_tzname()sql=connection.ops.datetime_trunc_sql(self.kind,inner_sql,tzname)elifisinstance(self.output_field,DateField):sql=connection.ops.date_trunc_sql(self.kind,inner_sql)elifisinstance(self.output_field,TimeField):sql=connection.ops.time_trunc_sql(self.kind,inner_sql)else:raiseValueError('Trunc only valid on DateField, TimeField, or DateTimeField.')returnsql,inner_paramsdefresolve_expression(self,query=None,allow_joins=True,reuse=None,summarize=False,for_save=False):copy=super().resolve_expression(query,allow_joins,reuse,summarize,for_save)field=copy.lhs.output_field# DateTimeField is a subclass of DateField so this works for both.assertisinstance(field,(DateField,TimeField)),("%r isn't a DateField, TimeField, or DateTimeField."%field.name)# If self.output_field was None, then accessing the field will trigger# the resolver to assign it to self.lhs.output_field.ifnotisinstance(copy.output_field,(DateField,DateTimeField,TimeField)):raiseValueError('output_field must be either DateField, TimeField, or DateTimeField')# Passing dates or times to functions expecting datetimes is most# likely a mistake.class_output_field=self.__class__.output_fieldifisinstance(self.__class__.output_field,Field)elseNoneoutput_field=class_output_fieldorcopy.output_fieldhas_explicit_output_field=class_output_fieldorfield.__class__isnotcopy.output_field.__class__iftype(field)==DateFieldand(isinstance(output_field,DateTimeField)orcopy.kindin('hour','minute','second','time')):raiseValueError("Cannot truncate DateField '%s' to %s. "%(field.name,output_field.__class__.__name__ifhas_explicit_output_fieldelse'DateTimeField'))elifisinstance(field,TimeField)and(isinstance(output_field,DateTimeField)orcopy.kindin('year','quarter','month','day','date')):raiseValueError("Cannot truncate TimeField '%s' to %s. "%(field.name,output_field.__class__.__name__ifhas_explicit_output_fieldelse'DateTimeField'))returncopydefconvert_value(self,value,expression,connection):ifisinstance(self.output_field,DateTimeField):ifsettings.USE_TZ:ifvalueisNone:raiseValueError("Database returned an invalid datetime value. ""Are time zone definitions for your database installed?")value=value.replace(tzinfo=None)value=timezone.make_aware(value,self.tzinfo)elifisinstance(value,datetime):ifisinstance(self.output_field,DateField):value=value.date()elifisinstance(self.output_field,TimeField):value=value.time()returnvalue

[docs]classTruncDate(TruncBase):kind='date'lookup_name='date'output_field=DateField()defas_sql(self,compiler,connection):# Cast to date rather than truncate to date.lhs,lhs_params=compiler.compile(self.lhs)tzname=timezone.get_current_timezone_name()ifsettings.USE_TZelseNonesql=connection.ops.datetime_cast_date_sql(lhs,tzname)

returnsql,lhs_params

[docs]classTruncTime(TruncBase):kind='time'lookup_name='time'output_field=TimeField()defas_sql(self,compiler,connection):# Cast to date rather than truncate to date.lhs,lhs_params=compiler.compile(self.lhs)tzname=timezone.get_current_timezone_name()ifsettings.USE_TZelseNonesql=connection.ops.datetime_cast_time_sql(lhs,tzname)