django日期的比较 DateTimeField
DateTimeField 是一个日期和时间字段,用于存储日期,在 Python 中由实例表示。顾名思义,该字段用于存储 python 中创建的 datetime 对象。此字段的默认表单窗口小部件是 .管理员使用两个带有 JavaScript 快捷方式的单独小部件。datetime.datetime``TextInput``TextInput
语法
field_name = models.DateTimeField(**options)
DateTimeField 具有以下额外的可选参数 –
-
DateTimeField.auto_now
每次保存对象时,自动将字段设置为现在。对 “last-modified” 时间戳很有用。请注意,始终使用当前日期;它不会被你传递的默认值覆盖。
该字段仅在调用 Model.save() 时自动更新。当以其他方式(例如 QuerySet.update())更新其他字段时,该字段不会更新,但你可以在这样的更新中为该字段指定一个自定义值。 -
DateTimeField.auto_now_add
首次创建对象时,自动将字段设置为现在。用于创建时间戳。请注意,始终使用当前日期;它不仅仅是您可以覆盖的默认值。因此,即使在创建对象时为此字段设置了值,它也将被忽略。如果希望能够修改此字段,请设置以下内容,而不是 auto_now_add=True:
- 对于 DateTimeField: default=datetime.now – 从
datetime.now()
- 对于 DateTimeField: default=timezone.now – 从
django.utils.timezone.now()
- 对于 DateTimeField: default=datetime.now – 从
注: 选项 auto_now_add、auto_now 和 default 是互斥的。这些选项的任意组合都会导致错误。
Python日期的比较
使用datetime模块创建日期
在Django中存储日期和时间的字段通常是DateTimeField或DateField。这些字段分别用于存储日期和时间、或两者的组合。一旦我们从数据库中获取了这些字段的值,我们可以使用datetime模块来处理和比较它们。
首先,我们需要导入datetime模块:
from datetime import datetime
接下来,我们可以使用datetime模块中的各种方法来创建日期。
下面是一些示例:
now = datetime.now() # 当前日期和时间
today = datetime.today() # 当天的日期和时间
date = datetime(2022, 1, 1) # 指定的日期
我们可以在创建日期时指定年、月和日,也可以省略其他字段。datetime模块还提供了许多其他方法来处理日期,比如获取年、月、日等等。
使用datetime比较日期
一旦我们有了两个日期,我们可以使用datetime模块中的比较运算符(如<、>、等)来比较它们。
下面是一些示例:
date1 = datetime(2022, 1, 1)
date2 = datetime(2023, 1, 1)
if date1 < date2:
print("date1在date2之前")
elif date1 > date2:
print("date1在date2之后")
else:
print("date1和date2相同")
if date1 != date2:
print("date1和date2不相同")
我们可以使用比较运算符来判断两个日期的相对位置,并根据需要执行相应的逻辑。
在Django查询中使用datetime比较日期
使用datetime模块比较日期的一个常见情况是在Django查询中筛选日期。Django提供了一种灵活且易于使用的方式来执行这样的查询。
假设我们有一个Model,其中有一个日期字段pub_date,我们想要找到所有pub_date在当前日期之后的记录。我们可以使用以下查询:
from django.db import models
from datetime import datetime
class Article(models.Model):
# other fields
pub_date = models.DateField()
articles = Article.objects.filter(pub_date__gt=datetime.now().date())
在上面的例子中,我们使用了__gt
表达式来检索pub_date大于当前日期的记录。你还可以使用其他运算符,如__lt
(小于)、__gte
(大于等于)等等。
字段比较大小
__gt
大于
__lt
小于
__gte
大于或等于
__lte
小于或等于
使用datetime进行日期计算
除了比较日期,datetime模块还提供了各种方法来执行日期计算。比如,我们可以计算两个日期之间的时间差,或者在给定日期上添加或减去一段时间。
下面是一些示例:
from datetime import timedelta
date1 = datetime(2022, 1, 1)
date2 = datetime(2023, 1, 1)
diff = date2 - date1 # 计算时间差
print(diff.days) # 打印相差的天数
new_date = date1 + timedelta(days=7) # 在给定日期上添加一周的时间
print(new_date)
以上示例展示了如何计算两个日期之间的天数差,并在给定日期上添加一段时间。
报错解决——DateTimeField *** received a naive datetime (***) while time zone support is active
这是一个跟时区有关的问题,报错中说到datetime字段得到一个naive datetime,而不是支持time zone的active datetime
由于Django的设置中米哦人USE_TZ设置为True,Django会自动根据所设的时区对时间进行转换,所以程序中和数据保存的时间都转UTC时间,只有模版渲染时会把时间转为TIME_ZONE所设置的时区的时间。
使用datetime.datetime.utcnow() 输出的是不带时区的utc时间,称为naive time
rom datetime import datetime
datetime.now()
datetime.datetime(2016, 06, 19, 07, 14, 55, 865000)
使用django.utils.timezone.now() 输出的是带时区的utc时间,称为active time
from django.utils import timezone
timezone.now()
datetime.datetime(2025, 1, 8, 13, 0, 37, 256763, tzinfo=datetime.timezone.utc)
如果项目需要根据时区显示时间,那就使用Django的timezone.now()。不需要的话将USE_TZ设置为False即可。
使用带时区的时间,将所有用到datetime.now()的地方改为timezone.now(),并在对应的文件顶部加上from django.utils import timezone,就OK了。
如果项目中已经有了很多datetime.now(),又不想大面积改动的话,可以将import的语句修改一下
# from datetime import datetime # 原来用的注释掉
from django.utils import timezone as datetime # 不想大面积修改就这么做
但是用timezone.now()去获取date、time、today都是没有时区信息的
timezone.now().today()
Out[54]: datetime.datetime(2025, 1, 8, 21, 9, 57, 799967)
timezone.now().date()
Out[55]: datetime.date(2025, 1, 8)
如果还要用django.utils.timezone,按需要可以使用timezone.now()加上或减去时间段timedelta
from datetime import timedelta
timezone.now()-timedelta(minutes=5)
Out[58]: datetime.datetime(2025, 1, 8, 13, 10, 9, 142733, tzinfo=datetime.timezone.utc)
例如:我要查找创建时间为十五分钟之前的订单,并对其进行更新
def update_timeout_order():
passed_time = timedelta(minutes=15)
now = timezone.now()
# 查找十五分钟之前的订单
timeout_orders = Order.objects.filter(create_time__lte=now - passed_time).filter(status='01')
print(timeout_orders)
# 更新
timeout_orders.update(status='09')
参考文章
DateTimeField - Django Models - GeeksforGeeks