How to deal with time values over 24 hours in python? - python

I'm dealing with a large amount of data that has both values and times (in strings). I am converting the string time values into datetime values with the following code:
time = datetime.datetime.strptime(time, " %H:%M:%S.%f")
The only problem is that some of my data has the format: 24:00:00.004. So some of the data is actually over 24 hours
Python is giving me this error:
ValueError: time data ' 24:00:00:004' does not match format ' %H:%M:%S.%f'

The %H parameter can only parse values in the range 0-23. You'll have to manually deal with those specific time stamps:
try:
time = datetime.datetime.strptime(time, " %H:%M:%S.%f")
except ValueError:
time = time.replace(' 24', ' 23')
time = datetime.datetime.strptime(time, " %H:%M:%S.%f")
time += datetime.timedelta(hours=1)

Try parsing the hours separately:
hours, rest = time.split(':', 1)
time = datetime.timedelta(hours=int(hours)) + datetime.datetime.strptime(rest, "%M:%S.%f")

Seems like your data does not contain dates, but time spans, so you should maybe store your data as timedelta instead of datetime.
You can use this function to create a timedelta from your strings:
import re
from datetime import timedelta
def parseTimeDelta(s):
d = re.match(
r'((?P<days>\d+) days, )?(?P<hours>\d+):'
r'(?P<minutes>\d+):(?P<seconds>\d+)\.(?P<milliseconds>\d+)',
str(s)).groupdict(0)
return timedelta(**dict(( (key, int(value))
for key, value in d.items() )))
Parsing your time string '24:00:00.004' like this
>>>t = parseTimeDelta('24:00:00.04')
would result in a timedelta represented like this
>>> print t
1 day, 0:00:00.004000

Related

How to subtract 2 hours from time formatted as string [duplicate]

This question already has answers here:
Subtract hours and minutes from time
(3 answers)
Closed last year.
My initial string looks like following:
a1 = "06:00:00"
a2 = "01:00:00"
I want to set the time back by two hours.
How to get the following output (in string format)?
a1_new = "04:00:00"
a2_new = "23:00:00"
Here you go!
from datetime import datetime, timedelta
a1 = "06:00:00"
x = datetime.strptime(a1, "%H:%M:%S") - timedelta(hours=2, minutes=0)
y = x.strftime("%H:%M:%S")
print(y)
Steps:
Convert HMS into a DateTime Object
Minus 2 hours from this
Convert the result into a String that only contains Hour Minute & Second
from datetime import datetime
from datetime import timedelta
time_fmt = "%H:%M:%S"
a1_new = datetime.strptime(a1, time_fmt) - timedelta(hours = 2)
a1_new = a1_new.strftime("%H:%M:%S")
print(a1_new)
'08:00:00'
I am assuming here that you only need a simple 24-hour clock.
s = "01:00:00"
h, m, s = s.split(":")
new_hours = (int(h) - 2) % 24
result = ':'.join((str(new_hours).zfill(2), m, s))
convert to datetime:
import datetime
a1 = "06:00:00"
obj = datetime.datetime.strptime(a1,"%H:%M:%S")
obj.replace(hour=obj.hour-2) #hours = hours - 2
tostr = obj.hour+":"+obj.min+":"+obj.second
print(tostr)
If your strings are always going to follow that exact format and you don't want to use datetime, here's a different way to do it: You could split the strings by their colons to isolate the hours, then work on them that way before joining back to a string.
a1 = "06:00:00"
parts = a1.split(":") # split by colons
hour = (int(parts[0]) - 2) % 24 # isolate hour, convert to int, and subtract hours, and clamp to our 0-23 bounds
parts[0] = f"{hour:02}" # :02 in an f-string specifies that you want to zero-pad that string up to a maximum of 2 characters
a1_new = ":".join(parts) # rejoin string to get new time
If there's any uncertainty in the format of the string however, this completely falls apart.
Convert to datetime, subtract timedelta, convert to string.
from datetime import datetime, timedelta
olds = ["06:00:00", "01:00:00"]
objs = [datetime.strptime(t, "%H:%M:%S") - timedelta(hours=2) for t in olds]
news = [t.strftime("%H:%M:%S") for t in objs]
You can use datetime and benefit from the parameters of datetime.timedelta:
from datetime import datetime, timedelta
def subtime(t, **kwargs):
return (datetime.strptime(t, "%H:%M:%S") # convert to datetime
- timedelta(**kwargs) # subtract parameters passed to function
).strftime("%H:%M:%S") # format as text again
subtime('01:00:00', hours=2)
# '23:00:00'
subtime('01:00:00', hours=2, minutes=62)
# '21:58:00'

