使用日期时间和时区时出现代码问题
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。 strftime
和 strptime
旨在解析字符串,通常不需要正则表达式来首先处理它们。输出格式也是如此——如果需要的特定格式没有像datetime.isoformat
这样的内置方法提供,请使用格式化程序。
在 Python 中,无需提前一定长度初始化列表(或使用 None
)。 list_var = []
或 list_var = list()
将为您提供一个空列表,可按需扩展。
通常最好和最简单的方法是迭代一个列表,而不是跳过循环来获取循环计数器。它更易读,最终更不容易记住。
如果您确实需要计数器,请使用 enumerate,例如:for i, entry in enumerate(entries):
使用范围变量。 localdate
和 localdt
之类的临时值可以保留在 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 在时区支持处于活动状态时收到了一个天真的日期时间