我参与将应用程序从php - mysql迁移到django - mysql,好吧,我已经开始迁移一个收件箱应用程序,它允许用户在我第一次数据迁移后使用插件发送消息1to1(使用插入 - 选择mysql声明)我继续进行一些数据迁移,如下所示。
如果我尝试使用以下ORM语句按月计算消息:
Message.objects.filter(sent_at__year=2011, sent_at__month=1).count()
返回0
如果我使用以下SQL语句直接计算它,则返回正确的数字:
select count(*)
from inbox_message
where year(sent_at) = 2011 and month(sent_at) = 1;
结果是64955
经过一些挖掘Google和Stackoverflow后,它似乎与时区天真的日期时间有关,所以我尝试了以下
settings.USE_TZ = False
Message.objects.filter(sent_at__year=2011, sent_at__month=1).count()
现在返回64955万岁!
众所周知,我已经开始将'sent_at'从时区转换为时区感知,我的第一种方法是在我的insert - select语句中应用CONVERT_TZ mysql函数,但它产生相同的结果,因为我的原始数据源在UTC + 1时区我决定使用以下方法解决这个问题:
convert_tz(sent_at, '+01:00', '+00:00')
我没有使用命名时区,因为我没有安装mysql时区 表(如文档所述)
之后我尝试使用django.utils.timezone.make_aware使用一个简单的python脚本来识别我的日期时区...没有任何变化,当USE_TZ = True时仍然为零,脚本看起来像:
from django.utils.timezone import is_naive, make_aware, utc
settings.USE_TZ = False
messages = Message.objects.filter(sent_at__year=2011, sent_at__month=1)
for m in messages:
settings.USE_TZ = True # Set it to true to avoid errors when datetime becomes timezone aware
if is_naive(m.sent_at):
m.sent_at = make_aware(m.sent_at, utc)
m.save()
相同的结果,按年和月过滤会返回0个元素。
只是为了让你知道,过年仅过滤似乎没问题。
提前致谢
添加模型定义回答评论:
class Message(models.Model):
subject = models.CharField(_(u"Subject"), max_length=2200)
body = models.TextField(_(u"Body"))
sender = models.ForeignKey(
get_user_model(),
related_name='sent_messages',
verbose_name=_(u"Sender"))
recipient = models.ForeignKey(
get_user_model(),
related_name='received_messages',
null=True, blank=True, verbose_name=_(u"Recipient"))
parent_msg = models.ForeignKey(
'self',
related_name='next_messages',
null=True, blank=True,
verbose_name=_(u"Parent message"))
sent_at = models.DateTimeField(
_(u"Sent at"), null=True, blank=True, db_index=True)
read_at = models.DateTimeField(
_(u"Read at"), null=True, blank=True, db_index=True)
replied_at = models.DateTimeField(
_(u"Replied at"), null=True, blank=True, db_index=True)
sender_status = BitField(
verbose_name=_(u'Estado sender'),
flags=FLAGS_MESSAGE,
db_index=True)
recipient_status = BitField(
verbose_name=_(u'Estado recipient'),
flags=FLAGS_MESSAGE,
db_index=True)
class Meta:
ordering = ['-sent_at']