解析包含不同长度Python的时间戳

时间:2015-01-08 20:28:37

标签: python parsing datetime pandas timestamp

我有180,000行时间戳,我想解析成日期时间格式,如:

YYYY-MM-DD HH:MM:SS

以下是时间戳(注意前9小时内缺少前导零):

19-May-14 3:36:00 PM PDT
19-May-14 10:37:00 PM PDT 

我一直使用parse_dates作为pandas.read的一部分来解析这些日期,但我发现这种方法很慢(通常约80秒)。我也尝试了dateutil解析器,结果相似。

我想更快地解析时间戳,但我遇到时间戳中不同宽度的问题。我发现this SO solution似乎与我的问题非常相似,但未能使该方法适应不同长度的时间戳。

有人会建议对链接解决方案进行可行的调整,还是其他更好的方法?

谢谢

4 个答案:

答案 0 :(得分:2)

此解决方案以附加链接中提供的accepted answer为基础,并假设时区由3个字符组成(并忽略其特定值)。


您可以根据它们在字符串开头的相对位置来提取年,月和日,如下所示:

month_abbreviations = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4,
                       'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8,
                       'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
day = int(line[0:2])
month = month_abbreviations[line[3:6]]
year = 2000 + int(line[7:9]) # this should be adapted to your specific use-case

您可以根据它们在字符串末尾的相对位置提取分钟,秒和AM / PM,如下所示:

AM_PM = line[-6:-4]
second = int(line[-9:-7])
minute = int(line[-12:-10])

您可以根据其相对于字符串开头和结尾的位置来提取小时:

hour = int(line[10:-13])

然后您可以根据AM_PM值计算确切的小时数,如下所示:

hour = hour if AM_PM == 'AM' else hour + 12

根据我的计算,这比使用dict略快,但不是很多:

hour_shifter = {(0, 'AM'): 0, (0, 'PM'): 12,
                (1, 'AM'): 1, (1, 'PM'): 13,
                ...
                (11, 'AM'): 11, (11, 'PM'): 23,
                (12, 'AM'): 12}
hour = hour_shifter[(hour, AM_PM)]

现在您可以实例化datetime对象:

datetime.datetime(year, month, day, hour, minute, second)

答案 1 :(得分:0)

使用正则表达式怎么样?你能提供你的数据文件进行测试吗?

patt = re.compile(r'(?P<day>\d\d)-(?P<month>\w+)-(?P<year>\d\d)'
                  r' (?P<hour>\d{1,2}):(?P<minute>\d\d):(?P<second>\d\d)'
                  r' (?P<noon>\w\w) (?P<tz>\w+)')

for date in dates:
    res = patt.match(date)
    print(res.groupdict())

然后将日,月,年等转换为整数,创建时区对象:

from pytz import timezone
tz = timezone(res.groupdict()['tz'])

答案 2 :(得分:0)

首先,一些问题。

  1. 您将该小时显示为包含1个或2个字符。这一天也有所不同吗?或者总是2个字符?
  2. 你在做什么时区?把它扔掉?
  3. 你是如何处理看起来像是从1900年开始的岁月?您是否必须处理未来的日期?你确定48年是指1948而不是2048?
  4. 这是我会尝试的。首先构建一些年份和月份的查找字典。

    months = {'Jan': '01', 'Feb': '02', ... 'Dec': '12'} 
    years = {}
    for i in range(50, 100):
        years[str(i)] = '19' + str(i)
    for i in range(0, 50):
        years[str(i)] = '20' + str(i)
    

    遍历每条记录和

    1. 在空格处分割每个字符串
    2. 从日期字符串中提取日,月和年子字符串。从词典中查找年份和月份。按天使用。
    3. 从时间的小时部分中分割分钟和秒。分钟和秒钟的文本形式很好。
    4. 提取小时的整数值。如果拆分操作中的第3个字段为“PM”,则添加12,如有必要,请考虑案例。
    5. 将所有内容重新组合为目标格式。如果它只有一个字符,则用小时填充小时。
    6. 可能明智地测试年份字典是否优于将两位数年份转换为整数,检查值,并根据您选择的截止值添加1900或2000。我希望字典能够获胜,但很难说。

答案 3 :(得分:0)

假设&#34; 14&#34;在您的日期字符串中对应于2014:

import datetime

month_abbr = {'Jan':1, 'Feb':2, 'Mar':3, 'Apr':4, 'May':5,'Jun':6, 
              'Jul':7, 'Aug':8, 'Sep':9, 'Oct':10, 'Nov':11, 'Dec':12
              }   

def format_date(date_str):
    day, month, year = (date_str.split(' ')[0]).split('-')
    hour, minute, sec = (date_str.split(' ')[1]).split(':')
    return datetime.datetime(int(year)+2000, month_abbr[month], 
           int(day), int(hour), int(minute), int(sec))


date_str = '19-May-14 3:36:00 PM PDT'
#date_str = '19-May-14 10:37:00 PM PDT'
formatted_date = format_date(date_str)
print(formatted_date)
2014-05-19 03:36:00

datetime对象的默认格式为YYYY-MM-DD HH:MM:SS,因此在这种情况下您不需要指定唯一格式。如果您将来这样做,请查看datetime中的strftime功能。

如果&#34; 14&#34;可以在20世纪和2000年代之间切换,然后你需要(1)在摄取日期字符串之前知道这些信息,并且(2)调整上面的代码,以便在年份中添加1900或2000。