【问题标题】:UTC to local timezone in a flask/jinja templateUTC 到烧瓶/神社模板中的本地时区
【发布时间】:2016-04-20 14:58:48
【问题描述】:

我知道以前有人问过这个问题,但我仍在努力解决这个问题。我尝试了 pytz、dateutil,现在又尝试了 flask_moment。在将 MySQL 表日期时间(即 UTC)转换为在 jinja2 模板中显示为本地时间(特别是 UTC - 05:00 (EST))时仍然存在问题。

我的 jinja2 for 循环如下所示:

{% for data in items %}
    ...
   <td>{{data.loggedInBy}}</td>
   <td>{{data.timeIn.strftime('%I:%M %p')}}</td>
    ...
{% endfor %}

我是 python/flask/jinja 的新手,所以请放轻松。对于像我这样的菜鸟来说,文档非常令人困惑。有人可以指导我获取我的 MySQL 表以显示本地时区的时间吗?

我觉得这很接近,但会出错。在 init.py 中,我有:

from pytz import timezone

def datetimefilter(value, format='%I:%M %p'):
    tz = timezone('US/Eastern')
    dt = value
    local_dt = tz.localize(dt)
    local_dt.replace(hour=local_dt.hour + int(local_dt.utcoffset().total_seconds() / 3600))
    return local_dt.strftime(format)

flask_app.jinja_env.filters['datetimefilter'] = datetimefilter

jinja template had:

{% for data in items %}
...
<td>{{data.loggedInBy}}</td>
<td>{{data.timeIn | datetimefilter }}</td>
...
{% endfor %}

但这给了我“ValueError:小时必须在 0..23” 从行:

local_dt.replace(hour=local_dt.hour + int(local_dt.utcoffset().total_seconds() / 3600))

提前致谢!

【问题讨论】:

    标签: python flask jinja2


    【解决方案1】:

    Localize 不会更改时区,而是将时区信息添加到一个简单的 datetime 对象。你说你的日期时间来自 SQL 并且是 UTC,但它是一个时区感知日期时间对象吗?如果 value 是一个知道它是 UTC 而不是天真的日期时间对象的日期时间对象,您应该像这样更改时区

    tz = pytz.timezone('US/Eastern')  # timezone you want to convert to from UTC
    local_dt = value.astimezone(tz)
    return local_dt.strftime(format)
    

    如果遇到错误
    ValueError: astimezone() cannot be applied to a naive datetime
    那么您的 value 是一个天真的日期时间对象,您可以将其设为第一个时区感知(如 UTC),然后像这样获取您的本地化日期时间。

    tz = pytz.timezone('US/Eastern')
    utc = pytz.timezone('UTC')
    tz_aware_dt = utc.localize(value)
    local_dt = tz_aware_dt.astimezone(tz)
    return local_dt.strftime(format)
    

    您可以通过多种方式检查您的 datetime 对象是否是幼稚的。例如,如果它知道它的时区,value.tzname() 将返回时区的名称,否则它将不返回。

    时区感知:datetime.datetime(2016, 1, 1, 4, 28, 26, 149703, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)

    天真的日期时间对象:datetime.datetime(2016, 1, 1, 9, 28, 26, 149703)

    【讨论】:

    • 感谢 Schechter,但似乎即使在您的第二次建议之后,我仍然收到 ValueError:astimezone() 不能应用于幼稚的日期时间。更近了,但对我来说仍然不太有效。
    • 是的,Schechter,看起来tz_aware_dt = utc.localize(value) 的行应该是:tz_aware_dt = utc.localize(value).astimezone(pytz.utc) 以使其真正意识到
    • 感谢@RyanGreever 指出这一点。我想我把“价值”留在了应该是 tz_aware_dt 的地方。我已编辑答案以反映更改。
    • 从 Python 3.6 开始, astimezone() 可以在一个简单的日期时间调用,并且假定它位于本地时区。当心!
    【解决方案2】:

    在这种特殊情况下,这最终对我有用,我仍然不确定它是否会在 DST 期间提供不正确的信息,但我们会看到。

    import pytz
    from pytz import timezone
    import tzlocal 
    
    def datetimefilter(value, format="%I:%M %p"):
        tz = pytz.timezone('US/Eastern') # timezone you want to convert to from UTC
        utc = pytz.timezone('UTC')  
        value = utc.localize(value, is_dst=None).astimezone(pytz.utc)
        local_dt = value.astimezone(tz)
        return local_dt.strftime(format)
    
    flask_app.jinja_env.filters['datetimefilter'] = datetimefilter
    

    那么我的 jinja2 模板看起来像:

    {% for data in items %}
    ...
    <td>{{data.loggedInBy}}</td>
    <td>{{data.timeIn | datetimefilter }}</td>
    ...
    {% endfor %}
    

    如果有任何改进的方法,我愿意接受建议,但到目前为止,这是我发现的唯一可行的方法。

    【讨论】:

    • 这就是我要找的。谢谢。
    【解决方案3】:

    Flask-Moment 在这种情况下很适合使用。详细说明见链接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-27
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 2016-01-21
      相关资源
      最近更新 更多