【问题标题】:Get local timezone in django在 django 中获取本地时区
【发布时间】:2013-01-17 09:46:30
【问题描述】:

我有一个存储在系统时间 UTC 中的 mysql DATETIME 值。我需要将其转换为 django 中的本地时区。这是我目前拥有的:

# value in mysql
`timestamp`
2013-02-01 22:48:45

# settings.py
TIME_ZONE = 'America/Los_Angeles'

# views.py
last_updated = PathLastUpdated.objects.all()[0].timestamp
print last_updated
2013-02-01 22:48:45 <-- same as UTC

如何让 last_updated 值位于我的本地时区 = "America/Los Angeles" 中?

【问题讨论】:

  • “我的本地时区”是指服务器运行的时区还是查看页面的客户端的时区?
  • 我在settings.py中设置的时区='America/Los_Angeles'

标签: python django


【解决方案1】:

Django documentation for timezones 记录了将datetime 对象转换为适当时区以进行显示的所有必要细节。

您的数据以 UTC 格式存储,这很好。当您从数据库中获取DateTime 字段对象时,它将是一个幼稚的datetime.datetime 对象。即没有附加时区的日期/时间。然后由您来完成转换。

您的 web 应用程序的用户可能位于不同的时区,因此对于每个请求,都必须转换为适当的时区。这就是为什么有一个activate 函数来设置当前时区的原因。

如果您安装了pytz,您应该能够执行以下操作:

from django.utils.timezone import activate
activate(settings.TIME_ZONE)

模板引擎中日期字段的所有输出将自动将您的原始日期时间对象转换为正确的时区以进行显示。

如果您只有一个简单的 datetime.datetime 实例来设置时区,那么直接使用 pytz 模块即可。但是,在您的视图中这样做是不正常的,因为最好只在呈现时转换时区。

from pytz import timezone

settings_time_zone = timezone(settings.TIME_ZONE)
last_updated = last_updated.astimezone(settings_time_zone)

【讨论】:

  • 如果last_updated 不在UTC 格式中,则将最后一行更改为:last_updated_in_tz = tz.normalize(last_updated.astimezone(tz))。如果last_updated 是一个简单的日期时间对象,则在调用.astimezone() 之前使其知道:aware_dt = naive_utc_dt.replace(tzinfo=pytz.utc)(注意:.replace() 仅适用于 UTC,否则使用aware_dt = some_tz.localize(naive_dt, is_dst=None))。
  • 通过执行“activate(settings.TIME_ZONE)”会发生设置未定义。我在 settings.py 上定义了我的 TIME_ZONE = 'UTC'。我想在哪里定义 TIME_ZONE?
  • @MrMartin 你需要按照docs.djangoproject.com/en/1.8/topics/settings/…导入Django设置模块
  • 除了构建 API 外,我如何使用它?
  • @Gocht 对于 API,发出请求的实体必须提供有关其时区的信息,以便您能够转换到其时区。这可以通过在请求中使用可以设置为指示时区的字段或使用单独的请求标头来实现。
【解决方案2】:

在哭了很多之后,我可以显示我的国家的正确日期,这样做:

>>> from django.utils.timezone import get_current_timezone
>>> from front.models import Training

>>> tz = get_current_timezone()
>>> stored_date = Training.objects.first().start_date
datetime.datetime(2015, 4, 25, 17, 0, tzinfo=<UTC>)

>>> desired_date = stored_date + tz.utcoffset(stored_date)
datetime.datetime(2015, 4, 25, 14, 0, tzinfo=<UTC>)

tzinfo 属性显示的是 UTC,但显示的日期和时间是正确的。

2015 年 10 月 30 日更新(Django 1.8)

我今天使用另一种方法,对 django 更友好

>>> from django.utils import timezone
>>> from trainings.models import Training
>>> value = Training.objects.first().date

>>> value
datetime.datetime(2015, 10, 23, 11, 32, 54, 633151, tzinfo=<UTC>)

>>> timezone.localtime(value)
datetime.datetime(2015, 10, 23, 9, 32, 54, 633151, tzinfo=<django.utils.timezone.LocalTimezone object at 0x7fa6129784a8>)

