Python datetime对象上的Django F表达式
我的模型是:Python datetime对象上的Django F表达式,python,django,python-2.7,django-queryset,Python,Django,Python 2.7,Django Queryset,我的模型是: class Test(): date1 = models.DateTimeField() date2 = models.DateTimeField() 我可以使用以下查询查找其date2大于date1的对象: Test.obejcts.filter(date2__gt=F('date1')) 我想查找date2大于date1一年的所有对象。 如何根据date1和date2之间的差异找出对象?一般解决方案: 您可以注释日期差异,然后对照时间增量(天数=365)(非常接
class Test():
date1 = models.DateTimeField()
date2 = models.DateTimeField()
我可以使用以下查询查找其date2
大于date1
的对象:
Test.obejcts.filter(date2__gt=F('date1'))
我想查找date2
大于date1
一年的所有对象。如何根据
date1
和date2
之间的差异找出对象?一般解决方案:
您可以注释
日期差异,然后对照时间增量(天数=365)
(非常接近@Anonymous在其评论中的建议):
PostgreSQL特定解决方案: 如果您使用的是
PostgreSQL
,则有另一个选项来自:
您可以一起使用和:
从django.db.models导入日期字段,ExpressionWrapper,F
从django.db.models.functions导入TruncDate
Test.obejcts.filter(
date2\uuu date\uuu gt=ExpressionWrapper(
TruncDate(F('date1'))+datetime.timedelta(天=365),
输出字段=日期字段(),
),
)
如果您真正需要的是类似于date1=2019-05-14
,date2>2020-05-14
。那么这种方法并不总是正确的,因为闰年有366天。这个问题可以通过同时使用Trunc
和Extract
函数来解决。不同的方法是可能的。。。例如:
来自django.db.models导入日期字段,ExpressionWrapper,F
从django.db.models.functions导入TruncDate、ExtractDay
日期\字段=日期字段()
年份=时间增量(天数=365)
闰年=时间增量(天数=366)
shifted_date1=ExpressionWrapper(
TruncDate(F(“日期1”)+年份,
输出字段=日期字段,
)
leap\u shift\u date1=ExpressionWrapper(
TruncDate(日期1)+闰年,
输出字段=日期字段,
)
qs=Test.objects.filter(
(
#如果。。。
Q(日期2\uu日期\uu gt=shift\u日期1)
&
(
#如果365天后的月份日期相同。。。
Q(日期1天=提取日(移位日期1))
|
#或者是2月29日
Q(
日期1__月=2,
date1_uuuDay=29,
)
)
)
|
Q(
#其他情况下使用366天
日期2\uuuu日期\uuuu gt=leap\u shift\u日期1,
)
)
注意:如果您有功能,请使用_TZ=True
并在特定时区执行查询(例如使用时区。在之前激活(…)
)
执行查询集),那么在添加timedelta
之前执行TruncDate
很重要,因为在每年不同日期执行切换到“夏令时”的国家,执行TruncDate(F('date1')+timedelta(…)
可能会给出错误的结果。例如:
- 一些国家在2019年切换到DST时间
,并将在2020年切换到2019-03-31
2020-03-29
- 当地时间2019-03-30 23:30尚未使用DST李>
- 加上366天(因为明年是闰年)将给出
,因此在“正常化”之后,这个日期时间将变为2020-03-30 23:30“非DST”
2020-03-31 00:30“DST”
- 在添加timedelta之前使用
可以解决问题,因为TruncDate
2016-12-31 23:59:60.999
)的最后几秒也可能受到TruncDate/timedelta shift排序的影响,但“幸运的是”大多数数据库不支持闰秒,而python的datetime.datetime
也缺少此功能没有现成的安装工具可供尝试,但是
Test.objects.annotate(下一年=F('date1')+timedelta(days=365)).filter(下一年=F('date2'))呢
?或者在注释表达式中减去两个日期。如果我使用Test.objects.annotate(duration=F('date2')-F('date1')),我会在queryset中得到一些十进制值。这些值是什么?@mahabuburrahamanmellow您是否有可能使用MySQL?是的,我正在使用MySQL。这是此解决方案的问题吗?尝试使用annotate(duration=F('end\u time')-F('start\u time'))。filter(duration\u gt=timedelta(0299))
但我收到了一个错误:TypeError:expected string或bytes-like-object
@sytech似乎是代码其他地方的问题,与此线程无关。也许您的迁移:
Test.objects.annotate(
duration=F('date2') - F('date1')
).filter(duration__gt=timedelta(days=365))
from django.db.models import F, Func
Test.objects.annotate(
duration = Func(F('date2'), F('date1'), function='age')
).filter(duration__gt=timedelta(days=365))