问题 Django:时区问题


注意:我删除了之前存在的问题,并在此处仅提供相关信息。

我们的数据库服务器(RH)指定了TIME_ZONE =“Europe / London”。并且,在Django settings.py中,我们指定TIME_ZONE =“America / New_York”。

并且,在我的Model类中,我指定了:

created = models.DateTimeField(editable=False,auto_now=False, auto_now_add=True)
modified = models.DateTimeField(editable=False,auto_now=True, auto_now_add=True)

当我再去查看管理站点中的数据时,我得到UTC / GMT时间而不是东部时间。

我认为所有的时间都是由Django自动调整的,因为我将“America / New_York”指定为Django的时区。

任何帮助/澄清表示赞赏。

谢谢 埃里克


9958
2018-01-26 14:40


起源

你从这里得到什么? >>> import datetime >>> datetime.datetime.now() - Tommaso Barbugli
我刚刚更新了SERVER信息。时区设置为On Server Europe / London。
我宁愿不使用AUTO_NOW。它委托给应该设置时区的数据库服务器。这样,您就失去了用户拥有不同时区的灵活性。 - Erwin Julius


答案:


依赖日期/时间'automagic'是危险的,这些auto_add模型参数是一个陷阱。始终了解您正在处理的时区。 Python通过将tzinfo成员附加到其datetime对象来简化这一过程。虽然默认情况下这些对象是“天真的”,但我建议您始终附上tzinfo详细信息。仍然Python需要一些额外的帮助 蟒蛇,dateutil 要么 pytz (我用的是什么)这是一个通用规则 - 始终将您的日期时间存储在数据库中作为UTC。

为什么?您的用户可能在不同的本地人,移动电话和笔记本电脑旅行,服务器配置错误或镜像在不同的时区。这么多头疼。日期时间永远不应该是幼稚的,如果它们(如在数据库中)并且您需要上下文,则还要在表中包含时区字段。

所以在你的情况下。

  1. 不要使用auto_now字段,而是使用自定义save()。
  2. 将UTC存储在数据库中
  3. 如果您需要知道时区 - 例如用户事件 - 也将时区存储在数据库中。
  4. 转换为必要/请求的时区

如果你正在使用pytz,那么 本地化() 方法很棒。 Python的datetime对象具有有用的replace()和astimezone()。

还有一点需要注意,如果您的数据库是时区(如MySQL),请确保您的日期时间是UTC,然后使用replace(tzinfo = None),因为数据库连接器无法处理tz感知对象。

这里有一个 线 有关Django的auto_now字段的详细信息。


10
2018-02-07 21:42





首先,我想将我的数据存储为UTC,因为它是一个很好的起点。

所以让我问一下,为什么你需要EST的时间,这是给最终用户的,还是你需要在服务器上做逻辑并在EST中需要它?

如果它是最终用户,一个简单的解决方法是让用户浏览器处理转换到正确的时间。在服务器上将datetime对象转换为时间戳:

timestamp = time.mktime(datetime_obj.timetuple()) * 1000

然后在网页上实例化Date对象:

var date_obj = new Date({{ timestamp }});
var datetime_string = date_obj.toString();
// the datetime_string will be in the users local timezone

现在,另一方面,如果您希望将时间放在服务器上的正确区域中,以便可以对其执行逻辑。我建议使用帮助 蟒蛇,dateutil。它将允许您轻松交换到不同的时区:

from datetime import datetime
from dateutil import zoneinfo

from_zone = zoneinfo.gettz('UTC')
to_zone = zoneinfo.gettz('America/New_York')

utc = created # your datetime object from the db


# Tell the datetime object that it's in UTC time zone since 
# datetime objects are 'naive' by default
utc = utc.replace(tzinfo=from_zone)

# Convert time zone
eastern_time = utc.aztimezone(to_zone)

现在,如果你真的想在EST中存储日期时间,你需要更改数据库服务器上的时间(如Ajay Yadav和gorus所说)。我不知道你为什么要将它们存储为EST,但我不知道你的应用程序是什么。


3
2018-02-03 02:36



托德,我想我的问题还不完整。但我看到你的观点,他们是好的。我将在当前项目中使用您的一些示例。谢谢!


当您说auto_now_add = True时,该值将由您的数据库服务器而不是您的django服务器添加。因此,您需要在数据库服务器上设置时区。


1
2018-02-02 09:47





由于您编辑了问题,我将编辑我的答案:) Django无法控制数据库的时区,因此解决此问题的方法是更新数据库的时区。对于MySql,运行以下查询:

SELECT @@global.time_zone, @@session.time_zone;

这应该回来了 SYSTEM, SYSTEM 默认情况下,在您的情况下,这意味着“欧洲/伦敦”,以及您的问题的原因。现在您已经验证了这一点,请按照此页面上第一条评论中的说明操作:

http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html

在更新时区以使更改生效后,请记住重新启动MySql服务器。


0
2018-01-27 03:40



只要DB存储时区偏移(不知道MySQL,但Postgres使用“带时区的时间戳”数据类型),Django不应该关心数据库设置 - 它应该只是做数学。尽管Django被认为是与DB无关的,但最好是,Eric应该指定他正在运行的数据库服务器(名称和版本) - 这将有助于调试。 - drdaeman