【问题标题】:Django DateTimeField() and timezone.now()Django DateTimeField() 和 timezone.now()
【发布时间】:2013-01-16 21:35:17
【问题描述】:

好的,运行功能测试时出现奇怪的时区问题。 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 v 5.5。 MySQL是否截断日期?

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    Django ORM 在 mysql 中将DateTimeField 转换为Timestamp。您可以通过查看执行./manage.py sqlall &lt;appname&gt; 的原始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 中修复,Bug

    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 有更好的支持,这也是 django 推荐的一种,在大多数情况下过渡很顺利。
    【解决方案2】:

    Django 1.8 现在supports milliseconds.

    以前,Django 在使用 MySQL 后端时会从日期时间和时间值中截断小数秒。现在它让数据库决定是否应该删除该部分值

    【讨论】:

      【解决方案3】:

      根据mysql developer site

      DATETIME 或 TIMESTAMP 值可以包含尾随小数 秒部分的精度高达微秒(6 位)。虽然这 小数部分被识别,它从存储到的值中被丢弃 DATETIME 或 TIMESTAMP 列。

      【讨论】:

        【解决方案4】:

        更新:这确实是旧答案,不再相关。

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

        这是一个 3 行更改。希望 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))
        

        到:

        return six.text_type(value)
        

        在“db/backends/mysql/creation.py”中 在“data_types”的定义中

        更改自:

        'DateTimeField': 'datetime',
        

        到:

        'DateTimeField': 'datetime(6)',
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-29
          • 2011-02-02
          • 1970-01-01
          • 2012-06-02
          相关资源
          最近更新 更多