【问题标题】:Django: time zone issueDjango:时区问题
【发布时间】:2011-06-15 21:37:56
【问题描述】:

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

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

而且,在我的模型类中我已经指定:

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 的时区。

感谢任何帮助/澄清。

谢谢 埃里克

【问题讨论】:

  • 你从中得到了什么? >>> 导入日期时间 >>> datetime.datetime.now()
  • 我刚刚更新了服务器信息。时区设置为 On Server Europe/London。
  • 我宁愿不使用 AUTO_NOW。它委托给应设置时区的数据库服务器。这样一来,您就失去了按用户设置不同时区的灵活性。

标签: django timezone


【解决方案1】:

依赖日期/时间“自动”是危险的,这些 auto_add 模型参数是一个陷阱。始终了解您正在处理的时区。 Python 通过将 tzinfo 成员附加到它的 datetime 对象使这更容易。虽然这些对象默认情况下是“幼稚的”,但我鼓励您始终附加 tzinfo 详细信息。 Python 仍然需要在 python-dateutilpytz (我使用的)方面提供一些额外的帮助。不过,这是一条通用规则 - 始终将您的日期时间以 UTC 格式存储在数据库中。

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

所以在你的情况下。

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

如果你使用 pytz,localize() 方法很棒。 Python 的 datetime 对象具有有用的 replace() 和 astimezone()。

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

这是一个thread,其中包含 Django 的 auto_now 字段的详细信息。

【讨论】:

    【解决方案2】:

    首先,我想将我的数据存储为 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
    

    现在,另一方面,如果您想让时间在服务器上的正确区域中,以便您可以在其上执行逻辑。我建议使用python-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】:

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

    【讨论】:

      【解决方案4】:

      最简单/最快的解决方法 [上面由 Ajay Yadav 说] 是这样的,

      只需将 TIME_ZONE 属性添加到 settings.py 中的数据库部分,

      settings.py

      # Database
      # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
      
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.sqlite3',
              'NAME': BASE_DIR / 'db.sqlite3',
              'TIME_ZONE': 'Asia/Tokyo',
          }
      }
      

      有关可用的时区选择,请参阅下面链接的官方文档

      DJANGO TIMEZONE CHOICES

      【讨论】:

      【解决方案5】:

      由于您编辑了问题,我将编辑我的答案 :) 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 服务器以使更改生效。

      【讨论】:

      • 只要 DB 存储时区偏移量(不了解 MySQL,但 Postgres 使用“带有时区的时间戳”数据类型来做到这一点),Django 不应该关心 DB 设置——它应该只做数学。尽管 Django 被认为与数据库无关,但 Eric 最好指定他正在运行的数据库服务器(名称和版本)——这将有助于调试。
      猜你喜欢
      • 2021-01-26
      • 2015-02-11
      • 2013-11-23
      • 2016-09-20
      • 2012-06-06
      • 2015-01-06
      • 1970-01-01
      • 2021-04-10
      • 1970-01-01
      相关资源
      最近更新 更多