Freezegun 总是导致 RuntimeWarning 收到天真的日期时间
Posted
技术标签:
【中文标题】Freezegun 总是导致 RuntimeWarning 收到天真的日期时间【英文标题】:Freezegun always causes RuntimeWarning of receiving naive datetime 【发布时间】:2018-10-20 02:32:55 【问题描述】:我正在处理一个可以暂停组织的测试用例。
目前我正在使用freezegun
来冻结一个固定时间,这是一个datetime.datetime
对象与tzinfo=pytz.UTC
。
在下面的测试中,您将看到self.fake_datetime
的打印,它返回tzaware
日期时间:2000-01-01 00:00:00+00:00
。
当测试运行时,我不断得到著名的RuntimeWarning
:
/usr/local/lib/python2.7/dist-packages/django/db/models/fields/init.py:1447: RuntimeWarning: DateTimeField Organization.suspended 收到一个天真的日期时间( 2000-01-01 00:00:00),而时区支持处于活动状态。 运行时警告)
import datetime
import pytz
from freezegun import freeze_time
# crop
class OrganizationSuspendTestCase(TestCase):
def setUp(self):
self.organization = OrganizationFactory()
self.fake_datetime = datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=pytz.UTC)
print self.fake_datetime
def test_suspend_organization(self):
"""
Case: An organization is being suspended with the suspend service.
Expected: The organization is updated with the suspending datetime and the reason.
"""
with freeze_time(self.fake_datetime):
mc_organization.services.organization.suspend(organization=self.organization, reason="Did not pay the bill")
self.assertEqual(self.organization.suspended, datetime.datetime(2000, 1, 1, 0, 0, 0))
我一直在玩freezegun timezone examples,但没有成功删除运行时警告。
关于如何正确解决此问题的任何建议?我想在没有RuntimeWarning
的情况下继续使用Freezegun
。抑制是一种选择,但我不想这样做。
更新 -- 基于answer of xyres的解决方案
服务在不知情的情况下保存了日期时间时区。旧情况注释,新情况是实际代码。我想了很多关于mocking
并假设保存在service
中的日期时间将被freezegun
测试用例中的时区感知日期时间对象模拟 - 事实并非如此。
def suspend(organization, reason):
"""
Suspend an organization with the given reason.
:param mc_organization.models.Organization organization: The organization to suspend.
:param string reason: The reason of the suspending.
:return: None
"""
# organization.suspended = datetime.datetime.now() (Old sitation)
organization.suspended = timezone.now() # timezone aware situation.
organization.suspended_reason = reason
organization.save()
【问题讨论】:
作为一种快捷方式,您可以将这一行 -timezone.make_aware(datetime.datetime.now())
- 替换为 timezone.now()
,这将自动返回可识别时区的 now
时间。
【参考方案1】:
好像你是trying to save an object with a timezone-naive datetime。要消除此警告,只需在应用程序中的任何位置使用时区感知日期时间即可。
您可以使用位于django.utils.timezone
的Django 的timezone
模块,而不是使用pytz
自己手动管理时区。它有一些快捷方法,可用于将天真的日期时间转换为有意识的日期时间。
使用此功能的一个优点是,如果您在设置文件中更改时区设置,它将自动选择新时区,而使用 pytz
您将不得不在任何地方手动更新新时区。
from django.utils import timezone
fake_datetime = timezone.make_aware(timezone.datetime(2000, 1, 1, 0, 0, 0))
【讨论】:
感谢您的解决方案。我期待 datetime 对象在测试期间被freezegun
模拟,这是一个不正确的假设。我已经根据您的回答更新了我的问题,并描述了我的错误假设。以上是关于Freezegun 总是导致 RuntimeWarning 收到天真的日期时间的主要内容,如果未能解决你的问题,请参考以下文章
在 setContentView() 之前调用 findViewById() 会导致 NullPointerException 但并非总是如此? [复制]