【讨论】:

    【解决方案3】:

    localtime 是一个模板过滤器,这可能会有所帮助。

    https://github.com/django/django/blob/1.8.4/django/utils/timezone.py#L298

    代码示例:

    from django.utils.timezone import localtime 
    
    desired_datetime = localtime(stored_datetime)
    

    【讨论】:

      【解决方案4】:

      我创建了一个简单的中间件来为您处理所有这些事情:

      https://github.com/Miserlou/django-easy-timezones

      只需安装它并按照说明操作即可!

      1. 安装 django-easy-timezones

        pip install django-easy-timezones pytz pygeoip
        
      2. 将“easy-timezones”添加到您的 INSTALLED_APPS 设置中,如下所示:

        INSTALLED_APPS = (
        ...
        'easy-timezones',
        )
        
      3. 将 EasyTimezoneMiddleware 添加到您的 MIDDLEWARE_CLASSES

        MIDDLEWARE_CLASSES = (
        ...
        'easy-timezones.middleware.EasyTimezoneMiddleware',
        )
        
      4. 在设置文件中添加MaxMind GeoIP database 的路径:

        GEOIP_DATABASE = '/path/to/your/geoip/database/GeoIP.dat'
        
      5. 在您的模板中启用本地时间。

        {% load tz %}
            The UTC time is {{ object.date }}
        {% localtime on %}
            The local time is {{ object.date }}
        {% endlocaltime %}
        
      6. 多田!

      【讨论】:

      • 根据您的回答,我已经在我的 django 应用程序中设置了简易时区,但是如果我想从终端运行我的应用程序,我收到一条错误消息,提示“没有名为 easy_timezones 的模块”,尽管我已经安装了使用 pip 打包。 @Rich Jones
      • INSTALLED_APPS 和 MIDDLEWARE_CLASSES 应该使用“easy_timezones”,而不是“easy-timezones”——在你的自述文件中是正确的,但在这个答案中却不是。
      • @Rich Jones 如果我在前端使用 DRF 和 angularJS,如何实现这一点?基本上我没有使用 Django 模板。在服务器端使用 DRF、Postgres、Django1.8,在前端使用 AngularJS/HTML。
      【解决方案5】:

      我个人建议不要使用 UTC 以外的 TIME_ZONE 设置。我记得过去遇到过这个问题,无论是数据库在与 Django 后端使用的不同时区(将值保存在不同时区)中运行。这意味着比较时间很麻烦,根据您正在做的事情来回更改时间。

      一种好的做法通常是在后端使用一个时区(比如说 UTC)并将前端的时间转换为您所服务的用户时区。

      【讨论】:

      • 我同意你的看法。我也遇到了其他时区的问题。但是当我从浏览器发送日期时,它不会转换为 UTC,你能建议我一个正确的方法吗?
      • 我需要更多关于如何从浏览器发送日期的信息(格式很重要,是否有以这种格式保存的时区信息)。如果日期是从浏览器发送的,则必须使用 Django 将其转换为 UTC。我建议使用像 labix.org/python-dateutil 这样的库来执行此操作。
      • 感谢您的回复,现在问题已经解决了,但我不知道它是否正确,因为我是 Django 和 python 的新手。目前我正在这样做。我从 jQuery-datepicker 中选择日期和时间并使用 Javascript 转换为 UTC 时间,然后发送到服务器。我曾尝试使用 pytz 库,但在确定日期时间来自哪个时区时出现问题。这造成了在 UTC 中转换的问题。我不知道我是对还是错,请提出正确的做法。
      • 这种方法确实有效,但您将更多逻辑放在客户端上。通常我会将日期转换放在服务器上。不过,如果它对你有用,那很好。这绝对不是错误的做法。
      • 谢谢,我会改成服务器端的。
      【解决方案6】:

      我遇到了同样的问题。在我的设置中,我设置了TIME_ZONE,但是MySql中的时间还是UTC时间。

      # settings.py
      TIME_ZONE = 'Asia/Shanghai'
      

      然后我发现,在settings.py中,USE_TZ已经被设置为False

      USE_TZ = False

      正如@MagicLAMP 所指出的,它仅适用于单时区网站,如果您的网站是国际网站或使用您的网站的地方发生夏令时,请检查time-zones

      【讨论】:

      【解决方案7】:

      我花了一段时间才找到这个,但这就是我解决它的方法。我从 IP 地址猜测用户的时区,然后在 Django 2 及更高版本中执行此操作:

      {% load tz %}
      {% timezone "Europe/Paris" %}
          Paris time: {{ object.date }}
      {% endtimezone %}
      

      【讨论】:

        【解决方案8】:

        随便用

        timezone.localtime(arg)
        

        【讨论】:

          【解决方案9】:

          1:在视图中定义时区

          from django.utils import timezone
          
          variable = timezone.now()
          

          2:然后在你的模板中使用它

          {% load l10n %}
          
          Teresina, {{variable |localize}}.
          

          【讨论】:

            猜你喜欢
            • 2015-05-26
            • 1970-01-01
            • 1970-01-01
            • 2012-01-28
            • 2016-05-05
            • 2023-03-25
            • 2013-08-09
            • 2011-08-12
            • 2021-06-01
            相关资源
            最近更新 更多