【问题标题】:Email datetime parsing with python使用 python 解析电子邮件日期时间
【发布时间】:2012-08-28 13:10:52
【问题描述】:

我正在尝试使用 python 脚本解析电子邮件的日期时间。

当我打开邮件详细信息时,邮件中的日期值如下所示...

from:    abcd@xyz.com
to:      def@xyz.com
date:    Tue, Aug 28, 2012 at 1:19 PM
subject: Subject of that mail

我正在使用类似的代码

mail = email.message_from_string(str1)
#to = re.sub('</br>','',mail["To"])
to = parseaddr(mail.get('To'))[1]
sender = parseaddr(mail.get('From'))[1]
cc_is = parseaddr(mail.get('Cc'))[1]
date = mail["Date"]
print date

使用python解析的相同邮件日期时间的输出如下所示,带有时间偏移。

Tue, 28 Aug 2012 02:49:13 -0500

我真正希望的地方

Tue, Aug 28, 2012 at 1:19 PM

我很困惑这两个价值观的关系。 谁能帮我弄清楚我需要同时了解邮件详细信息。

【问题讨论】:

标签: python datetime


【解决方案1】:

在 GMail 中查看电子邮件时,在显示电子邮件的发送日期和时间时会使用您的本地时区。 “Tue, 28 Aug 2012 02:49:13 -0500”被解析,然后更新为您的本地时区,并以特定于 GMail 的方式格式化。

stdlib方式的解析和格式化

email.utils 模块包含一个 parsedate_tz() function,专门处理带有时区偏移的电子邮件标头。

它返回一个与time.struct_time 兼容的元组,但添加了一个时区偏移量。另一个 mktime_tz() function 将该元组转换为偏移值(自 UNIX 纪元以来的时间,以秒为单位)。然后可以轻松地将这个值转换为datetime.datetime() 类型的对象。

同样的模块还有一个formatdate() function 用于将 UNIX 纪元时间戳转换为与电子邮件兼容的日期字符串:

>>> from email.utils import parsedate_tz, mktime_tz, formatdate
>>> import time
>>> date = 'Tue, 28 Aug 2012 02:49:13 -0500'
>>> tt = parsedate_tz(date)
>>> timestamp = mktime_tz(tt)
>>> print formatdate(timestamp)
Tue, 28 Aug 2012 07:49:13 -0000

现在我们有了一个适合外发电子邮件的 UTC 格式日期。要将其打印为我的 本地 时区(由我的计算机确定),您需要将 localtime 标志设置为 True

>>> print formatdate(timestamp, True)
Tue, 28 Aug 2012 08:49:13 +0100

使用更好的工具进行解析和格式化

请注意,当我们尝试处理时区时,事情会变得很棘手,formatdate() 函数不会为您提供任何不同格式的选项(就像 GMail 一样),也不会让您选择不同的格式使用的时区。

输入外部python-dateutil module;它有一个解析函数,几乎可以处理任何事情,并且正确地支持时区

>>> import dateutil.parser
>>> dt = dateutil.parser.parse(date)
>>> dt
datetime.datetime(2012, 8, 28, 2, 49, 13, tzinfo=tzoffset(None, -18000))

parse() 函数返回一个datetime.datetime() instance,这使得格式化更容易。现在我们可以使用.strftime() function 像您的电子邮件客户端一样输出它:

>>> print dt.strftime('%a, %b %d, %Y at %I:%M %p')
Tue, Aug 28, 2012 at 02:49 AM

当然,这仍然是当地时区;要将其转换为您的时区,请使用 .astimezone() method 和新的 tzone 对象。 python-dateutil 包对我们来说很方便。

这是您在本地时区(到您的机器)打印它的方法:

>>> import dateutil.tz
>>> print dt.astimezone(dateutil.tz.tzlocal()).strftime('%a, %b %d, %Y at %I:%M %p')
Tue, Aug 28, 2012 at 09:49 AM

或使用特定时区:

>>> print dt.astimezone(dateutil.tz.tzstr('Asia/Kolkata')).strftime('%a, %b %d, %Y at %I:%M %p')
Tue, Aug 28, 2012 at 07:49 AM

【讨论】:

  • 实际上,我要求输出我可以捕获的已解析邮件...例如 CC、TO 或 SENDER ...您指导我格式化该日期时间字符串 ...足够舒适。
  • 对,你对我认为的时区感到困惑;电子邮件日期被解析为一个时区,显示在另一个时区。这通常不是问题。
  • 请注意,您的问题还不清楚;不清楚您在哪里看到这些值以及您的预期。
  • @Martijin:现在清楚了吗?实际上,我无法获得字符串“2012 年 8 月 28 日星期二下午 1:19”..当我在浏览器中的 gmail acc 中打开它时,我可以在邮件中看到它。
  • 2012 年 8 月 28 日星期二亚洲/加尔各答的 13:19:21 转换为 GMT-5 的 2012 年 8 月 28 日星期二 02:49:21 ......所以这是我的最终答案......谢谢@Martijin 为您提供帮助。
【解决方案2】:

你可以只使用 stdlib 来做到这一点:

>>> from email.utils import parsedate_tz, mktime_tz, formatdate
>>> ts = mktime_tz(parsedate_tz('Tue, 28 Aug 2012 02:49:13 -0500'))
>>> formatdate(ts, localtime=True) # assuming Asia/Kolkata is the local timezone
'Tue, 28 Aug 2012 13:19:13 +0530'

如果你想在小时内使用PM 格式:

>>> from datetime import datetime
>>> datetime.fromtimestamp(ts).strftime('%a, %b %d, %Y at %I:%M %p')
'Tue, Aug 28, 2012 at 01:19 PM'

【讨论】:

  • J.F.塞巴斯蒂安是正确的,只是一个错字而不是他需要的日期时间 datetime.datetime 示例应该是这样的 datetime.datetime.fromtimestamp(ts).strftime('%a, %b %d, %Y at %I:%M %p')
  • @Dung:代码按原样工作。查看导入行。
  • 另外,如果你想要一个日期格式来匹配mysql的日期时间格式,这里是:>>> datetime.fromtimestamp(ts).strftime('%y-%m-%d %H: %M:%S')
  • @Dung:再次,代码按原样工作。它生成 OP 明确 请求的时间格式。看问题。
【解决方案3】:

可以选择以下代码

start = f.find('date:') + 5  # +5 is to exclude 'date'+':' i.e.(4+1=5)
end = f.find('subject:', start) # parse from date to subject 
date_time = f[start:end]
print date_time #it will print "Tue, Aug 28, 2012 at 1:19 PM"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-04
    • 2019-02-02
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多