Django DateTimeField()和timezone.now()是什么?

7

好的,在运行函数测试时遇到了奇怪的时区问题。使用Django 1.4和Python 2.7。在MySQL上,DateTimeField()中的毫秒会被截断吗?这是我唯一的理论。

模型文件

from django.db import models
from django.utils import timezone

class Search(models.Model):
    query = models.CharField(max_length=200, null=True)
    query_date = models.DateTimeField(null=True)

test.py

from django.test import TestCase
from django.utils import timezone
from search.models import Search

class SearchModelTest(TestCase):
def test_creating_a_new_search_and_saving_it_to_the_database(self):
    # start by creating a new Poll object with its "question" set
    search = Search()
    search.query = "Test"
    search.query_date = timezone.now()

    # check we can save it to the database
    search.save()

    # now check we can find it in the database again
    all_search_in_database = Search.objects.all()
    self.assertEquals(len(all_search_in_database), 1)
    only_search_in_database = all_search_in_database[0]
    self.assertEquals(only_search_in_database, search)

    # and check that it's saved its two attributes: question and pub_date
    self.assertEquals(only_search_in_database.query, "Test")
    self.assertEquals(only_search_in_database.query_date, search.query_date)

测试以以下方式失败:
self.assertEquals(only_search_in_database.query_date, search.query_date)
AssertionError: datetime.datetime(2013, 1, 16, 21, 12, 35, tzinfo=<UTC>) != datetime.datetime(2013, 1, 16, 21, 12, 35, 234108, tzinfo=<UTC>)

我认为现在发生的是毫秒数在保存到数据库后被截断了。这种情况是否可能?我使用的是MySQL v5.5,请问是MySQL自身截取了日期吗?

4个回答

11

Django ORM将DateTimeField转换为mysql中的Timestamp。通过执行./manage.py sqlall <appname>命令查看原始SQL,可以证实这一点。

在mysql中,timestamp不存储毫秒。

The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.

MySql中存在一个错误,该错误在v5.6.4中似乎已经得到修复,错误详情

Noted in 5.6.4 changelog.

MySQL now supports fractional seconds for TIME, DATETIME, and
TIMESTAMP values, with up to microsecond precision.

我曾经使用过MySQL,但最终决定使用Heroku,因为它对Postgres有更好的支持,而Postgres也是Django推荐使用的数据库。在大多数情况下,迁移都非常顺利。 - Pratik Mandrekar

5

Django 1.8现在支持毫秒。 点击此处查看详细内容。

在使用MySQL后端时,之前Django会从datetime和time值中截断分数秒。现在它让数据库决定是否丢弃这部分值。


2
根据mysql开发者网站

DATETIME或TIMESTAMP值可以包含高达微秒(6位数字)精度的尾数部分。尽管识别此小数部分,但将其从存储到DATETIME或TIMESTAMP列中的值中丢弃。


-2

更新:这是一个非常老的答案,已经不再相关。

DJango ORM目前还不支持MySQL的微秒。他们故意截断微秒组件。如果您使用的是MySQL 5.6.4或更高版本,则可以对DJango代码应用以下更改以使其按预期工作:

这是一个三行更改。希望Django开发人员将其包含在内。您可以在此处跟踪票据:https://code.djangoproject.com/ticket/19716


在 "db/backends/mysql/base.py" 文件中,
函数 "def value_to_db_datetime(self, value)",
从以下内容进行更改:
return six.text_type(value.replace(microseconds=0))

至:

return six.text_type(value)

在 "db/backends/mysql/base.py" 文件中的函数 "def value_to_db_time(self, value)" 中,
将以下内容更改为:
return six.text_type(value.replace(microseconds=0))

to:

return six.text_type(value)

在 "db/backends/mysql/creation.py" 文件中 在 "data_types" 定义中
更改为:
'DateTimeField': 'datetime',

到:

'DateTimeField': 'datetime(6)',

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接