Reputation: 785
I am attempting to convert a list of strings to datetime.
Here is an example of the data I'm dealing with:
x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']
For example, the list is supposed to reflect 59 minutes, 58 seconds to 1 hour, 0 minutes and 5 seconds.
I understand this is a wacky format, but I'm playing with the hand I've been dealt. I'm not sure how to handle the data once I get into values that are greater than 59 minutes.
I tried using:
from datetime import datetime
for i in x:
datetime_object = datetime.strptime(i, '%M:%S:%f')
print(datetime_object)
My results are:
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
I would like to keep my output to minutes and seconds.
For example 1:01:26
would be 00:61:26
So my desired output would look something like:
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
Any help or guidance is greatly appreciated!
Upvotes: 3
Views: 3008
Reputation: 164623
Your list contains durations rather than times. datetime.timedelta
is designed for this purpose, but isn't necessary given you want a very specific string format for output.
The problem with your input data is the inconsistency of formatting. If you are willing to hard-code a limiting value for the first part, you can apply a toggle via ternary statements:
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']
Upvotes: 1
Reputation: 71451
datetime.datetime
objects must take parameters that are within a certain range i.e minutes must be between 0
and 59
. However, you can create a class to handle this desired behavior. The class can convert the input into the desired timestamp format, store the original string, and provide a to_date
property to retrieve the actual timestamp as a datetime.datetime
object:
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]
Output:
[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]
Upvotes: 2
Reputation: 4030
Given the guarantee that the data will not go back to the previous format, we can normalize it. To keep things clean this is probably better wrapped in a generator so it doesn't clutter your main application logic. For example:
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)
results in
00:59:55
00:59:55
00:59:58
01:00:02
01:00:05
01:01:26
Now in the loop you can do whatever you want.
Upvotes: 0
Reputation: 10959
Maybe strptime
isn't the right tool here (some error checking omitted for brevity):
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")
Output:
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
Upvotes: 1
Reputation: 327
>>> 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'
Upvotes: 0