微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何有效地将时间/日期字符串解析为日期时间对象?

如何解决如何有效地将时间/日期字符串解析为日期时间对象?

我正在从新闻网站抓取数据,并希望存储这些文章的发布时间和日期。好消息是我可以直接从文章页面中提取这些时间戳。

当我今天抓取的文章发布时,输出如下所示:

17:22 ET
02:41 ET
06:14 ET

文章早于今天发布时,输出如下所示:

Mar 10,2021,16:05 ET
Mar 08,08:00 ET
Feb 26,11:23 ET

当前问题:我无法在文章发布时对我的数据库进行排序,因为每当我运行该程序时,今天发布的文章只存储一个时间。在多天之后,这将创建许多带有邮票的文章,看起来好像它们是在您查看数据库的那天发布的 - 因为只有时间。

我想要的:在给定格式的基础上,在时间戳前面添加当前的月/日/年。

我的想法:我很难理解正则表达式的工作原理。我的想法是检查导入字符串的长度。如果正好是8,我想在前面加上月、日和年。但我不知道这是否是 a) 最有效的方法和 b) 最重要的是,如何编写这个看似简单的想法。

如果有人可以帮助我如何编码,我将不胜感激。当前抓取时间的行如下所示:

article_time = item.select_one('h3 small').text

解决方法

试试这个,如果我忽略了什么,其他人可以纠正我,

from datetime import datetime,timedelta

def get_datetime_from_time(time):
    time,timezone = time.rsplit(' ',1)
    if ',' in time:
        article_time = datetime.strptime(time,r"%b %d,%Y,%H:%M")
    else:
        article_time = datetime.strptime(time,r"%H:%M")
        hour,minute = article_time.hour,article_time.minute
        if timezone == 'ET':
            hours = -4
        else:
            hours = -5
        article_time = (datetime.utcnow() + timedelta(hours=hours)).replace(hour=hour,minute=minute) # Adjust for timezone
    return article_time
        

article_time = item.select_one('h3 small').text
article_time = get_datetime_from_time(article_time)

我在这里做的是检查您的时间字符串中是否有逗号。如果是,那么它有日期,否则它没有。然后我正在检查时区,因为夏令时与标准时间不同。所以我有一个声明将时区调整 4 或 5。然后我得到 UTC 时间(不管你的时区)并调整时区。 strptime 是一个函数,它根据您提供的格式解析时间。

请注意,这不考虑空时间字符串。

,

正确处理时区可能会相当复杂,因为标准库几乎不支持它们(并建议使用第三方 pytz 模块)这样做)。如果您需要它,则尤其如此

因此,处理它们的一种“快速而肮脏”的方法是忽略该信息并将当前日、月和年添加到遇到的任何不包含该信息的时间戳中。下面的代码演示了如何做到这一点。

from datetime import datetime


scrapped = '''
17:22 ET
02:41 ET
06:14 ET
Mar 10,2021,16:05 ET
Mar 08,08:00 ET
Feb 26,11:23 ET
'''

def get_datetime(string):
    string = string[:-3]  # Remove timezone.
    try:
        r = datetime.strptime(string,"%b %d,%H:%M")
    except ValueError:
        try:
            today = datetime.today()
            daytime = datetime.strptime(string,"%H:%M")
            r = today.replace(hour=daytime.hour,minute=daytime.minute,second=0,microsecond=0)
        except ValueError:
            r = None
    return r

for line in scrapped.splitlines():
    if line:
        r = get_datetime(line)
        print(f'{line=},{r=}')
,

我无法订购我的数据库” - 为了能够这样做,您必须将字符串转换为日期时间对象或有序格式(从低分辨率到高分辨率,所以 year-month-day- 等)可以让你正确地对字符串进行排序。

我很难理解正则表达式的工作原理” - 虽然您可以在此处使用正则表达式以某种方式解析和修改您拥有的字符串,但您不会'不需要。

#1 如果您想要一个方便的选项,让您保留日期时间对象,这里有一个使用 dateutil 的选项:

import dateutil

times = ["17:22 ET","02:41 ET","06:14 ET","Mar 10,16:05 ET","Mar 08,08:00 ET","Feb 26,11:23 ET"]

tzmapping = {'ET': dateutil.tz.gettz('US/Eastern')}

for t in times:
    print(f"{t:>22} -> {dateutil.parser.parse(t,tzinfos=tzmapping)}")
              17:22 ET -> 2021-03-13 17:22:00-05:00
              02:41 ET -> 2021-03-13 02:41:00-05:00
              06:14 ET -> 2021-03-13 06:14:00-05:00
Mar 10,16:05 ET -> 2021-03-10 16:05:00-05:00
Mar 08,08:00 ET -> 2021-03-08 08:00:00-05:00
Feb 26,11:23 ET -> 2021-02-26 11:23:00-05:00

请注意,您可以轻松地告诉 dateutil 的解析器使用某个时区(例如,将“ET”转换为美国/东部),如果输入中不存在日期,它还会自动添加今天的日期。

#2 如果你想自己做更多的解析(可能更高效),你可以先提取时区,然后解析其余的并在需要的地方添加日期:

from datetime import datetime
from zoneinfo import ZoneInfo # Python < 3.9: you can use backports.zoneinfo

# add more if you not only have ET...
tzmapping = {'ET': ZoneInfo('US/Eastern')}

# get tuples of the input string with tz stripped off and timezone object
times_zones = [(t[:t.rfind(' ')],tzmapping[t.split(' ')[-1]]) for t in times]

# parse to datetime
dt = []
for t,z in times_zones:
    if len(t)>5: # time and date...
        dt.append(datetime.strptime(t,'%b %d,%H:%M').replace(tzinfo=z))
    else: # time only...
        dt.append(datetime.combine(datetime.now(z).date(),datetime.strptime(t,'%H:%M').time()).replace(tzinfo=z))
        
for t,dtobj in zip(times,dt):
    print(f"{t:>22} -> {dtobj}")

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。