使用日期时间和时区时出现代码问题

Posted

技术标签:

【中文标题】使用日期时间和时区时出现代码问题【英文标题】:Issue with code when using datetime and timezone 【发布时间】:2018-02-10 00:06:10 【问题描述】:

我有一个名为“条目”的字符串列表。每个条目都包含一个日期和时间,格式如下:'Mon Jun 15 17:52:03 2015'

我正在使用正则表达式解析每个条目的日期/时间,然后我需要将它们放入 python 的日期时间格式并将时区更改为 UTC(本地时间 +4 小时)。这是我的代码:

from datetime import datetime
import pytz

local = pytz.timezone("Etc/GMT+4")
localdate = [None]*len(entries)
local_dt = [None]*len(entries)
utc_dt = [None]*len(entries)
utdate = [None]*len(entries)

for i in range(len(entries)):
    localdate[i] = datetime.strptime(re.search(r'\w3\s*?\w3\s*?\d1,2\s*?
\d1,2:\d2:\d2\s*?\d4', entries[i]).group(0), "%c")
    local_dt[i] = local.localize(localdate[i], is_dst=None)
    utc_dt[i] = local_dt[i].astimezone(pytz.utc)
    utdate[i] = utc_dt[i].strftime("%c")

utdate = map(str, utdate)
print utdate

如果我通过并打印每个步骤,它似乎逐行运行良好,但是一旦到达最后一步,它就会恢复为日期/时间的原始格式,而不是 python 日期时间格式yyyy-mm-dd hh:mm:ss'。有谁知道怎么回事?

【问题讨论】:

【参考方案1】:

tl;博士

您正在将datetime 对象格式化为带有utdate[i] = utc_dt[i].strftime("%c") 的字符串。 %c 代码 formats the date according to the system's localization settings,不是您期望的格式。

datetime 对象的标准字符串表示将生成您正在寻找的格式 - 您可以从 str(some_datetime)print(some_datetime) 获取字符串以将其打印到控制台。

时区

众所周知,这很难跟踪,但您可能需要仔细检查您使用的时区。照原样,您的代码将花费输入时间并给出提前 4 小时的输出时间。如果我理解正确,那么您期望它反过来。您应该知道"Etc" timezones are labelled oppositely for weird reasons,并且您可能想要更改使用的时区。这是一个不同的问题,但使用基于位置的时区而不是 UTC 偏移量对于 DST 支持等问题可能是一个好主意。

改进

您可以通过一些更改来简化和阐明您在此处尝试执行的操作。它也使它更“Pythonic”。

input_format = '%a %b %d %H:%M:%S %Y' # Change 1
converted_entries = [] # Change 2

for entry in entries: # Change 3
    local_date = datetime.strptime(entry, input_format) # Change 1 (continued)
    # Change 4
    localized_date = local.localize(local_date)
    utc_date = localized_date.astimezone(pytz.utc)
    converted_entries.append(utc_date)

utdate = map(str, converted_entries)
print utdate

变化

    使用strftime/strptime formatter。 strftimestrptime 旨在解析字符串,通常不需要正则表达式来首先处理它们。输出格式也是如此——如果需要的特定格式没有像datetime.isoformat 这样的内置方法提供,请使用格式化程序。

    在 Python 中,无需提前一定长度初始化列表(或使用 None)。 list_var = []list_var = list() 将为您提供一个空列表,可按需扩展。

    通常最好和最简单的方法是迭代一个列表,而不是跳过循环来获取循环计数器。它更易读,最终更不容易记住。

    如果您确实需要计数器,请使用 enumerate,例如for i, entry in enumerate(entries):

    使用范围变量。 localdatelocaldt 之类的临时值可以保留在 for 循环内。从技术上讲,这是在浪费内存,但更重要的是,它使代码更简单、更封装。

    如果以后需要这些值,请执行我对 converted_entries 列表所做的操作。在循环外初始化它,然后每次都将值附加到列表中。

不需要计数器变量:

localized_dates = []
for # omitted ...
    localized_date = local.localize(local_date)
    localized_dates.append(localized_date)

我希望这对你有帮助。 Python 的美妙之处在于它可以非常简单,所以就接受它吧?

【讨论】:

感谢您的帮助!虽然有一件事还没有解决。我实施了您的改进,但 utdate 以这种格式出现:'2015-06-15 21:52:03+00:00'。时区更改成功并且格式很好,但我需要摆脱那个讨厌的'+00:00'。有什么想法吗?我正在运行 python 2.7.6,所以 %z 不起作用。 阅读我在第 1 点中链接的 strftime format 文档。这就是您用来将日期输出为特定格式的方法。在你的情况下,你会想要像output_format = '%Y-%m-%d %H:%M:%S' 这样的东西。然后将其与strftime 一起使用以获得您想要的格式。您必须将map 操作更改为map(lambda k: k.strftime(output_format), converted_entries) @WynneT 如果解决了问题,请将问题标记为已回答 :)

以上是关于使用日期时间和时区时出现代码问题的主要内容,如果未能解决你的问题,请参考以下文章

得到错误的结果:从 AngularJS 访问 api 并使用 NodeJS 从 firebase 查询结果时出现时区问题

Rails 和 Postgres:迁移到 change_colomn 时出现错误“无法强制转换为没有时区的时间戳”

Django:RunTimeWarning:DateTimeField 在时区支持处于活动状态时收到了一个天真的日期时间

尝试在 moment.js 中转换 RFC2822 日期时出现“弃用警告:时刻构造回退到 js 日期”

使用日期时间绘制切片熊猫数据框时出现 KeyError

获取范围之间的日期时出现问题