Python - Parsing string to timedelta when hours value is greater than 24

I am running a daily report and I'd like to keep a log of how long it takes to run each day.
I get a report_time timedelta object by calling datetime.datetime.now() at beginning and end and then getting the difference between the two values.
I have a text file that has two lines. Line 1 is today's run-time. Line 2 is total cumulative run time.
The issue is that when I try to parse Line 2 into a datetime.datetime object (to then create a timedelta object to add today's report time) it won't let me do so if the cumulative run time is over 24 hours (I guess because it no longer makes a valid date.
Any idea how to get around this (essentially parse a string into a time.delta object when it won't conform to a datetime.datetime format?
Code:
report_stats = f.read()
today_cumulative_reports_time = report_stats.splitlines()[0]
prev_total_reports_time = report_stats.splitlines()[1]
today_cumulative_reports_time = datetime.datetime.strptime(today_cumulative_reports_time,
'%H:%M:%S.%f')
today_cumulative_reports_time = datetime.timedelta(hours=today_cumulative_reports_time.hour,
minutes=today_cumulative_reports_time.minute,
seconds=today_cumulative_reports_time.second,
microseconds=today_cumulative_reports_time.microsecond)
prev_total_reports_time = datetime.datetime.strptime(prev_total_reports_time, '%H:%M:%S.%f')
prev_total_reports_time = datetime.timedelta(hours=prev_total_reports_time.hour,
minutes=prev_total_reports_time.minute,
seconds=prev_total_reports_time.second,
microseconds=prev_total_reports_time.microsecond)
cumulative_run_time = report_time + today_cumulative_reports_time + prev_total_reports_time
f.close()
Error:
ValueError: time data '24:54:03.294820' does not match format '%H:%M:%S.%f'
Manually parse the string and then construct the timedelta object:
from datetime import timedelta
time_string = '24:54:03.294820'
hours, minutes, seconds = map(float, time_string.split(':'))
t_delta = timedelta(hours=hours, minutes=minutes, seconds=seconds)
print(t_delta)
outputs
1 day, 0:54:03.294820

How to add a certain time to a datetime?

I want to add hours to a datetime and use:
date = date_object + datetime.timedelta(hours=6)
Now I want to add a time:
time='-7:00' (string) plus 4 hours.
I tried hours=time+4 but this doesn't work. I think I have to int the string like int(time) but this doesn't work either.
Better you parse your time like below and access datetime attributes for getting time components from the parsed datetime object
input_time = datetime.strptime(yourtimestring,'yourtimeformat')
input_seconds = input_time.second # for seconds
input_minutes = input_time.minute # for minutes
input_hours = input_time.hour # for hours
# Usage: input_time = datetime.strptime("07:00","%M:%S")
Rest you have datetime.timedelta method to compose the duration.
new_time = initial_datetime + datetime.timedelta(hours=input_hours,minutes=input_minutes,seconds=input_seconds)
See docs strptime
and datetime format
You need to convert to a datetime object in order to add timedelta to your current time, then return it back to just the time portion.
Using date.today() just uses the arbitrary current date and sets the time to the time you supply. This allows you to add over days and reset the clock to 00:00.
dt.time() prints out the result you were looking for.
from datetime import date, datetime, time, timedelta
dt = datetime.combine(date.today(), time(7, 00)) + timedelta(hours=4)
print dt.time()
Edit:
To get from a string time='7:00' to what you could split on the colon and then reference each.
this_time = this_time.split(':') # make it a list split at :
this_hour = this_time[0]
this_min = this_time[1]
Edit 2:
To put it all back together then:
from datetime import date, datetime, time, timedelta
this_time = '7:00'
this_time = this_time.split(':') # make it a list split at :
this_hour = int(this_time[0])
this_min = int(this_time[1])
dt = datetime.combine(date.today(), time(this_hour, this_min)) + timedelta(hours=4)
print dt.time()
If you already have a full date to use, as mentioned in the comments, you should convert it to a datetime using strptime. I think another answer walks through how to use it so I'm not going to put an example.

How to read timestamp from excel list in python

I am quite new to python and already struggling with an easy task like importing the timestamps of a series of measurement from an excel list.
The excel file has one column for date and one for time. I need the data for further calculation like time difference etc.
I tried to different ways how to get the data. So far my codes looks like this:
method with pyexcel
import pyexcel as pe
import datetime
import time
from datetime import time
import timestring
for n in range(len(users)):
sheet = pe.get_sheet(file_name=users[n],name_columns_by_row=0)
sheet = sheet.to_array()
data_meas = np.array(sheet)
for row in range(len(data_meas)):
print(type(row))
input_time = data_meas[row,1]
input_date = data_meas[row,0]
times = [datetime.datetime.strptime(input_date, input_time, "%d %b %Y %H:%M:%S")]
I get this error for the last line:
TypeError: strptime() takes exactly 2 arguments (3 given)
method with xlrd
import xlrd
from datetime import time
inputdata = xlrd.open_workbook('file.xls')
sheet = inputdata.sheet_by_index(0)
for row in sheet:
input_date=sheet.cell_value(row,0)
input_time=sheet.cell_value(row,1)
date_values = xlrd.xldate_as_tuple(input_time, inputdata.datemode)
time_value = time(*date_values[3:])
TypeError: 'Sheet' object is not iterable
Does anybody know how to help me?
I appreciate every hint.
Regarding your first solution, strptime takes only one date string as input.
You should join input_date and input_time:
input_time = '18:20:00'
input_date = 'Mon, 30 Nov 2015'
time = datetime.datetime.strptime(' '.join([input_date, input_time]), "%a, %d %b %Y %H:%M:%S")
To create the whole list of datetime objects, you can try:
times = [datetime.datetime.strptime(' '.join([data_meas[row,0], data_meas[row,1]]), "%a, %d %b %Y %H:%M:%S") for row in range(len(data_meas))]
Edit:
If you want to keep the for loop, you have to append each datetime object to your list (otherwise you will only keep the last date):
data_meas = np.array([['07/11/2015 18:20:00'],['09/11/2015 21:20:00']])
#list initilization
times = []
for row in range(len(data_meas)):
input_date = data_meas[row,0]
#we add a new item to our list
times.append(datetime.datetime.strptime(input_date, "%d/%m/%Y %H:%M:%S"))
Now, you can access each datetime in the list times. To calculate time differences, you can check the documentation on timedelta.
#Create a timedelta object
t1 = times[1] - times[0]
#Convert time difference in seconds
t2 = t1.total_seconds()

Convert timestamps of "yyyy-MM-dd'T'HH:mm:ss.SSSZ" format in Python

I have a log file with timestamps like "2012-05-12T13:04:35.347-07:00". I want to convert each timestamp into a number so that I sort them by ascending order based on time.
How can I do this in Python? In Java I found out that I can convert timestamps for such format with SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") but for Python I couldn't find anything.
As py2.x has issues with the %z directive you've to do something like this:
from datetime import timedelta,datetime
strs = "2012-05-12T13:04:35.347-07:00"
#replace the last ':' with an empty string, as python UTC offset format is +HHMM
strs = strs[::-1].replace(':','',1)[::-1]
As datetime.striptime doesn't supports %z(UTC offset)(at least not in py2.x), so you need a work around:
#Snippet taken from http://stackoverflow.com/a/526450/846892
try:
offset = int(strs[-5:])
except:
print "Error"
delta = timedelta(hours = offset / 100)
Now apply formatting to : '2012-05-12T13:04:35.347'
time = datetime.strptime(strs[:-5], "%Y-%m-%dT%H:%M:%S.%f")
time -= delta #reduce the delta from this time object
print time
#2012-05-12 20:04:35.347000

Categories