Django在保存DateTimeField到数据库时是否会破坏它?



我有一个如下所述的Django模型

我创建并保存这个模型的一个实例:

>>> from django.db.models import Max, F, Func
>>> from django.conf import settings
>>> import pytz, datetime
>>> from myapp.models import myModel
>>> myModel.objects.all().delete()
>>> myModel.objects.create(
    my_date=datetime.datetime(2037,4,2,15,18,17,tzinfo=pytz.UTC), 
    my_string="asda"
)
<myModel: myModel object>

然后我尝试检索我刚刚插入的实例,但我在本地格式和应用UNIX_TIMESTAMP后获得DateTimeField:

>>> x = myModel.objects.values('my_string').aggregate(
    max1=Max('my_date'), 
    max2=Max(Func(F('my_date'), function='UNIX_TIMESTAMP'))
)
>>> x
{
    'max2': Decimal('2122848857.000000'), 
    'max1': datetime.datetime(2037, 4, 8, 20, 14, 17, tzinfo=<UTC>)
}
>>> datetime.datetime.utcfromtimestamp(x["max2"])
datetime.datetime(2037, 4, 9, 0, 14, 17)

>>> pytz.timezone(settings.TIME_ZONE)
<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
>>> 

如果将2122848857转换回DateTime,则得到2037-04-09T00:14:17+00:00。这比我实际插入的时间长4个小时。为什么?如何纠正这种表面上的腐败?我的机器的时区是EDT,比UTC晚4个小时。但是这仍然不能解释为什么Django把UTC时间保存为我的本地时区。

import pytz, datetime
from django.db.models import Max, F, Func
from django.conf import settings
from myapp.models import myModel
local_tz = pytz.timezone(settings.TIME_ZONE)
local_datetime = local_tz.localize(datetime.datetime(2037, 4, 8, 20, 14, 17), is_dst=None)
utc_datetime = local_datetime.astimezone(pytz.UTC)
# datetime.datetime(2037, 4, 9, 0, 14, 17, tzinfo=<UTC>)
MyModel.objects.create(my_date=utc_datetime)
x = MyModel.objects.aggregate(max1=Max('my_date'),max2=Max(Func(F('my_date'), function='UNIX_TIMESTAMP')))
pytz.UTC.localize(datetime.datetime.fromtimestamp(x['max2'])).astimezone(local_tz) == x['max1'].astimezone(local_tz)

datetimetimestamp之间的主要区别是timestamp将自动存储一个值为UTC,使用当前mysql的time_zone设置,而datetime在插入和检索记录时将忽略time_zone设置。

你正在使用一个datetime字段,但是你也使用mysql的UNIX_TIMESTAMP函数对该字段。当您这样做时,文档解释服务器将该值解释为基于time_zone设置的本地时间值。这就是转换差异的来源。

你有两个选择。

  1. 确保time_zone会话变量在运行查询之前设置为UTC。
  2. 将值存储到timestamp字段,而不是datetime字段。

是。部分数据被丢弃。

Django DateTime字段将数据存储在缺乏时区信息的数据库DateTime存储中,因此信息在存储之前被删除。

这是手册中说的:

注意,如果将其设置为指向DateTimeField,则只考虑>字段的日期部分。此外,当USE_TZ为True时,将在保存对象时的当前时区执行检查。

存储完整的datetime日期的正确方法是使用DateTimeOffset字段-可以在MS-Sql和其他中找到。

相关内容

  • 没有找到相关文章

最新更新