烧瓶/神社模板中的UTC到本地时区

Rya*_*ver 3 python jinja2 flask

我知道这已经被问过了,但我仍在努力寻找解决方案。我已经尝试过pytz,dateutil和现在flask_moment。在将MySQL表日期时间(UTC)转换为本地时间(特别是UTC-05:00(EST))在jinja2模板中显示时,仍然存在问题。

我的jinja2 for循环如下所示:

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

我是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 %}
Run Code Online (Sandbox Code Playgroud)

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

local_dt.replace(hour=local_dt.hour + int(local_dt.utcoffset().total_seconds() / 3600))
Run Code Online (Sandbox Code Playgroud)

提前致谢!

Rya*_*ver 5

在这种特殊情况下,这就是最终为我工作的原因,我仍然不确定在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
Run Code Online (Sandbox Code Playgroud)

然后我的jinja2模板如下所示:

{% for data in items %}
...
<td>{{data.loggedInBy}}</td>
<td>{{data.timeIn | datetimefilter }}</td>
...
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

如果有任何改进的方法,我欢迎您提出建议,但是到目前为止,这是我发现可行的唯一方法。


Sch*_*ter 1

Localize 不会更改时区,而是将时区信息添加到简单的日期时间对象中。你说你的日期时间来自 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)
Run Code Online (Sandbox Code Playgroud)

如果出现错误,
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)
Run Code Online (Sandbox Code Playgroud)

您可以通过多种方法来检查您的日期时间对象是否简单。例如,如果它知道它的时区,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)