【问题标题】:how to switch strings from 14/Nov/2012 into 2012/11/14 without converting to datetime in Python?如何在不转换为 Python 中的日期时间的情况下将字符串从 2012 年 11 月 14 日切换到 2012 年 11 月 14 日?
【发布时间】:2013-02-24 02:58:27
【问题描述】:

也许是个奇怪的问题,但我们开始吧:

我必须解析几个日志文件,我正在以随机顺序读取这些文件。为了对它们进行排序,我需要按提取的日志时间进行排序。

日志条目将如下所示:

l = 2001:470:1f14:169:5000:eae0:589d:c211 - SOFT12 [14/Nov/2012:09:32:46 +0100] "POST /request HTTP/1.1" 200 984 "-" "-" 181446

我可以这样提取日期:

l.split('+', 1)[0].split('-', 1)[1].split(' ')[2].split('[')[1]

这给了我:

14/Nov/2012:09:32:46

当我查看一年多的日志文件时,每天有超过 200 万条记录,我不想将任何内容转换为日期时间对象,以便可以切换格式和排序。所以我正在寻找一个纯字符串操作,它可以将字符串14/Nov/2012 的日期部分转换为可排序的2012-11-14,最好包含在我方便的拆分语句中...

问题:
如何修改字符串日期而不将其转换为日期时间对象?

【问题讨论】:

  • 斜线分割,选择转换数组,将所有内容串联起来
  • 考虑到日期和时间的复杂性,我个人会硬着头皮直接转换为 DateTime。当我查看接近 10 亿条记录时,我真的不希望字符串转换中出现细微的错误,导致 0.01% 的结果出现错误。细微错误的潜在来源:日志中的夏令时转换。
  • mh。没错,但现在优先考虑的是“处理时间”。
  • 从您的问题来看,这听起来像是一次性操作 - 无论哪种方式都可能只需要几分钟即可运行?但是,如果您确定您的日志时间戳始终来自同一个时区,并且与 DST 没有太多有趣的业务,那么 @lc 的方法更容易,并且可能足以满足您的目的。
  • 旁注:您可能可以减少用于获取日期的拆分次数,例如。 l.split("+",1)[0].split("[",1)[1]'14/Nov/2012:09:32:46 '。这应该可以为每行节省几纳秒。

标签: python string datetime logging converter


【解决方案1】:

这段代码可以工作:

# Converts something like "14/Nov/2012:09:32:46"
# to "2012-11-14:09:32:46"
_MONTHS = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
def convert(s):
  p = s.split(':', 1)
  t = p[0].split('/')
  return "%s-%02d-%02d:" % (t[2], _MONTHS.index(t[1]) + 1, int(t[0])) + p[1]

【讨论】:

  • 不错!我不知道我需要多长时间才能想出这个……谢谢!
【解决方案2】:

与其使用列表并使用其.index() 方法,不如使用dict 可能有用,因为列表将涉及线性搜索。即使列表很短,dict 中的散列操作也可能更快。至少值得一试。

所以,以Nayuki Minase's solution

# Converts something like "14/Nov/2012:09:32:46"
# to "2012-11-14:09:32:46"
_MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
_MONTHS = dict((m, n + 1) for n, m in enumerate(_MONTHS)) # {"Jan": 1, "Feb: 2, ...} 
def convert(s):
  p = s.split(':', 1)
  t = p[0].split('/')
  return "%s-%02d-%02d:" % (t[2], _MONTHS[t[1]], int(t[0])) + p[1]

甚至(为了节省时间)

  return "%s-%02d-%s:" % (t[2], _MONTHS[t[1]], t[0]) + p[1]

如果您可以确定日期的格式已经正确(前导 0)。

【讨论】:

  • 我已经从使用 dict 切换到使用列表,这减少了几毫秒。还是会试一试的
  • 您好 glglgl,如果您对我的答案发表评论或提出编辑而不是复制它并做出自己的答案,那就太好了。谢谢。
  • @NayukiMinase 编辑会破坏您的版本 - 这也是有效的。评论本来是一种选择。但正如我明确指出的代码是谁的行礼,我看不出有什么大问题......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 2022-11-22
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多