You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Freezegun冻结时区感知datetime仍触发RuntimeWarning的解决方法

解决Freezegun冻结时区时间仍触发Django时区警告的问题

问题场景

你在开发机构暂停功能的测试用例时,使用freezegun冻结了带UTC时区的datetime.datetime对象,打印验证时能看到时区感知的时间(2000-01-01 00:00:00+00:00),但运行测试时一直收到Django的RuntimeWarning:

/usr/local/lib/python2.7/dist-packages/django/db/models/fields/init.py:1447: RuntimeWarning: DateTimeField Organization.suspended received a naive datetime (2000-01-01 00:00:00) while time zone support is active. RuntimeWarning)

你的测试代码如下:

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))

问题根源

其实问题出在业务服务代码而非测试代码:你的测试用例正确冻结了带时区的时间,但服务内部原本使用datetime.datetime.now()生成的是无时区感知(naive)的时间对象——哪怕freezegun冻结了时间,datetime.datetime.now()返回的依然是不带时区的结果,而Django开启时区支持后,不允许将naive时间存入DateTimeField,因此触发了警告。

解决方案

将服务代码中获取当前时间的方式替换为Django提供的timezone.now(),这个方法会返回时区感知的时间对象,能和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 situation)
    organization.suspended = timezone.now() # timezone aware situation.
    organization.suspended_reason = reason
    organization.save()

另外建议同步调整测试中的断言,使用带时区的时间对象,保持代码一致性:

self.assertEqual(self.organization.suspended, datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=pytz.UTC))

内容的提问来源于stack exchange,提问作者Nrzonline

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:49:57