将字符串列表转换为日期时间

3

我正在尝试将一组字符串转换为日期时间。

以下是我处理的数据示例:
x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']

例如,列表应该反映出从59分58秒到1小时0分5秒的时间。

我知道这是一个奇怪的格式,但由于我手头只有这个,所以必须得处理。我不确定如何处理超过59分钟的值。

我尝试使用:

from datetime import datetime
for i in x:
    datetime_object = datetime.strptime(i, '%M:%S:%f')
    print(datetime_object)

我的结果是:

1900-01-01 00:59:55
1900-01-01 00:59:55
1900-01-01 00:59:58
1900-01-01 00:01:00.020000
1900-01-01 00:01:00.050000
1900-01-01 00:01:01.260000

我希望将输出保留为分钟和秒数。 例如,1:01:26 应该是 00:61:26
所以我期望的输出大致如下:
1900-01-01 00:59:55
1900-01-01 00:59:55
1900-01-01 00:59:58
1900-01-01 00:60:02
1900-01-01 00:60:02
1900-01-01 00:61:26


任何帮助或指导都将不胜感激!

1
可能是将字符串转换为日期时间的重复问题。 - VOL
2
一旦从%M:%S:%f转换为%H:%M:%S,是否保证不会返回到以前的格式? - Chris Hunt
1
你的数据含糊不清。@ChrisHunt提出了一个消除歧义的好主意。但需要回答他的问题。 - Stephen Rauch
你可以使用 timedelta 对象并使用 total_seconds() 方法来计算秒数、分钟数和小时数。 - alkasm
@ChrisHunt 数据将不会返回到先前的格式。 - Tommy
5个回答

2

datetime.datetime对象必须采用某个范围内的参数,即分钟必须在059之间。但是,您可以创建一个类来处理此所需行为。该类可以将输入转换为所需的时间戳格式,存储原始字符串,并提供一个to_date属性以检索实际时间戳作为datetime.datetime对象:

最初的回答:

import datetime

class Minutes:
  d = datetime.datetime.now()
  def __init__(self, _str, _year = None):
    self._val = _str
    d = datetime.datetime.now()
    self.year = _year if _year is not None else '-'.join(str(getattr(d, i)) for i in ['year', 'month', 'day'])
  @property
  def to_date(self):
    return datetime.datetime(*map(int, self.year.split('-')), *map(int, str(self).split(':')))
  def __str__(self):
    _h, _m, _s = map(int, self._val.split(':'))
    h, m, s = 0 if _h else _h, _m+(_h*60) if _h else _m, _s
    return f'{self.year} '+':'.join(str(i).zfill(2) for i in [h, m, s])
  def __repr__(self):
    return str(self)

x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']
new_x = [Minutes(i, '1900-01-01') for i in x]    

输出:

[1900-01-01 00:3595:00, 
 1900-01-01 00:3595:00, 
 1900-01-01 00:3598:00, 
 1900-01-01 00:60:02, 
 1900-01-01 00:60:05, 
 1900-01-01 00:61:26]

1
也许在这里使用 strptime 不是最合适的工具(为了简洁省略了一些错误检查):
def convert(s):
    parts = [int(i) for i in s.split(":")]

    if parts[0] < 3:  # 3 is arbitrary value, may need adaption
        # Assuming format hour:min:sec
        h, m, s = parts
        millis = 0
    else:
        # Assuming format min:sec:millisec
        m, s, millis = parts
        h = 0

    return "1900-01-01 00:{:02}:{:02}".format(h * 60 + m, s)


x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']

print(*(convert(i) for i in x), sep="\n")

输出:

1900-01-01 00:59:55
1900-01-01 00:59:55
1900-01-01 00:59:58
1900-01-01 00:60:02
1900-01-01 00:60:05
1900-01-01 00:61:26

1
你的列表包含时间段而不是具体时间。虽然datetime.timedelta专门用于此目的,但由于你需要一个非常特定的字符串格式进行输出,因此并不是必要的
你的输入数据存在格式的不一致性问题。如果你愿意为第一部分硬编码一个限制值,就可以通过三元语句应用一个切换:
from datetime import timedelta

x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']

def converter(value, limit=59):
    var1, var2, var3 = map(int, value.split(':'))
    switch = var1 < limit
    mins = var1 * 60 + var2 if switch else var1
    secs = var3 if switch else var2
    return f'00:{mins:02}:{secs:02}'

res = list(map(converter, x))

print(res)
# ['00:59:55', '00:59:55', '00:59:58', '00:60:02', '00:60:05', '00:61:26']

0
>>> time = datetime.datetime.now()
>>> halfformatted = time.strftime('00:{minutes}:%S.%f')
>>> minutes_total = time.hour * 60 + time.minute
>>> halfformatted.format(minutes=minutes_total)
'00:358:33.339341'

0

如果保证数据不会返回到以前的格式,我们可以对其进行规范化。为了保持代码整洁,最好将其封装在生成器中,这样就不会混淆主应用程序逻辑。例如:

def normalized(times):
    hms = False
    last_minute = 0
    for t in x:
        h, m, s = [int(i) for i in t.split(':')]
        if not hms:
            if h < last_minute:
                hms = True
            else:
                h, m, s = 0, h, m
                last_minute = m
        yield f'{h:02}:{m:02}:{s:02}'


x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']


for v in normalized(x):
    print(v)

结果为

00:59:55
00:59:55
00:59:58
01:00:02
01:00:05
01:01:26

现在在循环中,你可以做任何你想做的事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接